C++ C++;MFC StretchDIBits像素格式

C++ C++;MFC StretchDIBits像素格式,c++,mfc,gdi+,C++,Mfc,Gdi+,玩MFC时,绘图pixelformat8bpappindexed似乎出了问题 示例PixelFormat8Bppined: 有了另一种格式,一切都好了 我认为问题在于: (*pBitmapInfo)->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); (*pBitmapInfo)->bmiHeader.biBitCount = 8; (*pBitmapInfo)->bmiHeader.biCompression = BI_RGB; (*

玩MFC时,绘图
pixelformat8bpappindexed
似乎出了问题

示例
PixelFormat8Bppined

有了另一种格式,一切都好了

我认为问题在于:

(*pBitmapInfo)->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
(*pBitmapInfo)->bmiHeader.biBitCount = 8;
(*pBitmapInfo)->bmiHeader.biCompression = BI_RGB;
(*pBitmapInfo)->bmiHeader.biWidth = (*width);
(*pBitmapInfo)->bmiHeader.biHeight = (*height);
(*pBitmapInfo)->bmiHeader.biPlanes = 1;
(*pBitmapInfo)->bmiHeader.biSizeImage = ((*width) * (*height) * 1);
(*pBitmapInfo)->bmiHeader.biClrUsed = 256;
(*pBitmapInfo)->bmiHeader.biClrImportant = 0;
for (int i = 0; i < 256; i++)
{
    (*pBitmapInfo)->bmiColors[0].rgbBlue = i;
    (*pBitmapInfo)->bmiColors[0].rgbRed = i;
    (*pBitmapInfo)->bmiColors[0].rgbGreen = i;
    (*pBitmapInfo)->bmiColors[0].rgbReserved = 0;
}
(*pBitmapInfo)->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
(*pBitmapInfo)->bmiHeader.biBitCount=8;
(*pBitmapInfo)->bmiHeader.biCompression=BI_RGB;
(*pBitmapInfo)->bmiHeader.biWidth=(*width);
(*pBitmapInfo)->bmiHeader.biHeight=(*height);
(*pBitmapInfo)->bmiHeader.biPlanes=1;
(*pBitmapInfo)->bmiHeader.biSizeImage=((*宽度)*(*高度)*1);
(*pBitmapInfo)->bmiHeader.biclrued=256;
(*pBitmapInfo)->bmiHeader.biClrImportant=0;
对于(int i=0;i<256;i++)
{
(*pBitmapInfo)->bmiColors[0].rgbBlue=i;
(*pBitmapInfo)->bmiColors[0].rgbreed=i;
(*pBitmapInfo)->bmiColors[0].rgbGreen=i;
(*pBitmapInfo)->bmiColors[0].rgbReserved=0;
}
如何解决这个问题

代码:

void ConvertImage(WCHAR*文件名,Gdiplus::PixelFormat PixelFormat,BITMAPINFO**pBitmapInfo,void**imageData,int*宽度,int*高度)
{
#布拉格地区GDI+
*pBitmapInfo=新的BITMAPINFO();
乌龙写的;
大整数零;
0.QuadPart=0;
ULARGE_INTEGER liSize;
Gdiplus::GDIPlusStartupInputTMP;
ULONG_PTR令牌;
Gdiplus::Gdiplus启动(&token,&tmp,NULL);
Gdiplus::Bitmap*image=Gdiplus::Bitmap::FromFile(文件名,false);
Gdiplus::Bitmap*destination=image->Clone(0,0,image->GetWidth(),image->GetHeight(),
像素格式);
CLSID CLSID_bmp;
CLSIDFromString(L“{557cf400-1a04-11d3-9a73-0000f81ef32e}”,&clsid_bmp);
IStream*stream=NULL;
HRESULT hr=CreateStreamOnHGlobal(0、TRUE和stream);
如果(!成功(hr))
printf(“问题”);
目的地->保存(流和clsid\u bmp);
IStream_大小(流和liSize);
stream->Seek(零,stream\u Seek\u SET,NULL);
unsigned char*info=新的unsigned char[liSize.QuadPart];
流->读取(信息、liSize.QuadPart和写入);
字节*outImageData=新字节[(liSize.QuadPart-54)];
memcpy(outImageData,info+54,(liSize.QuadPart-54));
*宽度=*(整数*)和信息[18];
*高度=*(整数*)和信息[22];
开关(像素格式)
{
案例像素格式32bpparGB:
(*pBitmapInfo)->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
(*pBitmapInfo)->bmiHeader.biBitCount=32;
(*pBitmapInfo)->bmiHeader.biCompression=BI_RGB;
(*pBitmapInfo)->bmiHeader.biWidth=*width;
(*pBitmapInfo)->bmiHeader.biHeight=*height;
(*pBitmapInfo)->bmiHeader.biPlanes=1;
(*pBitmapInfo)->bmiHeader.biSizeImage=((*宽度)*(*高度)*4);
打破
案例像素格式24bpprgb:
(*pBitmapInfo)->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
(*pBitmapInfo)->bmiHeader.biBitCount=24;
(*pBitmapInfo)->bmiHeader.biCompression=BI_RGB;
(*pBitmapInfo)->bmiHeader.biWidth=*width;
(*pBitmapInfo)->bmiHeader.biHeight=*height;
(*pBitmapInfo)->bmiHeader.biPlanes=1;
(*pBitmapInfo)->bmiHeader.biSizeImage=((*宽度)*(*高度)*3);
打破
案例像素格式16BPPRGB555:
(*pBitmapInfo)->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
(*pBitmapInfo)->bmiHeader.biBitCount=16;
(*pBitmapInfo)->bmiHeader.biCompression=BI_RGB;
(*pBitmapInfo)->bmiHeader.biWidth=*width;
(*pBitmapInfo)->bmiHeader.biHeight=*height;
(*pBitmapInfo)->bmiHeader.biPlanes=1;
(*pBitmapInfo)->bmiHeader.biSizeImage=((*宽度)*(*高度)*2);
打破
已编制索引的案例像素:
(*pBitmapInfo)->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
(*pBitmapInfo)->bmiHeader.biBitCount=8;
(*pBitmapInfo)->bmiHeader.biCompression=BI_RGB;
(*pBitmapInfo)->bmiHeader.biWidth=(*width);
(*pBitmapInfo)->bmiHeader.biHeight=(*height);
(*pBitmapInfo)->bmiHeader.biPlanes=1;
(*pBitmapInfo)->bmiHeader.biSizeImage=((*宽度)*(*高度)*1);
(*pBitmapInfo)->bmiHeader.biclrued=256;
(*pBitmapInfo)->bmiHeader.biClrImportant=0;
对于(int i=0;i<256;i++)
{
(*pBitmapInfo)->bmiColors[0].rgbBlue=i;
(*pBitmapInfo)->bmiColors[0].rgbreed=i;
(*pBitmapInfo)->bmiColors[0].rgbGreen=i;
(*pBitmapInfo)->bmiColors[0].rgbReserved=0;
}
打破
}
*imageData=outImageData;
删除目的地;
删除图像;
删除[]信息;
Gdiplus::GdiplusShutdown(令牌);
#布拉格端区
}
无效CMFCApplicationColorsView::OnDraw(CDC*pDC)
{
CMFCApplicationColorsDoc*pDoc=GetDocument();
断言有效(pDoc);
if(!pDoc)
返回;
BITMAPINFO*pBitmapInfo=NULL;
void*imageData=NULL;
整数*宽度=新整数;
整数*高度=新整数;
ConvertImage(L“E:\TestImage.bmp”、PixelFormat8BPindexed、&pBitmapInfo、&imageData、宽度、高度);
//ConvertImage(L“E:\TestImage.bmp”、PixelFormat16bppRGB555、&pBitmapInfo、&imageData、宽度、高度);
::StretchDIBits(pDC->GetSafeHdc(),0,0,*宽度,*高度,0,0,*宽度,*高度,图像数据,pBitmapInfo,DIB_PAL_颜色,SRCCOPY);
删除[]图像数据;
删除pBitmapInfo;
删除宽度;
删除高度;
//TODO:在此处添加本机数据的绘图代码
}

Gdiplus::GetHBITMAP
允许直接检索
HBITMAP
。在大多数情况下,这足以允许将GDI函数与GDI+一起使用

如果出于某种原因必须使用
stretchibits
,则首先使用
GetDIBits
检索
BITMAPINFO

BITMAPINFO
分配内存时,请确保为调色板添加额外内存,以防使用8位位图:

sizeof(BITMAPINFO) + palettesize
您还可以使用helper类
gdiplus_init
确保始终调用启动/关闭

#include <vector>
...

class gdiplus_init
{
    ULONG_PTR token;
public:
    gdiplus_init()
    {
        Gdiplus::GdiplusStartupInput tmp;
        Gdiplus::GdiplusStartup(&token, &tmp, NULL);
    }
    ~gdiplus_init()
    {
        Gdiplus::GdiplusShutdown(token);
    }
};

bool getbits(const wchar_t *filename, Gdiplus::PixelFormat pixelformat, 
    std::vector<BYTE> &bitmapinfo, std::vector<BYTE> &bits, int &w, int &h)
{
    gdiplus_init init;

    WORD bpp = 0;
    int usage = DIB_RGB_COLORS;
    int palettesize = 0;

    switch(pixelformat)
    {
    case PixelFormat8bppIndexed: 
        bpp = 8; 
        usage = DIB_PAL_COLORS;  
        palettesize = 256 * sizeof(RGBQUAD);
        break;
    case PixelFormat16bppRGB555: bpp = 16; break;
    case PixelFormat16bppRGB565: bpp = 16; break;
    case PixelFormat24bppRGB: bpp = 24; break;
    case PixelFormat32bppRGB: bpp = 32; break;
    default:return false;
    }

    auto src = Gdiplus::Bitmap::FromFile(filename);
    if(src->GetLastStatus() != Gdiplus::Status::Ok)
        return false;

    auto dst = src->Clone(0, 0, src->GetWidth(), src->GetHeight(),
        pixelformat);

    w = src->GetWidth();
    h = src->GetHeight();

    HBITMAP hbitmap;
    Gdiplus::Color color;
    dst->GetHBITMAP(color, &hbitmap);

    //allocate enough memory for bitmapinfo and initialize to zero
    //it's sizeof BITMAPINFO structure + size of palette
    bitmapinfo.resize(sizeof(BITMAPINFO) + palettesize, 0);

    //fill the first 6 parameters
    BITMAPINFO* ptr = (BITMAPINFO*)bitmapinfo.data();
    ptr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); //don't skip
    ptr->bmiHeader.biWidth = w;
    ptr->bmiHeader.biHeight = h;
    ptr->bmiHeader.biPlanes = 1;
    ptr->bmiHeader.biBitCount = bpp;
    ptr->bmiHeader.biCompression = BI_RGB;

    //magic formula to calculate the size:
    //this is roughly w * h * bytes_per_pixel, it's written this way
    //to account for "bitmap padding"
    DWORD size = ((w * bpp + 31) / 32) * 4 * h;

    //allocate memory for image
    bits.resize(size, 0);

    //finally call GetDIBits to fill bits and bitmapinfo
    HDC hdc = GetDC(0);
    GetDIBits(hdc, hbitmap, 0, h, &bits[0], (BITMAPINFO*)&bitmapinfo[0], usage);
    ReleaseDC(0, hdc);

    //cleanup
    delete src;
    delete dst;

    return true;
}

