文件位置"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;
}