Italiano - English

Reading from file and fast access to image pixels with C#

Translation for this document is not available or is not complete,
if you are intrested to receive information please write to

This page describes how to use Image::FromFile methods to read image form file and howto gain fast access to its pixel using Bitmap::LockBits in VisualStudio. Example code and performance test are shown. Finally, above performace are compared to C++ native CBitmap class.

Lettura di una immagine in un buffer di memoria usando librerie standard C#

La lettura di una immagine in memoria è una operazione molto semplice con Visual C#. Infatti è disponibile la classe System::Drawing::Image che dispone di tutte le funzioni necessarie tra cui i metodi FromFile o FromStream che restituiscono un oggetto Bitmap.

Benché i due metodi operino in modo simile, il metodo FromStream è estremamente più veloce di FromFile. In entrambi i casi si tratta di operazioni molto semplici, segue il codice di esempio.

Lettura di una immagine con FromFile

 
using namespace System::Drawing;
 
// dichiaro un oggetto bitmap 
Bitmap^ bmp;
 
// Leggo l'immagine dal file
bmp = (Bitmap^)Image::FromFile("Test.bmp");
 

Lettura di una immagine con FromStream

 
using namespace System::IO;
using namespace System::Drawing;
 //creo un file stream sul file dell'immagine 
FileStream^ fs = gcnew FileStream("Test.bmp",FileMode::Open,FileAccess::Read);
 
//Leggo immagine dallo stream
bmp = (Bitmap^)Image::FromStream(fs,true,false);
 

La differenza di prestazioni è dovuta alla convalida dei dati dell'immagine operata automaticamente dal metodo FromFile e opzionale per il metodo FromStream (3^ parametro validateImageData:false).

Non è chiaro che tipo di validazione venga eseguita e pare che si tratti di un un bug di sulla funzione di validazione in MS Visual Studio .NET 2003.

FIX: Slow performance when you call System.Drawing.Image.FromStream to load a bitmap image: http://support.microsoft.com/kb/831419

Accesso ai Pixel di una immagine

Per accedere ai singoli pixel dell'immagine, il metodo Bitmap::GetPixel(col,row) è estremamente lento e per un accesso diretto e rapido alla memoria della immagine è consigliabile utilizzare la tecnica LockBits.

Accesso alla memoria di una immagine con LockBits

Lo scopo è ottenere un puntatore ad una matrice di memoria che contiene le informazioni sui pixel dell'immagine.

Il metodo Bitmap::LockBits ritorna on oggetto tipo Imaging::BitmapData che specifica gli attributi di un'immagine bitmap e permette l'accesso diretto alla memoria della immagine stessa. Quindi il metodo Imaging::BitmapData::Scan0 ritorna un puntatore al primo pixel selezionato con LockBits.

 
// Selezione del formato desiderato 
Imaging::PixelFormat pxf =Imaging::PixelFormat::Format24bppRgb;
 
// Selezione Region Of Interest (ROI), ad esempio intera immagine
Drawing::Rectangle rect = Drawing::Rectangle(0, 0, bmp->Width, bmp->Height);
 
// Creazione oggetto BitmapData 
Imaging::BitmapData^ bmpData  =  
    bmp->LockBits(rect, Imaging::ImageLockMode::ReadOnly,pxf);
 
// Puntatore al primo pixel nella ROI selezionata  
unsigned char * imgdata = (unsigned char*)bmpData->Scan0.ToPointer();
 
...operazioni sull'immagine... 
 
// IMPORTANTE Unlock al termine delle operazioni
bmp->UnlockBits(bmpData);

Organizzazione di una immagine RGB in memoria ottenuta con LockBits

Ottenuto il puntatore, l'accesso alla memoria dell'immagine è molto semplice e può essere fatto con le normali operazioni di accesso ad array, tenendo presente che:

  • I pixel sono organizzati in sequenza BGR in caso di formato 24bit o BGRA in caso di formato 32bit. Ogni canale richiede 1 byte
  • La memoria è allineata a 4 byte: questo vuol dire che la matrice di memoria ha un numero di colonne multiplo di 4. La proprietà Stride fornisce la larghezza della matrice. La larghezza della matrice è sempre maggiore o uguale a quella strettamente necessaria.
  • Il segno di Stride indica il verso dell'immagine.
    • Stride > 0: L'immagine in memoria corrisponde all'originale quindi, la prima riga della matrice è la prima riga dell'immagine ecc..
    • Stride < 0: L'immagine in memoria è ribaltata rispetto all'originale, l'ultima riga della matrice è la prima riga dell'immagine, la penultima riga della matrice è la seconda riga dell'immagine ecc...
 BitmapData Memory Organization

Tempi di esecuzione a confronto

PkLab ha condotto un test per misurare le prestazioni in termini di velocità nella lettura e trasferimento dei dati dell'immagine in un buffer di memoria. Il test è stato eseguito su 1000 file bitmap a da 288x288 a 32bit (RGB)

Vengono messi a confronto i due metodi sopra descritti e le prestazioni offerte dalla classe CBitmap

Read Bitmap Methods Performances

Il grafico suggerisce chiaramente che

  • La classe CBitmap è performante.
  • Per la sola operazione di lettura da file, il metodo Image::FromStream è molto più veloce del metodo Image::FromFile
  • La copia dell'immagine in un buffer di memoria (con LockBits) penalizza decisamente il metodo Image::FromStream e l'operazione Open+Copy ha prestazioni equivalenti per i due metodi della classe Image. Questo comportamento suggerisce che FromStream posticipa alcune operazioni dall'operazione di lettura da file, verso fasi successive del trattamento dell'immagine.
  • La classe CBitmap offre una funzione di trasferimento verso un buffer di memoria molto veloce.

La classe CBitmap

La classe CBitmap è inclusa nelle GDI+ di MFC. Tuttavia ne esistono numerose versioni e varianti su internet. Per i test di questa pagina si utilizza la versione bitmap.h sviluppata da Benjamin Kalytta (http://www.kalytta.com/bitmap.h).

La classe è compatibile con i soli file bitmap e non con tutte le immagini come per la classe Image.

See also:

PkCBitmap: Windows Bitmap File Loader C++ class

14-01-2010 565

Viene presentata una classe la lettura ultra veloce di un file bitmap in C++. La versione originale a cura di Benjamin Kalytta è stata modificata da PkLab introducendo, tra l'altro, il riutilizzo della memoria.

Vote this page:

0 Comments:

Leave your comment:

Note:
  • Your email email will not be visible or used in any way, and is not required
  • Please keep comments relevant
  • Any content deemed inappropriate or offensive may be edited and/or deleted
  • HTML code is not allowed. Please use BBCode to format your text
    [b]bold[/b], [u]underline[/u], [i]italic[/i], [code]code[/code]
The coding examples presented here are for illustration purposes only. The author takes no responsibility for end-user use
This work is property of Pk Lab. You can use it for free but you must retain author's copyright.