Pregunta

Encontré el código de la red en el que no puedo entender esta línea: -

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

Allí Scan0 es System.IntPtr. Es el código de C # .Net. Por favor, explique la línea de arriba.

El código completo se proporciona a continuación. Este es el código para convertir una imagen en escala de grises.

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;
    }

Entiendo todo el código pero solo tengo el problema en esta línea.

<*>
¿Fue útil?

Solución

Primero convierte el IntPtr en un puntero void . Luego a un puntero byte . Este es el código inseguro .

Más sobre código inseguro: http://msdn.microsoft.com/en-us /library/aa288474%28VS.71%29.aspx

Como señala Robert Harvey, un puntero es una ubicación de memoria. En C / C ++, las matrices están estrechamente relacionadas con este concepto. Cuando hace corchetes, básicamente está ajustando la dirección.

Otros consejos

Su pregunta suena como si estuviera preguntando qué está haciendo el código, pero en base a algunos de sus comentarios, creo que está buscando por qué está emitiendo primero a un puntero nulo.

Probablemente esté confundido aquí porque no hay razón para lanzar Scan0 primero a un vacío *. La conversión al byte * funcionaría igual de bien.

IntPtr tiene un operador explícito (void *) que permite convertir a void *. Si intenta transmitir directamente desde IntPtr a otra cosa, el compilador vomitará porque solo se define la conversión void * para la clase IntPtr. Vea también IntPtr :: ToPointer ().

El compilador permite la conversión de void * a byte * porque en este punto, si no sabe lo que está haciendo, ya está en problemas.

Parece extraño, pero entonces no conozco C # tan bien. puede ser que hay algún problema al enviar un System.IntPtr directamente a un byte * , pero no con System.IntPtr a void * o void * a byte * .

El resultado final es probablemente el mismo que si lanza int * a char * en C: la capacidad de quitar la defensa de p para obtener un solo byte del entero (suponiendo que CHAR_BIT es 8 en la implementación de C).

Consulte este tutorial sobre código inseguro. Explicará qué significa la línea de código y cómo se puede usar para otros tipos además del byte:

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

Esencialmente, el código inseguro le permite usar punteros de estilo C.

¿Sería posible que necesite convertir a void para evitar que el objeto ejecute algún código de auto-conversión en él?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top