2011-02-14 50 views
8

我有一个字节数组(我通过直接从一个.bmp读取流,然后作为BLOB存储在数据库中),我想在CImageList中显示为图标。因此,我想以某种方式将我的数据加载到HBITMAP或CBitmap中。我已经做了这样的到现在为止,从文件中读取:阵列[字节] HBITMAP或CBitmap

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

但很明显,这仅适用于文件,而不是字节数组。我怎样才能得到相同的结果,但从字节数组中读取?

编辑: 请注意,我的数组不包含只是颜色信息,而是完整的文件,因为它是写在磁盘上,包括所有页眉和元数据。在我看来,丢弃所有这些信息是一个坏主意。

+0

相关:(相反的方向)[?:: Gdiplus位图来BYTE阵列(http://stackoverflow.com/questions/3340017/gdiplusbitmap-to字节数组) – jrh 2016-12-15 13:16:15

回答

16

假设你已经装载到一个名为字节一个字节数组的信息....

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

这是一个有点乱,可以使用错误检查的一个沉重的剂量,但其基本思想是健全的。

2

下面的示例可以帮助你。

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

事情是这样的工作对我来说:


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

(这具体配置为32位色,但您可以指定任何一种)。

+0

我相信在我的代码中我没有(实际的)窗口句柄来写这个。 GetDC()部分是否有解决方法? – 2011-02-14 15:21:47

+0

@Kdansky:您可以使用`GetDC(NULL)`返回的屏幕DC。 – casablanca 2011-02-14 16:34:42

0

好的,这是一个完整的例子: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; 
}