void CMFCApplicationColorsView::OnDraw(CDC* pDC)
{
    ...
    std::vector<BYTE> bi; //automatic storage
    std::vector<BYTE> bits; 
    int w, h;

    //24-bit test
    if(getbits(L"c:\\test\\24bit.bmp", PixelFormat24bppRGB, bi, bits, w, h))
        StretchDIBits(dc, 0, 0, w, h, 0, 0, w, h, 
            bits.data(), (BITMAPINFO*)bi.data(), DIB_RGB_COLORS, SRCCOPY);

    //8-bit test
    if(getbits(L"c:\\test\\8bit.bmp", PixelFormat8bppIndexed, bi, bits, w, h))
        StretchDIBits(dc, 0, 220, w, h, 0, 0, w, h, 
            bits.data(), (BITMAPINFO*)bi.data(), DIB_PAL_COLORS, SRCCOPY);
}
<代码
#include <vector>
...

class gdiplus_init
{
    ULONG_PTR token;
public:
    gdiplus_init()
    {
        Gdiplus::GdiplusStartupInput tmp;
        Gdiplus::GdiplusStartup(&token, &tmp, NULL);
    }
    ~gdiplus_init()
    {
        Gdiplus::GdiplusShutdown(token);
    }
};

bool getbits(const wchar_t *filename, Gdiplus::PixelFormat pixelformat, 
    std::vector<BYTE> &bitmapinfo, std::vector<BYTE> &bits, int &w, int &h)
{
    gdiplus_init init;

    WORD bpp = 0;
    int usage = DIB_RGB_COLORS;
    int palettesize = 0;

    switch(pixelformat)
    {
    case PixelFormat8bppIndexed: 
        bpp = 8; 
        usage = DIB_PAL_COLORS;  
        palettesize = 256 * sizeof(RGBQUAD);
        break;
    case PixelFormat16bppRGB555: bpp = 16; break;
    case PixelFormat16bppRGB565: bpp = 16; break;
    case PixelFormat24bppRGB: bpp = 24; break;
    case PixelFormat32bppRGB: bpp = 32; break;
    default:return false;
    }

    auto src = Gdiplus::Bitmap::FromFile(filename);
    if(src->GetLastStatus() != Gdiplus::Status::Ok)
        return false;

    auto dst = src->Clone(0, 0, src->GetWidth(), src->GetHeight(),
        pixelformat);

    w = src->GetWidth();
    h = src->GetHeight();

    HBITMAP hbitmap;
    Gdiplus::Color color;
    dst->GetHBITMAP(color, &hbitmap);

    //allocate enough memory for bitmapinfo and initialize to zero
    //it's sizeof BITMAPINFO structure + size of palette
    bitmapinfo.resize(sizeof(BITMAPINFO) + palettesize, 0);

    //fill the first 6 parameters
    BITMAPINFO* ptr = (BITMAPINFO*)bitmapinfo.data();
    ptr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); //don't skip
    ptr->bmiHeader.biWidth = w;
    ptr->bmiHeader.biHeight = h;
    ptr->bmiHeader.biPlanes = 1;
    ptr->bmiHeader.biBitCount = bpp;
    ptr->bmiHeader.biCompression = BI_RGB;

    //magic formula to calculate the size:
    //this is roughly w * h * bytes_per_pixel, it's written this way
    //to account for "bitmap padding"
    DWORD size = ((w * bpp + 31) / 32) * 4 * h;

    //allocate memory for image
    bits.resize(size, 0);

    //finally call GetDIBits to fill bits and bitmapinfo
    HDC hdc = GetDC(0);
    GetDIBits(hdc, hbitmap, 0, h, &bits[0], (BITMAPINFO*)&bitmapinfo[0], usage);
    ReleaseDC(0, hdc);

    //cleanup
    delete src;
    delete dst;

    return true;
}

void CMFCApplicationColorsView::OnDraw(CDC* pDC)
{
    ...
    std::vector<BYTE> bi; //automatic storage
    std::vector<BYTE> bits; 
    int w, h;

    //24-bit test
    if(getbits(L"c:\\test\\24bit.bmp", PixelFormat24bppRGB, bi, bits, w, h))
        StretchDIBits(dc, 0, 0, w, h, 0, 0, w, h, 
            bits.data(), (BITMAPINFO*)bi.data(), DIB_RGB_COLORS, SRCCOPY);

    //8-bit test
    if(getbits(L"c:\\test\\8bit.bmp", PixelFormat8bppIndexed, bi, bits, w, h))
        StretchDIBits(dc, 0, 220, w, h, 0, 0, w, h, 
            bits.data(), (BITMAPINFO*)bi.data(), DIB_PAL_COLORS, SRCCOPY);
}