1

Today I wanted to try sth new in image processing in C#.

Szenario as following: I have two black and white images. Now I want to get all white pixels (x,y) from both images and put them into a return image. So in the end my image3 contains all white pixels from image1 and image2. I'm using unsafe pointers as they are faster.

So in the code I check if image1 in (x,y) == image2 in (x,y) as it is very unlikely that both pictures have a white pixel at the same spot

My approach right now:

private unsafe static Bitmap combine_img(Bitmap img1, Bitmap img2)
    {
        Bitmap retBitmap = img1;

        int width = img1.Width;
        int height = img1.Height;
        BitmapData image1 = retBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        BitmapData image2 = img2.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // here an error

        byte* scan1 = (byte*)image1.Scan0.ToPointer();
        int stride1 = image1.Stride;

        byte* scan2 = (byte*)image2.Scan0.ToPointer();
        int stride2 = image2.Stride;

        for (int y = 0; y < height; y++)
        {
            byte* row1 = scan1 + (y * stride1);
            byte* row2 = scan2 + (y * stride2);

            for (int x = 0; x < width; x++)
            {
                if (row1[x] == row2[x])
                    row1[x] = 255;
            }
        }

        img1.UnlockBits(image1);
        img2.UnlockBits(image2);

        return retBitmap;
    }

unfortunately it returns an error when trying to lock the second image, saying the image has already been locked!

user3079834
  • 2,009
  • 2
  • 31
  • 63
  • That would be no surprise if you are passing the same image on both parameters. Even if that's not the case, you should add code that verifies that the images are the same, an if they are handle that case properly; otherwise continue as usual. – Theraot Dec 08 '13 at 13:07
  • 1
    Just swap the two LockBits statements. If it now complains about retBitmap being locked then they really do refer to the same bitmap data. If not then it is locked elsewhere. UnlockBits() belongs in a finally { block }. – Hans Passant Dec 08 '13 at 14:34

2 Answers2

1

The problem was, that strangely I did pass the same image, here the corrected Code:

private unsafe static void combine_img(Bitmap img1, Bitmap img2)
    {
        BitmapData image1 = img1.LockBits(new Rectangle(0, 0, img1.Width, img1.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        BitmapData image2 = img2.LockBits(new Rectangle(0, 0, img2.Width, img2.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

        int bytesPerPixel = 3;

        byte* scan1 = (byte*)image1.Scan0.ToPointer();
        int stride1 = image1.Stride;

        byte* scan2 = (byte*)image2.Scan0.ToPointer();
        int stride2 = image2.Stride;

        for (int y = 0; y < img1.Height; y++)
        {
            byte* row1 = scan1 + (y * stride1);
            byte* row2 = scan2 + (y * stride2);

            for (int x = 0; x < img1.Width; x++)
            {
                if (row2[x * bytesPerPixel] == 255)
                    row1[x * bytesPerPixel] = row1[x * bytesPerPixel - 1] = row1[x * bytesPerPixel-2] = 255;
            }
        }
        img1.UnlockBits(image1);
        img2.UnlockBits(image2);
    }
user3079834
  • 2,009
  • 2
  • 31
  • 63
0

I guess your second image is not 24 bit image. Mayber try something like:

BitmapData image2 = img2.LockBits(new Rectangle(0, 0, img2.Width, img2.Height), ImageLockMode.ReadWrite, img2.PixelFormat);

In this case you will always pass this line (I assume), but problem is you wont know you are actually dealing with 24 bits image or 32 bits image.