Trying to Understand this Image function

165 views Asked by At
private void ReadImage()
    {
        int i, j;
        GreyImage = new int[Width, Height];  //[Row,Column]
        Bitmap image = Obj;
        BitmapData bitmapData1 = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
                                 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        unsafe
        {
            byte* imagePointer1 = (byte*)bitmapData1.Scan0;

            for (i = 0; i < bitmapData1.Height; i++)
            {
                for (j = 0; j < bitmapData1.Width; j++)
                {
                    GreyImage[j, i] = (int)((imagePointer1[0] + imagePointer1[1] + imagePointer1[2]) / 3.0);
                    //4 bytes per pixel
                    imagePointer1 += 4;
                }//end for j
                //4 bytes per pixel
                imagePointer1 += bitmapData1.Stride - (bitmapData1.Width * 4);
            }//end for i
        }//end unsafe
        image.UnlockBits(bitmapData1);
        return;
    }

the line GreyImage[j,i] = (int)((imagePointer1[0] ..... seems to be reading into the byte* like an array, obviously I can't assign an unsafe bit of code to an array for later processing, so i thought maybe just assign those 4 bytes to the array.

How do you assign those 4 bytes to the array?

i thought by doing:

var imageData = new byte[Width, Height][];
imageData[x,y] = pixelSet //basically byte[];
2

There are 2 answers

2
drankin2112 On BEST ANSWER

I think you are trying to do something like this. Obviously, I haven't tested this code but it will get you in the direction you want.

byte[] save = new byte[4];
Array.Copy(*imagePointer1, save, 4);

OR

byte[] save = new byte[4];
save[0] = bitmapData1.Scan0[0];
save[1] = *(imagePointer1 + 1);
save[2] = *(imagePointer1 + 2);
save[3] = *(imagePointer1 + 3);

A pointer to an array always points to element zero. You can access other elements by adding to the pointer or incrementing the pointer.

 (imagePointer1 + 5)  // pointer to 5th element
*(imagePointer1 + 5)  // value of 5th element
  imagePointer1 += 5; // imagePointer1 now starts at element 5

Plus and minus move the pointer reference by the number of bytes that make up the sizeof the array's data type. If it was an int[], + and - would move the pointer in increments of 4 bytes.

3
ppetrov On

The function should transform your image into a greyscale one, and store the color values into the GreyScale array. But there is an error in this function (actually 2).

First of all, you only read the upper-left pixel of your image, instead you should use this:

GreyImage[j, i] = (int)((imagePointer1[j * 4 + i * bitmapData1.Width * 4] + imagePointer1[j * 4 + i * bitmapData1.Width * 4 + 1] + imagePointer1[j * 4 + i * bitmapData1.Width * 4 + 2]) / 3.0);

The other thing is that all colors aren't "equal" when you transform your image, you can find the usual factors applied to the red, green and blue channels to transform to the greyscale quite easily on google.

And to answer your question, the way it's done in your function to assign the value to your array is correct.

EDIT

To answer you comments:

In the brackets [] I calculate the offset in the array where the color information about the pixel at coordinates (j, i) are. (btw we usually use i for x and j for y, here it's the opposite)

Say you want to know the color values of the pixel at coordinates x = 2, y = 4, you'll need to use the following formula:

color = y * <number of bytes per line> + x

Since your image is a 32 bits one, with the formula above you'll get the red value of the color. If you want the green one you add 1, for the blue you add 2.

In the piece of code I posted, I assume each line take exactly width * 4 bytes, this is true most of the time for 32 bit images, but not always, so it's best to use this formula actually:

[imagePointer[i * bitmapData1.Stride + j]