2011-01-04 19 views
10

Ho un'applicazione che carica alcuni dati blob da un database che può rappresentare dati binari in formato png o grezzi per varie bitmap e icone. Questo viene memorizzato in un std::vector<unsigned char>Creazione di HBITMAP dal buffer di memoria

sto usando CImageList oggetti da visualizzare diverse immagini in viste ad albero, le immagini della barra degli strumenti, ecc, ma il problema è la creazione di bitmap dei dati in memoria stanno uscendo sfocata come se manca pixel quando fare qualcosa di simile di seguito:

std::vector<unsigned char> bits; 
HBITMAP hbitmap = CreateBitmap(16, 16, 1, 32, bits.data()); 

per aggirare il problema per ora sto semplicemente scrivendo fuori i dati() nel vettore in un file temporaneo e quindi utilizzando LoadImage di leggerlo indietro e creare il HBITMAP da quella . Questo funziona perfettamente, tuttavia, che è certamente un trucco spudorato e dovrebbe essere completamente inutile, spero.

Mi sono guardato in giro online ma non ho trovato alcun buon esempio di come "correttamente" creare hbitmap dalla memoria. Mi piacerebbe essere in grado di creare questi bitmap da aggiungere all'elenco delle immagini senza alcun file I/O e quantità limitate di copia dei dati, se possibile.

Cercare il modo migliore per farlo e ovviamente il codice specifico di Windows va bene.

UPDATE:

in base alla risposta del JDV ho cominciato a giocare con CreateCompatibleBitmap, CreateDIBitmap, e, infine, CreateDIBSection. Tutti questi hanno finito per creare belle bitmap nere invece delle precedenti bitmap fuzzy, quindi devo fare ancora qualcosa di sbagliato e la mia ipotesi è che questa creazione di bitmap viene eseguita in un oggetto che non ha alcun concetto di schermo dc o finestra che utilizza GetDC(NULL) e CreateCompatibleDC(NULL) non vanno bene. Esempio di codice:

BITMAPINFO bmi; 
    ZeroMemory(&bmi, sizeof(BITMAPINFO)); 
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    bmi.bmiHeader.biBitCount = 32; 
    bmi.bmiHeader.biHeight = 16; 
    bmi.bmiHeader.biWidth = 16; 
    bmi.bmiHeader.biPlanes = 1; 

    HDC dc = CreateCompatibleDC(NULL); 
    HBITMAP hbitmap = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, (void**)blobData.GetMember<FILEDATAFIELD_DATA>().data(), NULL, 0); 

ora sto ovviamente pensando che ci ha ottenuto di essere un modo più semplice per andare su questo, forse evitando la HBITMAP tutto e lavorando direttamente con CBitmap classe? Quando si tratta di aggiungere l'immagine allo CImageList, sto usando lo stesso CBitmap::FromHandle(HBITMAP hbitmap, COLORREF mask). Qualcuno sa un modo semplice per inizializzare un oggetto CBitmap da un std::vector<unsigned char>?

+0

Si prega di non modificare una domanda per un nuovo significato in quanto invalida le risposte. Sentiti libero di postare una nuova domanda e link a quella vecchia. –

+0

Scusa, ho fatto solo un passo indietro e ho capito che l'unica ragione per cui ero in GDI land era perché stavo usando il metodo FromHandle quando aggiungevo alla CImageList ... MFC CBitmap semplicemente avvolgeva comunque le chiamate GDI quindi è molto simile. – AJG85

risposta

3

Utilizzo di GdiPlus Ho ottenuto qualcosa che funziona abbastanza bene e non comporta l'estrazione di alcun dente!

Gdiplus::Bitmap* pBitmap = NULL; 
IStream* pStream = NULL; 

HRESULT hResult = ::CreateStreamOnHGlobal(NULL, TRUE, &pStream); 
if(hResult == S_OK && pStream) 
{ 
    hResult = pStream->Write(&bits[0], ULONG(bits.size()), NULL); 
    if(hResult == S_OK) 
     pBitmap = Gdiplus::Bitmap::FromStream(pStream); 
    pStream->Release(); 
} 

Edit: Modificato per Jegatheesh

+1

E come ottenere HBITMAP da 'Gdiplus :: Bitmap *'? –

5

Vorrei usare CreateCompatibleBitmap e quindi chiamare SetDIBits per riempirlo con i dati. Queste sono funzioni che ho visto funzionare, e SetDIBits è abbastanza flessibile, anche se prolisso.

Nei miei anni MFC, CreateBitmap è stato evitato a causa di sospetti problemi di prestazioni.

+1

Sto guardando CreateDIBitmap ora che da quello che posso dire fondamentalmente crea una bitmap DC compatibile e quindi chiama un equivalente di SetDIBits se si specifica il flag CBM_INIT. Chiunque abbia chiamato parametri e membri delle strutture nell'API di Windows deve essere girato. – AJG85

+0

Oh, giusto, c'era anche CreateDIBitmap. –