C++ C++;MFC StretchDIBits像素格式
玩MFC时,绘图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; (*
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);
}