Domanda

Ho trovato il codice dalla rete in cui non riesco a capire questa riga: -

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

Qui Scan0 è System.IntPtr. È il codice di C # .Net. Plz Spiega la riga sopra.

Il codice completo è riportato di seguito. questo è il codice per convertire un'immagine in scala di grigi.

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

Comprendo tutto il codice ma ho solo il problema su questa riga.

<*>
È stato utile?

Soluzione

Innanzitutto converte IntPtr in un puntatore void . Quindi a un puntatore byte . Questo è unsafe code.

Altre informazioni sul codice non sicuro: http://msdn.microsoft.com/en-us /library/aa288474%28VS.71%29.aspx

Come osserva Robert Harvey, un puntatore è una posizione di memoria. In C / C ++ gli array sono strettamente legati a questo concetto. Quando fa le parentesi quadre, sostanzialmente sta regolando l'indirizzo.

Altri suggerimenti

La tua domanda sembra che stai chiedendo a cosa il codice sta facendo, ma sulla base di alcuni dei tuoi commenti penso che tu stia cercando perché sta lanciando prima un puntatore vuoto.

Probabilmente sei confuso qui perché non c'è motivo di lanciare Scan0 prima su un vuoto *. Il cast in byte * funzionerebbe altrettanto bene.

IntPtr ha un operatore esplicito (void *) che consente di annullare il casting *. Se si tenta di eseguire il cast direttamente da IntPtr a qualcos'altro, il compilatore noterà perché solo il cast void * è definito per la classe IntPtr. Vedi anche IntPtr :: ToPointer ().

Il cast da void * a byte * è consentito dal compilatore perché a questo punto se non sai cosa stai facendo sei già nei guai.

Sembra bizzarro ma poi non conosco C # così bene. potrebbe essere che c'è qualche problema con il casting di un System.IntPtr direttamente in un byte * , ma non con System.IntPtr in void * o void * in byte * .

Il risultato finale è probabilmente lo stesso che se si lancia int * in char * in C: la capacità di derefence p per ottenere un singolo byte dell'intero (supponendo che CHAR_BIT sia 8 nell'implementazione C).

Dai un'occhiata a questo tutorial su un codice non sicuro. Spiegherà cosa significa la riga di codice e come può essere utilizzata per altri tipi oltre a byte:

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

In sostanza, il codice non sicuro ti consente di utilizzare i puntatori di tipo c.

Sarebbe possibile che tu debba eseguire il cast su void per evitare che l'oggetto esegua del codice di auto-cast su di esso?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top