英文:
SkiaSharp SKbitmap.GetPixel and SKbitmap.SetPixel - improve performance
问题
I am trying to use C# and SkiaSharp to implement image processing.
The code below is trying to implement edge detection.
The result of the code below is quite good, it needs improving, but this is not my point:
canvas.Clear(SKColors.White);
// USerskbitmapNEW has been loaded earlier.
SKBitmap image = new SKBitmap(USerskbitmapNEW.Width, USerskbitmapNEW.Height);
for (int i = 0; i < image.Width; i++)
{
for (int j = 0; j < image.Height; j++)
{
SKColor c1 = USerskbitmapNEW.GetPixel(i, j - 1);
SKColor c2 = USerskbitmapNEW.GetPixel(i, j + 1);
int xval = 0;
int yval = 0;
xval = (int)(c1.Red * .3 + c2.Blue * 0.11 - (c2.Red * .3));
yval = (int)(c2.Red * .3 + c2.Green * .29 + c2.Blue * 0.11);
if (xval > yval )
{
SKColor c = SKColors.Black;
image.SetPixel(i, j, c);
}
}
}
canvas.DrawBitmap(image, myframe);
My problem is that the methods: SKBitmap.GetPixel(i, j); and SKBitmap.SetPixel(i, j, color); are extremely slow when used with images larger than 200kb in size.
In contrast to the above methods (.GetPixel, .SetPixel), when you apply various filters to the image, for example, var cf = SKColorFilter.CreateTable(null, null, colorTable, colorTable); ...
, SkiaSharp is very fast.
My question: Is there any other way, using SkiaSharp, to read and modify pixels of the image with better performance than the methods I described?
Thanks in advance,
Michalis
英文:
I am trying to use C# and SkiaSharp to implement image processing.
The code below is trying to implement edge detection.
The result of the code below is quite good, it needs improving, but this is not my point:
canvas.Clear(SKColors.White);
// USerskbitmapNEW has been loaded earlier.
SKBitmap image = new SKBitmap(USerskbitmapNEW.Width, USerskbitmapNEW.Height);
for (int i = 0; i < image.Width; i++)
{
for (int j = 0; j < image.Height; j++)
{
SKColor c1 = USerskbitmapNEW.GetPixel(i, j - 1);
SKColor c2 = USerskbitmapNEW.GetPixel(i, j + 1);
int xval = 0;
int yval = 0;
xval = (int)(c1.Red * .3 + c2.Blue * 0.11 - (c2.Red * .3));
yval = (int)(c2.Red * .3 + c2.Green * .29 + c2.Blue * 0.11);
if (xval > yval )
{
SKColor c = SKColors.Black;
image.SetPixel(i, j, c);
}
}
}
canvas.DrawBitmap(image, myframe);
My problem is that the methods : SKbitmap.GetPixel(i, j); and SKbitmap.SetPixel(i, j, color); are extremely slow when use them with images bigger than 200kb size.
In contrast to the above methods( .GetPixel .SetPixel) , when you apply image various filters , for example , var cf = SKColorFilter.CreateTable(null, null, colorTable, colorTable); ....
skiasharp is very fast.
My question: is there any other way, using skiasharp, to read and modify pixels of the image, with better performance than the methods I described?
Thanks in advance
Michalis
答案1
得分: 1
请忘记 GetPixel
/SetPixel
方法,如果你想直接访问像素数据。
首先,你可以使用 SKBitmap
的 GetPixels
方法直接访问像素数据:
IntPtr pixelsPtr = image.GetPixels();
然后,在 unsafe
上下文中,你可以快速操作数据(你需要手动计算像素偏移,以及通过 uint 或字节值设置颜色)。
unsafe
{
var unsafePtr = (uint*)pixelsPtr.ToPointer();
for (int y = 1; y < image.Height - 1; y++)
{
var rowOffset = y * image.Width;
for (int x = 0; x < image.Width; x++)
{
uint c1 = unsafePtr[rowOffset - image.Width + x];
uint c2 = unsafePtr[rowOffset + image.Width + x];
// 现在你应该有 c1/c2 uints 代表 RGBA 像素数据
// 你可以对它们进行操作并通过 unsafePtr 存储回去
// ...
}
}
}
我不会为你重新编写整个逻辑,我可以看到还有一个问题,你实时更改像素颜色,所以在 (x, y) 坐标设置黑色将导致在像素 (x, y + 1) 处出现错误的计算。
英文:
You need to forget about GetPixel
/SetPixel
methods if you want to have direct access to pixels.
For starters, you access pixel data directly for SKBitmap
using GetPixels
method:
IntPtr pixelsPtr = image.GetPixels();
Then, in unsafe
context, you can manipulate the data quickly (you need to calculate pixel offset manually, as well as setting colors via uint or byte values).
unsafe
{
var unsafePtr = (uint*)pixelsPtr.ToPointer();
for (int y = 1; y < image.Height - 1; y++)
{
var rowOffset = y * image.Width;
for (int x = 0; x < image.Width; x++)
{
uint c1 = unsafePtr [rowOffset - image.Width + x];
uint c2 = unsafePtr [rowOffset + image.Width + x];
// now you should have c1/c2 uints representing RGBA pixel data
// you can manipulate those and store back via unsafePtr
...
}
}
}
I will not rewrite the whole logic for you, I can see there is also a problem that you change the pixel colors on the fly, so setting a black color at (x, y) coordinates will cause false calculation at pixel (x, y + 1)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论