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
", 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 ...
");
    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;
}

  

原文地址:https://www.cnblogs.com/baigoogledu/p/5276142.html