views:

616

answers:

6

I found the code from the net in which i cant understand this line:-

byte* p = (byte*)(void*)Scan0;

There Scan0 is System.IntPtr. It is code of C#.Net. Plz Explain the above line.

The complete code is given below. this is code to convert a image in grayscale.

public static Image GrayScale(Bitmap b)
    {

        BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

        int stride = bmData.Stride;
        System.IntPtr Scan0 = bmData.Scan0;

        unsafe
        {
            byte* p = (byte*)(void*)Scan0;

            int nOffset = stride - b.Width * 3;

            byte red, green, blue;

            for (int y = 0; y < b.Height; ++y)
            {
                for (int x = 0; x < b.Width; ++x)
                {
                    blue = p[0];
                    green = p[1];
                    red = p[2];

                    p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);

                    p += 3;
                }
                p += nOffset;
            }
        }

        b.UnlockBits(bmData);

        return (Image)b;
    }

I understand all the code but only have the problem on this line.

byte* p = (byte*)(void*)Scan0;
+4  A: 

First converts the IntPtr to a void pointer. Then to a byte pointer. This is unsafe code.

More on unsafe code: http://msdn.microsoft.com/en-us/library/aa288474%28VS.71%29.aspx

As Robert Harvey notes, a pointer is a memory location. In C/C++ arrays are closely tied to this concept. When it does the square brackets, its basically is adjusting the address.

Daniel A. White
Thanks sir, I understand the concept of pointers and unsafe code. Can you give some more explanation about void pointers.
qulzam
A void pointer is, in a very rudimentary way, a pointer to NO SPECIFIC TYPE. So, you get a pointer to an address that doesn't reference any type, simply the data at that address. Then, you are free to cast it to whatever you like. In this example, they cast an Int to a void (nothing). The void pointer (a raw memory address) is then cast to the address of a byte. (Good lord, it's been forever since I worked with this. Someone please correct me if I'm wrong.)
Mike Hofer
+1  A: 

It looks bizarre but then I don't know C# that well. It may be that there's some problem with casting a System.IntPtr directly to a byte*, but not with System.IntPtr to void* or void* to byte*.

The end result is probably the same as if you cast int* to char* in C: the ability to derefence p to get a single byte of the integer (assuming CHAR_BIT is 8 in the C implementation).

paxdiablo
+1  A: 

Check out this tutorial on unsafe code. It will explain what the line of code means, and how it can be used for other types besides byte:

http://msdn.microsoft.com/en-us/library/aa288474(VS.71).aspx

Essentially, unsafe code allows you to use c-style pointers.

Robert Harvey
i understand the unsafe code, but there is some confusion that what is meaning of (byte*)(void*)
qulzam
+3  A: 

Your question sounds as if you are asking what the code is doing, but based on some of your comments I think you are after why it is casting first to a void pointer.

You are likely confused here because there is no reason to be casting Scan0 first to a void*. The cast to byte* would work just as well.

Ed Swangren
A: 

Would it be possible that you need to cast to void to avoid the object from executing some self-cast code on it?

ChaosCoder
+2  A: 

IntPtr has an explicit operator (void*) that allows casting to void*. If you try to cast directly from IntPtr to something else the compiler will barf because only the void* cast is defined for the IntPtr class. See also IntPtr::ToPointer( ).

Casting from void* to byte* is allowed by the compiler because at this point if you don't know what you're doing you're already in trouble.

charlie chaplin