FreeImage中 FIBITMAP与HBITMAP互相转化
文件位置"FreeImage/TestAPI/testMemIO.cpp"
// ========================================================== // FreeImage 3 Test Script // // Design and implementation by // - Herv?Drolon (drolon@infonie.fr) // // This file is part of FreeImage 3 // // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER // THIS DISCLAIMER. // // Use at your own risk! // ========================================================== #include <windows.h> #include "TestSuite.h" // 保存HBITMAP对应的文件 int save_bitmap_to_file(HBITMAP hBitmap, char *bitmap_filename); void testHBitmapMemIO(const char* qlpszPathName) { char* lpszPathName = "a.mgm"; struct stat buf; int result; // get data associated with lpszPathName result = stat(lpszPathName, &buf); if(result == 0) { // allocate a memory buffer and load temporary data BYTE *mem_buffer = (BYTE*)malloc(buf.st_size * sizeof(BYTE)); if(mem_buffer) { FILE *stream = fopen(lpszPathName, "rb"); if(stream) { fread(mem_buffer, sizeof(BYTE), buf.st_size, stream); fclose(stream); // attach the binary data to a memory stream FIMEMORY *hmem = FreeImage_OpenMemory(mem_buffer, buf.st_size); // get the file type FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0); // load an image from the memory stream FIBITMAP *dib = FreeImage_LoadFromMemory(fif, hmem, PNG_DEFAULT); { HBITMAP hBitmap; HDC hdc; // FIBITMAP转换HBITMAP { hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);//为屏幕创建设备描述表 hBitmap = CreateDIBitmap(hdc, FreeImage_GetInfoHeader(dib), CBM_INIT, FreeImage_GetBits(dib), FreeImage_GetInfo(dib), DIB_RGB_COLORS); //DeleteDC(hdc); save_bitmap_to_file(hBitmap, "aFIBITMAP2HBITMAP.bmp"); } // HBITMAP转换FIBITMAP // the following code assumes that you have a valid HBITMAP loaded into the memory { HBITMAP hBitmap_2 = (HBITMAP)LoadImageA(NULL, "aFIBITMAP2HBITMAP.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); BITMAP bm_info; GetObject(hBitmap_2, sizeof(BITMAP), (LPSTR)&bm_info); FIBITMAP* dib_new = FreeImage_Allocate(bm_info.bmWidth, bm_info.bmHeight, bm_info.bmBitsPixel); // The GetDIBits function clears the biClrUsed and biClrImportant BITMAPINFO members (dont't know why) // So we save these infos below. This is needed for palettized images only. int Success = GetDIBits(hdc, hBitmap_2, 0, FreeImage_GetHeight(dib_new), FreeImage_GetBits(dib_new), FreeImage_GetInfo(dib_new), DIB_RGB_COLORS); // restore BITMAPINFO members int nColors = FreeImage_GetColorsUsed(dib_new); FreeImage_GetInfoHeader(dib_new)->biClrUsed = nColors; FreeImage_GetInfoHeader(dib_new)->biClrImportant = nColors; FreeImage_Save(FIF_BMP, dib_new, "aHBITMAP2FIBITMAP.bmp", BMP_DEFAULT); } DeleteDC(hdc); } // save as a regular file //FreeImage_Save(FIF_PNG, dib, "blob.png", PNG_DEFAULT); FreeImage_Unload(dib); // close the stream FreeImage_CloseMemory(hmem); } } // user is responsible for freeing the data free(mem_buffer); } } void testSaveMemIO(const char *lpszPathName) { FIMEMORY *hmem = NULL; // load a regular file FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName); FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0); // open a memory handle hmem = FreeImage_OpenMemory(); // save the file to memory FreeImage_SaveToMemory(fif, dib, hmem, 0); // at this point, hmem contains the entire FREE_IMAGE_FORMAT data in memory. // the amount of space used by the memory is equal to file_size FreeImage_SeekMemory(hmem, 0, SEEK_END); long file_size = FreeImage_TellMemory(hmem); printf("File size : %ld\n", file_size); // its easy load an image from memory as well // seek to the start of the memory stream FreeImage_SeekMemory(hmem, 0L, SEEK_SET); // get the file type FREE_IMAGE_FORMAT mem_fif = FreeImage_GetFileTypeFromMemory(hmem, 0); // load an image from the memory handle FIBITMAP *check = FreeImage_LoadFromMemory(mem_fif, hmem, 0); // save as a regular file FreeImage_Save(FIF_PNG, check, "dump.png", PNG_DEFAULT); // make sure to free the data since FreeImage_SaveToMemory // will cause it to be malloc'd FreeImage_CloseMemory(hmem); FreeImage_Unload(check); FreeImage_Unload(dib); } //you could also have image data in memory via some other method, and just set //fmh.data to point to it, and set both fmh.datalen and fmh.filelen to the //size of that data, then FreeImage_LoadFromMemory could load the image from that memory void testLoadMemIO(const char *lpszPathName) { struct stat buf; int result; // get data associated with lpszPathName result = stat(lpszPathName, &buf); if(result == 0) { // allocate a memory buffer and load temporary data BYTE *mem_buffer = (BYTE*)malloc(buf.st_size * sizeof(BYTE)); if(mem_buffer) { FILE *stream = fopen(lpszPathName, "rb"); if(stream) { fread(mem_buffer, sizeof(BYTE), buf.st_size, stream); fclose(stream); // attach the binary data to a memory stream FIMEMORY *hmem = FreeImage_OpenMemory(mem_buffer, buf.st_size); // get the file type FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0); // load an image from the memory stream FIBITMAP *check = FreeImage_LoadFromMemory(fif, hmem, PNG_DEFAULT); // save as a regular file FreeImage_Save(FIF_PNG, check, "blob.png", PNG_DEFAULT); FreeImage_Unload(check); // close the stream FreeImage_CloseMemory(hmem); } } // user is responsible for freeing the data free(mem_buffer); } } void testAcquireMemIO(const char *lpszPathName) { FIMEMORY *hmem = NULL; // load a regular file FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName); FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0); // open and allocate a memory stream hmem = FreeImage_OpenMemory(); // save the file to memory FreeImage_SaveToMemory(FIF_PNG, dib, hmem, PNG_DEFAULT); FreeImage_Unload(dib); // get the buffer from the memory stream BYTE *mem_buffer = NULL; DWORD size_in_bytes = 0; FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes); // save the buffer in a file stream FILE *stream = fopen("buffer.png", "wb"); if(stream) { fwrite(mem_buffer, sizeof(BYTE), size_in_bytes, stream); fclose(stream); } // close and free the memory stream FreeImage_CloseMemory(hmem); } void testMemIO(const char *lpszPathName) { printf("testMemIO ...\n"); testHBitmapMemIO(lpszPathName); testSaveMemIO(lpszPathName); testLoadMemIO(lpszPathName); testAcquireMemIO(lpszPathName); } // 保存HBITMAP对应的文件 int save_bitmap_to_file(HBITMAP hBitmap, char *bitmap_filename) { if(NULL == hBitmap) { return -1; } HDC hDC; int bits_len;//当前分辨率下每象素所占字节数 WORD bit_count;//位图中每象素所占字节数 DWORD palette_size = 0;//定义调色板大小 DWORD bitmap_bits_size = 0;//位图中像素字节大小 DWORD bitmap_file_size = 0;//位图文件大小 DWORD dwWritten = 0;//写入文件字节数 BITMAP bitmap;//位图属性结构 BITMAPFILEHEADER file_head;//位图文件头结构 BITMAPINFOHEADER file_head_info;//位图信息头结构 LPBITMAPINFOHEADER p_file_head_info;//指向位图信息头结构 HANDLE hFile, hMem, hPalette, hPaletteOld = NULL;//定义文件,分配内存句柄,调色板句柄 //计算位图文件每个像素所占字节数 hDC = CreateDCA("DISPLAY", NULL, NULL, NULL); bits_len = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); DeleteDC(hDC); if(bits_len <= 1) { bit_count = 1; } else if(bits_len <= 4) { bit_count = 4; } else if(bits_len <= 8) { bit_count = 8; } else { bit_count = 24; } GetObject(hBitmap, sizeof(bitmap), (LPSTR)&bitmap); file_head_info.biSize = sizeof(BITMAPINFOHEADER); file_head_info.biWidth = bitmap.bmWidth; file_head_info.biHeight = bitmap.bmHeight; file_head_info.biPlanes = 1; file_head_info.biBitCount = bit_count; file_head_info.biCompression = BI_RGB; file_head_info.biSizeImage = 0; file_head_info.biXPelsPerMeter = 0; file_head_info.biYPelsPerMeter = 0; file_head_info.biClrImportant = 0; file_head_info.biClrUsed = 0; bitmap_bits_size = ((bitmap.bmWidth * bit_count + 31) / 32) * 4 * bitmap.bmHeight; //为位图内容分配内存 hMem = GlobalAlloc(GHND, bitmap_bits_size + palette_size + sizeof(BITMAPINFOHEADER)); p_file_head_info = (LPBITMAPINFOHEADER)GlobalLock(hMem); *p_file_head_info = file_head_info; // 处理调色板 hPalette = GetStockObject(DEFAULT_PALETTE); if(hPalette) { hDC = ::GetDC(NULL); hPaletteOld = ::SelectPalette(hDC, (HPALETTE)hPalette, FALSE); RealizePalette(hDC); } // 获取该调色板下新的像素值 GetDIBits(hDC, hBitmap, 0, (UINT)bitmap.bmHeight, (LPSTR)p_file_head_info + sizeof(BITMAPINFOHEADER)+palette_size, (BITMAPINFO *)p_file_head_info, DIB_RGB_COLORS); // 恢复调色板 if(hPaletteOld) { ::SelectPalette(hDC, (HPALETTE)hPaletteOld, TRUE); RealizePalette(hDC); ::ReleaseDC(NULL, hDC); } // 创建位图文件 hFile = CreateFileA(bitmap_filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if(hFile == INVALID_HANDLE_VALUE) { return S_FALSE; } // 设置位图文件头 file_head.bfType = 0x4D42; // "BM" bitmap_file_size = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+palette_size + bitmap_bits_size; file_head.bfSize = bitmap_file_size; file_head.bfReserved1 = 0; file_head.bfReserved2 = 0; file_head.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+palette_size; // 写入位图文件头 WriteFile(hFile, (LPSTR)&file_head, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); // 写入位图文件其余内容 WriteFile(hFile, (LPSTR)p_file_head_info, bitmap_file_size, &dwWritten, NULL); // 清除 GlobalUnlock(hMem); GlobalFree(hMem); CloseHandle(hFile); return S_OK; }