我想从 JPEG 格式的字节数组创建 HBITMAP。
我已经搜索过,但我只能从位图文件创建它
HBITMAP hbm = (HBITMAP)LoadImage(NULL,"fileName",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
有人可以告诉我怎么做吗?
只需使用 GDIplus。它支持加载 JPEG,其他一些东西感觉更合乎逻辑
http://msdn.microsoft.com/en-us/library/ms533830%28v=vs.85%29.aspx
使用“位图”类。当您在缓冲区中有 jpeg 时,您需要通过流读取它。
MFC 提供了一个封装位图对象的CImage
类。它提供了以多种格式加载和保存图像的便捷方法,包括 JPEG、GIF、BMP 和 PNG。
因此,首要任务是获取CImage
代表您的HBITMAP
. 您可以通过调用Attach
方法并传递句柄来做到这一点。
但在这种情况下,您似乎可以完全跳过它,只需让CImage
对象直接从文件中加载您的图像。使用该Load
方法。
一旦你有了一个CImage
代表你的图像的对象,只需调用该Save
方法并使用适当的扩展名指定所需的文件名。根据文档:
如果
guidFileType
不包含该参数,则将使用文件名的文件扩展名来确定图像格式。如果没有提供扩展名,图像将以 BMP 格式保存。
示例代码:
CImage img;
img.Load(TEXT("fileName.bmp")); // load a bitmap (BMP)
img.Save(TEXT("fileName.jpg")); // and save as a JPEG (JPG)
您也可以反转此模式,使用Load
加载 JPEG 文件的Save
方法和保存 BMP 文件的方法。
我找到了以下代码 // http://katahiromz.web.fc2.com/win32/loadjpeg.html
红色和蓝色被交换了,所以这里是一个修正了颜色的修正版本。它使用 jpeglib,所以你必须先编译它。如果你只需要转换一个缓冲区,那么你可以跳过加载文件的那一行——转换的细节应该是一样的。
extern "C" {
#include <jpeglib.h>
#include <jerror.h>
}
#pragma comment(lib, "jpeg.lib")
HBITMAP LoadJpegAsBitmap(const std::string & filename)
{
struct jpeg_decompress_struct decomp{};
struct jpeg_error_mgr jerror{};
BITMAPINFO bi = {};
LPBYTE lpBuf, pb = NULL;
HBITMAP hbm{};
JSAMPARRAY buffer{};
INT row = 0;
decomp.err = jpeg_std_error(&jerror);
jpeg_create_decompress(&decomp);
FILE* file = fopen(filename.c_str(), "rb");
if (file == nullptr)
{
return NULL;
}
jpeg_stdio_src(&decomp, file);
jpeg_read_header(&decomp, TRUE); // read jpeg file header
jpeg_start_decompress(&decomp); // decompress the file
row = ((decomp.output_width * 3 + 3) & ~3);
buffer = (*decomp.mem->alloc_sarray)((j_common_ptr)&decomp, JPOOL_IMAGE,
row, 1);
ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = decomp.output_width;
bi.bmiHeader.biHeight = decomp.output_height;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = row * decomp.output_height;
hbm = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&lpBuf, NULL, 0);
if (hbm == NULL)
{
jpeg_destroy_decompress(&decomp);
fclose(file);
return NULL;
}
pb = lpBuf + row * decomp.output_height;
while (decomp.output_scanline < decomp.output_height)
{
pb -= row;
jpeg_read_scanlines(&decomp, buffer, 1);
if (decomp.out_color_components == 1)
{
UINT i;
LPBYTE p = (LPBYTE)buffer[0];
for (i = 0; i < decomp.output_width; i++)
{
pb[3 * i + 0] = p[i];
pb[3 * i + 1] = p[i];
pb[3 * i + 2] = p[i];
}
}
else if (decomp.out_color_components == 3)
{
// There was talk on Internet about one being RGB and another BGR.
// If colors appear swapped, then swap the bytes, and update this comment.
//CopyMemory(pb, buffer[0], row);
// Updated color correction
UINT i;
LPBYTE p = (LPBYTE)buffer[0];
for (i = 0; i < row; i += 3)
{
pb[i + 0] = p[i + 2]; // Blue
pb[i + 1] = p[i + 1]; // Green
pb[i +2] = p[i + 0]; // Red
}
}
else
{
jpeg_destroy_decompress(&decomp);
fclose(file);
DeleteObject(hbm);
return NULL;
}
}
SetDIBits(NULL, hbm, 0, decomp.output_height, lpBuf, &bi, DIB_RGB_COLORS);
jpeg_finish_decompress(&decomp);
jpeg_destroy_decompress(&decomp);
fclose(file);
return hbm;
}