C++ 从jpeg内存缓冲区创建HBITMAP?

C++ 从jpeg内存缓冲区创建HBITMAP?,c++,windows,winapi,mfc,hbitmap,C++,Windows,Winapi,Mfc,Hbitmap,我想用JPEG格式从字节数组创建HBITMAP 我已经搜索过了,但我只能从位图文件创建它 HBITMAP hbm = (HBITMAP)LoadImage(NULL,"fileName",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION); 有人能告诉我怎么做吗?只要使用GDIplus就行了。 它支持加载JPEG,其他一些东西感觉更符合逻辑 使用“位图”类。 当缓冲区中有jpeg时,您需要通过流来读取它。MFC提供了一种包装位图对象的方

我想用JPEG格式从字节数组创建HBITMAP

我已经搜索过了,但我只能从位图文件创建它

HBITMAP hbm = (HBITMAP)LoadImage(NULL,"fileName",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
有人能告诉我怎么做吗?

只要使用GDIplus就行了。 它支持加载JPEG,其他一些东西感觉更符合逻辑

使用“位图”类。 当缓冲区中有jpeg时,您需要通过流来读取它。

MFC提供了一种包装位图对象的方法。它提供了以多种格式加载和保存图像的便捷方法,包括JPEG、GIF、BMP和PNG

因此,业务的第一个顺序是获取一个表示您的
HBITMAP
CImage
对象。您可以通过调用并传递句柄来实现这一点

但是在这种情况下,看起来您可以完全跳过它,直接让
CImage
对象从文件中加载图像。用这个

一旦获得了表示图像的
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文件//

红色和蓝色被交换了,所以这里是一个修正版,颜色也被修正了。它使用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;
}
extern“C”{
#包括
#包括
}
#pragma注释(lib,“jpeg.lib”)
HBITMAP加载JPEGASBitmap(常量std::字符串和文件名)
{ 
结构jpeg_decompress_struct decomp{};
结构jpeg_error_mgr jerror{};
BITMAPINFO bi={};
LPBYTE lpBuf,pb=NULL;
HBITMAP hbm{};
JSAMPARRAY缓冲区{};
INT行=0;
decomp.err=jpeg\u std\u error(&jerror);
jpeg\u创建\u解压缩(&decomp);
FILE*FILE=fopen(filename.c_str(),“rb”);
if(file==nullptr)
{   
返回NULL;
}
jpeg_stdio_src(解压缩,文件);
jpeg_read_头(&decomp,TRUE);//读取jpeg文件头
jpeg_start_decompress(&decomp);//解压缩文件
行=((decomp.output_width*3+3)和~3);
buffer=(*decomp.mem->alloc_sarray)((j_common_ptr)和decomp,JPOOL_IMAGE,
第1行);
零内存(&bi.bmiHeader,sizeof(BitMapInfo头));
bi.bmiHeader.biSize=sizeof(BitMapInfo标头);
bi.bmiHeader.biWidth=decomp.output\u width;
bi.bmiHeader.biHeight=decomp.output\u height;
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biBitCount=24;
bi.bmiHeader.biCompression=bi_RGB;
bi.bmiHeader.biSizeImage=行*decomp.output\u高度;
hbm=CreateDIBSection(空值,&bi,DIB_RGB_颜色,(空**)和lpBuf,空值,0);
如果(hbm==NULL)
{
jpeg\u destroy\u解压缩(&decomp);
fclose(文件);
返回NULL;
}
pb=lpBuf+行*反编译输出高度;
while(decomp.output\u扫描线
您使用的是像MFC这样的库吗?如果是这样的话,可能有一种方便的方法可以很容易地做到这一点。否则,您将不得不编写一些代码。是的,我正在使用MFC库。请帮帮我。谢谢。据我所知,并不是所有的库都支持加载JPEG,但至少GDI+正在进行iThanks,但我需要从JPEG缓冲区(而不是从文件)创建HBITMAP。我有一个jpeg缓冲区,我想从这个缓冲区创建HBITMAP。我不想将此缓冲区保存到文件中。非常感谢。您需要创建一个IStream,以便可以使用CImage::Load(IStream)方法并从“缓冲区”加载图像。目前还不清楚该缓冲区是什么样子,CImage::Load只有在具有正确的JPEG文件头时才能工作。CreateStreamOnHGlobal()是一个方便的函数,只要缓冲区实际上是使用GlobalAlloc()创建的。Image::FromStream()。与CImage::Load(IStream)相同的要求谢谢,这正是我想要的。我将C与libjpeg一起使用,GDI+和MFC不在我的考虑范围之内。我甚至认为我需要用GDI绘制每个像素来创建一个!