Comprensione C # Bitmap e BitmapData

C Bitmap Bitmapdata Understanding



Molte attività di elaborazione delle immagini sono le conversioni del tipo di file più semplici, come la conversione del formato da profondità a 32 bit a profondità a 8 bit e l'accesso diretto agli array di pixel è molto più efficiente rispetto all'utilizzo di GetPixel e SetPixel.

Potresti scoprire che DotNet utilizza un meccanismo di hosting e nella maggior parte dei casi Microsoft consiglia di utilizzare codice gestito per motivi convenienti e sicuri. In pratica, è raro manipolare direttamente i blocchi di dati in memoria. Tuttavia, l'elaborazione delle immagini è solo uno dei pochi casi, perché l'inefficienza dell'utilizzo del codice gestito è insopportabile, soprattutto per quantità enormi. Per il bene delle immagini, qui discutiamo un nuovo approccio.



La modalità di utilizzo del codice non gestito dipende dalla lingua. In C #, possiamo chiamare il puntatore tramite la parola chiave unsafe per manipolare direttamente i dati bitmap in memoria. VB utilizza il metodo nella classe Marshal, che causerà alcune prestazioni. Perdita, quindi l'efficienza non è buona come la prima.



Blocca bitstream

La classe Bitmap utilizza i metodi LockBits e UnLockBits per archiviare in memoria la matrice di dati della bitmap.Operateci direttamenteInfine, i dati modificati vengono utilizzati per sostituire i dati originali nella bitmap. LockBits restituisce la posizione e la distribuzione dei dati descritti nella matrice bloccata con la classe di ogni BitmapData.



La classe BitmapData include le seguenti importanti proprietà:

  • Scan0: l'indirizzo della matrice di dati in memoria.
  • Stride: la larghezza della linea nella matrice di dati, in byte. Può espandere alcuni byte, che verranno introdotti in seguito.
  • PixelFormat: il formato pixel, importante per il posizionamento dei byte nella matrice.
  • Larghezza: la larghezza della bitmap.
  • Altezza: l'altezza della bitmap.
    La relazione specifica è mostrata nella figura seguente:
    Immagine

Come mostrato in FIG, L'attributo stride rappresenta la larghezza della linea della matrice di dati bitmapIn byte . Per motivi di efficienza, la larghezza della linea della matrice non è esattamente un multiplo intero del numero di pixel per linea e il sistema tende a incapsularla in multipli interi di quattro. Ad esempio, per un'immagine larga 17 pixel e profonda 24 bit, l'attributo stride è 52 la quantità di dati per riga è 17 3 = 51, il sistema incapsula automaticamente un byte, quindi il suo passo è di 52 byte (o 13 4 byte). Per una mappa indice a 4 bit di 17 pixel di larghezza, il passo è 12, di cui 9 byte (esattamente 8,5 byte) vengono utilizzati per registrare le informazioni sui dati, e ogni riga viene automaticamente aggiunta con 3 (3,5) byte per garantire che sia 4. Multiplo intero.
La distribuzione di dati specifici varia a seconda del formato dei pixel. Un'immagine profonda a 24 bit contiene una serie di informazioni RGB ogni 3 byte un'immagine profonda a 32 bit contiene una serie di informazioni RGBA ogni 4 byte. I formati pixel che contengono più pixel per byte, come immagini indicizzate a 4 bit o immagini indicizzate a 1 bit, devono essere elaborati con attenzione per garantire che i byte adiacenti nello stesso byte non vengano confusi.
posizionamento accurato dei puntatori
RGB a 32 bit: supponendo che X e Y siano le coordinate del pixel nella bitmap, il suo indirizzo in memoria è scan0 + Y falcata + X 4. A questo punto il puntatore punta al blu, seguito dai componenti verde, rosso e alfa.
RGB a 24 bit: scansione 0 + Y falcata + X 3. Il puntatore ora punta al blu, seguito dal verde e dal rosso.
Indice a 8 bit: scan0 + Y Stride + X. Il puntatore corrente punta alla tavolozza dell'immagine.
Indice a 4 bit: scan0 + Y
Passo + (X / 2). Il byte puntato dal puntatore corrente include due pixel e la ruota dei colori a 16 toni è indicizzata dai bit superiore e inferiore, dove il bit superiore rappresenta il pixel sinistro e il bit inferiore rappresenta il pixel destro.
Indice a 1 bit: scan0 + Y * stride + X / 8. Ogni bit nel byte puntato dal puntatore corrente rappresenta il colore dell'indice di un pixel, la tavolozza è di due colori, il pixel più a sinistra è 8 e il pixel più a destra è zero.
utilizzando iteratori tra i pixel
L'esempio seguente imposta il componente blu di tutti i pixel in un'immagine profonda a 32 bit al massimo (255):
BitmapData bmd = bm.LockBits (new Rectangle (0, 0, 10, 10), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat)
int PixelSize = 4

for(int y=0 y > 1) byte currentByte = ((byte *)bmd.Scan0)[offset] if((x&1) == 1) currentByte &= 0xF0 currentByte else currentByte &= 0x0F currentByte ((byte *)bmd.Scan0)[offset]=currentByte Handling the code for a 1-bit index: byte* p=(byte*)bmd.Scan0.ToPointer() int index=y*bmd.Stride+(x>>3) byte mask=(byte)(0x80>>(x&0x7)) if(pixel) p[index]|=mask else p[index]&=(byte)(mask^0xff) Finally, after all the processing is done, don't forget to use the Unlockbits command to unlock.