0

I'm trying to create some basic image process program, and if I go throw the image with two for loops, then that's very slow, so, I tried with Parallel. For but, with that, I have to lock the image or copy to the temporary image in each loop, which is also not so fast, or even worst than a single for. So I thinking about, how can I copy just a row of an image, process it, and copy it back into the image, or, what is the best/better, and not so complicated method for this?

Easiest example: creating an inverse/negate image:

                for (int i = 0; i < image.Height; i++)
                    for (int j = 0; j < image.Width; j++)
                    {
                        System.Drawing.Color c = image.GetPixel(j, i);
                        c = Color.FromArgb(255 - c.R, 255 - c.G, 255 - c.B);
                        image.SetPixel(j, i, c);
                    }

Thanks, for it!


UPDATE:

Here is a basic example of how to do it:

Bitmap image = new Bitmap(pictureBox.Image);
BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat); //reserve an area in memory which is equal to the image
int height = bitmapData.Height;
int bPP = System.Drawing.Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; //pixels/byte
int width = bitmapData.Width*bPP;

unsafe //because of c# doesn't support well pointers
{
    byte* firstPixel = (byte*)bitmapData.Scan0; //the fst pixel of the reserved area
    Parallel.For(0, height, j => 
    {
        byte* line = firstPixel + (j * bitmapData.Stride); //iterate row by row from the fst pixel
        for (int i = 0; i < width; i= i + bPP)//one pixel is 3 element in a row, in  BGR order
        {
            int oldB = line[i];
            int oldG = line[i+1];
            int oldR = line[i+2];

            line[i] = (byte) oldB;
            line[i + 1] = (byte) oldG;
            line[i + 2] = (byte) oldR;
        }
    });
    image.UnlockBits(bitmapData);
}

pictureBox.Image = image;
gabor aron
  • 390
  • 2
  • 3
  • 15
  • Thanks, @Martheen this is interesting, and maybe is faster, and some good advice is in that answer, but not solving the parallelization problem. I can't use even `Parallel.For` if I have to `lock` in each loop. – gabor aron Apr 09 '21 at 03:02
  • 1
    I'd suggest using `LockBits`, get the image data as an array of bytes, you can access that in parallel (so long as you don't manipulate the same array entry from two threads at the same time), and then convert it back into an image. – ProgrammingLlama Apr 09 '21 at 03:05
  • "maybe"? I've been in your position, all the parallelism in the world can't beat simply lockbit the whole array, it's the difference between blink-of-an-eye 3 MP filter processing and seconds of waiting. – Martheen Apr 09 '21 at 03:07
  • @Llama Can you give me a basic example? – gabor aron Apr 09 '21 at 03:08
  • 2
    [Example in the question linked by Martheen](https://stackoverflow.com/a/49664605/3181933). – ProgrammingLlama Apr 09 '21 at 03:09
  • [Examples a plenty](https://stackoverflow.com/search?q=user%3A3152130+lockbits) - For a simple inversion a [ColorMatrix](https://stackoverflow.com/search?q=user%3A3152130+colormatrix) may be even better.. – TaW Apr 09 '21 at 07:55

0 Answers0