Question

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;
Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

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).

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.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top