2011-02-14 4 views
8

J'ai un tableau d'octets (que je lis dans un flux directement à partir d'un fichier .bmp, puis stocké comme un BLOB dans une base de données) que je veux afficher comme icônes dans un CImageList. Par conséquent, je veux en quelque sorte charger mes données dans un HBITMAP ou CBitmap. Je l'ai fait comme ça jusqu'à maintenant, la lecture d'un fichier:tableau [octets] à HBITMAP ou CBitmap

hPic = (HBITMAP)LoadImage(NULL, strPath, IMAGE_BITMAP, dwWidth, dwHeight, LR_LOADFROMFILE | LR_VGACOLOR); 
... 
CBitmap bitmap; 
bitmap.Attach(hPicRet); 

Mais évidemment, qui ne fonctionne que pour les fichiers, mais pas pour les octets tableaux. Comment puis-je obtenir le même résultat, mais lire à partir d'un tableau d'octets?

Edit: Notez que mon tableau ne contient pas seulement les informations de couleur, mais le dossier complet comme il est écrit sur le disque, y compris tous les en-têtes et des méta-données. Il me semble que rejeter toute cette information est une mauvaise idée.

+0

connexes: (sens inverse) [? Gdiplus :: Bitmap pour tableau Byte] (http://stackoverflow.com/questions/3340017/gdiplusbitmap-to -byte-array) – jrh

Répondre

16

En supposant que vous avez les informations chargées dans un tableau d'octets nommé octets ....

BITMAPFILEHEADER* bmfh; 
bmfh = (BITMAPFILEHEADER*)bytes; 

BITMAPINFOHEADER* bmih; 
bmih = (BITMAPINFOHEADER*)(bytes + sizeof(BITMAPFILEHEADER)); 
BITMAPINFO* bmi; 
bmi = (BITMAPINFO*)bmih; 

void* bits; 
bits = (void*)(bytes + bmfh->bfOffBits); 

HDC hdc = ::GetDC(NULL); 

HBITMAP hbmp = CreateDIBitmap(hdc, bmih, CBM_INIT, bits, bmi, DIB_RGB_COLORS) ; 

::ReleaseDC(NULL, hdc); 

Il est un peu en désordre et pourrait utiliser une bonne dose de contrôle d'erreur, mais l'idée de base est saine.

+0

A travaillé hors de la boîte! Je vous remercie! Puis-je vous demander quels types de contrôles d'erreurs vous suggéreriez? –

+3

@kdansky Vérifiez que bmi, bmih et bits sont tous dans le tableau d'octets. Vérifiez que GetDC a réussi. Vérifiez que CreateDIBitmap a réussi. Vous pouvez également envisager d'échanger GetDC (NULL) avec un appel plus approprié pour obtenir un contrôleur de domaine. GetDC (NULL) utilise le DC de l'écran entier pour déterminer une profondeur de couleur appropriée, ce qui peut ou non être approprié - cela dépend de ce que vous prévoyez d'utiliser le hbitmap pour. – Jon

+0

Si je pouvais voter plus, je le ferais. M'a sauvé des heures. – acraig5075

2

L'échantillon suivant pourrait vous aider.

BITMAPINFO bmInfo; 
BITMAPINFOHEADER &bmInfohdr = (BITMAPINFOHEADER)bmInfo.bmiHeader; 

bmInfohdr.biSize = 40 + 255; //I think it's not of use 
bmInfohdr.biWidth = x; 
bmInfohdr.biHeight = y; 
bmInfohdr.biPlanes=1; 
bmInfohdr.biBitCount=8; 
bmInfohdr.biCompression=0; 
bmInfohdr.biSizeImage=0; 
bmInfohdr.biXPelsPerMeter = 0; 
bmInfohdr.biYPelsPerMeter = 0; 
bmInfohdr.biClrUsed = 0; 
bmInfohdr.biClrImportant = 0; 

      // should I allocate memory further than the 
      // bmColors[1]?? anyway the compiler gives an 
      // error for type mismatch! 
//bmInfo.bmiColors = (RGBQUAD *) 
        malloc(sizeof(RGBQUAD) * 256); 

// here I define the 256 graylevel palette 
for (int i=0; i<256; i++) 
{ 
    bmInfo.bmiColors[i].rgbRed = i; 
    bmInfo.bmiColors[i].rgbGreen = i; 
    bmInfo.bmiColors[i].rgbBlue = i; 
} 


BYTE *matrix; 
matrix = (BYTE*)malloc(size*sizeof(BYTE)); 
// here I put the BYTE values of the pixels 

CDC *pdcDest = this->GetDC(); 

HBITMAP hBmp = CreateDIBitmap(pdcDest->m_hDC, 
       &bmInfohdr, 
       CBM_INIT, 
       matrix,  
       &bmInfo, 
       DIB_RGB_COLORS); 
m_bmpBitmap.Attach(hBmp); 
0

Quelque chose comme ça a fonctionné pour moi:


    int bitmap[WX*WY]; // truecolor bitmap data 
    BITMAPINFO bm = { sizeof(BITMAPINFOHEADER), WX, WY, 1, 32, BI_RGB, 0, 0, 0, 0, 0 }; 
    HBITMAP bmp = CreateDIBSection(GetDC(win), &bm, DIB_RGB_COLORS, (void**)&bitmap, 0,0); 

(Ceci est spécialement configuré pour les couleurs 32 bits, mais vous pouvez spécifier tout type).

+0

Je crois ne pas avoir une poignée de fenêtre (pratique) au point dans mon code où je veux écrire ceci. Y a-t-il une solution de rechange pour la partie GetDC()? –

+0

@Kdansky: Vous pouvez simplement utiliser l'écran DC retourné par 'GetDC (NULL)'. – casablanca

+0

Bien que cela ne plante pas ou ne fasse pas d'autres choses diaboliques, il en résulte que toutes mes images sont vides. Êtes-vous sûr que cela fonctionne lorsque le tableau contient le bitmap complet, y compris tous les en-têtes? Je stocke les fichiers dans ma base de données, avec toutes les méta-données, pas seulement les couleurs de pixels. –

0

Ok, voici un exemple complet: http://nishi.dreamhosters.com/u/so_bmp_v0.zip

#include <stdio.h> 
#include <windows.h> 

#pragma comment(lib,"gdi32.lib") 
#pragma comment(lib,"user32.lib") 

char buf[1<<22]; 

int main(int argc, char **argv) { 

    FILE* f = fopen("winnt.bmp", "rb"); if(f==0) return 1; 
    fread(buf, 1,sizeof(buf), f); 
    fclose(f); 

    BITMAPFILEHEADER& bfh = (BITMAPFILEHEADER&)buf[0]; 
    BITMAPINFO& bi = (BITMAPINFO&)buf[sizeof(BITMAPFILEHEADER)]; 
    BITMAPINFOHEADER& bih = bi.bmiHeader; 
    char* bitmap = &buf[bfh.bfOffBits]; 

    int WX=1024, WY=512; // window's width/height 
    int SX=bih.biWidth, SY=bih.biHeight; 

    HWND win = CreateWindow("STATIC", "Bitmap test", 0x90C0, 0,0, WX,WY, 0,0, GetModuleHandle(0), 0); 

    MSG msg; 
    PAINTSTRUCT ps; 
    HDC DC = GetDC(win); // window's DC 
    HBITMAP dib = CreateDIBitmap(DC, &bih, CBM_INIT, bitmap, &bi, DIB_RGB_COLORS); 
    HDC dibDC = CreateCompatibleDC(DC); SelectObject(dibDC, dib); 

    ShowWindow(win, SW_SHOWNOACTIVATE); 
    SetFocus(win); 

    while(GetMessage(&msg,win,0,0)) { 
    int m = msg.message; 
    if(m==WM_PAINT) { 
     DC = BeginPaint(win, &ps); 
     StretchBlt(DC, 0,0,WX,WY, dibDC,0,0,SX,SY, SRCCOPY); 
     EndPaint(win, &ps); 
    } else if((m==WM_KEYDOWN) || (m==WM_SYSKEYDOWN)) { 
     break; 
    } else { 
     DispatchMessage(&msg); 
    } 
    } 

    return 0; 
} 
Questions connexes