gpt4 book ai didi

C++ MFC StretchDIBits PixelFormat8bppIndexed

转载 作者:搜寻专家 更新时间:2023-10-31 02:05:40 25 4
gpt4 key购买 nike

玩 MFC,似乎在绘制 PixelFormat8bppIndexed 时出错了。

示例 PixelFormat8bppIndexed:

enter image description here

使用其他格式一切正常。

我认为问题出在:

(*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;
}

如何解决这个问题?

代码:

void ConvertImage(WCHAR *filename, Gdiplus::PixelFormat pixelformat, BITMAPINFO** pBitmapInfo, void** imageData, int* width, int* height)
{
#pragma region GDI+

*pBitmapInfo = new BITMAPINFO();
ULONG written;
LARGE_INTEGER zero;
zero.QuadPart = 0;

ULARGE_INTEGER liSize;

Gdiplus::GdiplusStartupInput tmp;
ULONG_PTR token;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);

Gdiplus::Bitmap *image = Gdiplus::Bitmap::FromFile(filename, false);

Gdiplus::Bitmap* destination = image->Clone(0, 0, image->GetWidth(), image->GetHeight(),
pixelformat);

CLSID clsid_bmp;
CLSIDFromString(L"{557cf400-1a04-11d3-9a73-0000f81ef32e}", &clsid_bmp);

IStream *stream = NULL;
HRESULT hr = CreateStreamOnHGlobal(0, TRUE, &stream);

if (!SUCCEEDED(hr))
printf("problems");

destination->Save(stream, &clsid_bmp);
IStream_Size(stream, &liSize);

stream->Seek(zero, STREAM_SEEK_SET, NULL);

unsigned char *info = new unsigned char[liSize.QuadPart];

stream->Read(info, liSize.QuadPart, &written);

BYTE *outImageData = new BYTE[(liSize.QuadPart - 54)];

memcpy(outImageData, info + 54, (liSize.QuadPart - 54));

*width = *(int*)&info[18];
*height = *(int*)&info[22];
switch (pixelformat)
{
case PixelFormat32bppARGB:
(*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 = ((*width) * (*height) * 4);
break;

case PixelFormat24bppRGB:
(*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 = ((*width) * (*height) * 3);
break;

case PixelFormat16bppRGB555:
(*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 = ((*width) * (*height) * 2);
break;

case PixelFormat8bppIndexed:
(*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;
}

break;
}
*imageData = outImageData;

delete destination;
delete image;
delete[]info;

Gdiplus::GdiplusShutdown(token);

#pragma endregion
}

void CMFCApplicationColorsView::OnDraw(CDC* pDC)
{
CMFCApplicationColorsDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;

BITMAPINFO* pBitmapInfo = NULL;
void *imageData = NULL;
int *width = new int;
int *height = new int;

ConvertImage(L"E:\TestImage.bmp", PixelFormat8bppIndexed, &pBitmapInfo, &imageData, width, height);
//ConvertImage(L"E:\TestImage.bmp", PixelFormat16bppRGB555, &pBitmapInfo, &imageData, width, height);
::StretchDIBits(pDC->GetSafeHdc(), 0, 0, *width, *height, 0, 0, *width, *height, imageData, pBitmapInfo, DIB_PAL_COLORS, SRCCOPY);

delete[] imageData;
delete pBitmapInfo;
delete width;
delete height;
// TODO: add draw code for native data here
}

最佳答案

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

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

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

sizeof(BITMAPINFO) + palettesize

您还可以使用辅助类 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);
}

关于C++ MFC StretchDIBits PixelFormat8bppIndexed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51538613/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com