- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
玩 MFC,似乎在绘制 PixelFormat8bppIndexed
时出错了。
示例 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;
}
如何解决这个问题?
代码:
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
检索 bits
和 BITMAPINFO
为 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/
我有一个 MFC 项目,它链接到第三方 dll。在程序退出时,IDE 会报告“检测到内存泄漏!”并倾倒泄漏物。 这些泄漏来自第三方 dll。我很确定这些是错误的报道。 (Google 的快速检查表明
首先我想要的是:能够显示具有多列的网格,每个单元格都有一个自定义渲染回调。因此,您可以使用这样的控件在游戏中显示您的库存,或者类似于 Google Chrome 中的行为,它会显示您访问的热门页面的网
在新的 MFC 功能(功能包)中,菜单出现在三个地方: 在菜单栏中 (CMFCMenuBar) 在弹出菜单中 (CMFCPopupMenu) 在 CMFCButton 的“下拉菜单”版本中 我想在所有
在我的 MFC 项目中,我想动态生成标签。例如:我必须为它们生成 4 个编辑控件和相应的标签——比如“Label1”“Label2”...... CStatic *label[MAX_THREAD];
我有第一个对话框,上面有一个简单的按钮,单击该按钮时,使用 CDialog::Create(IDD,this) 创建了第二个对话框。我希望在销毁第二个对话框但不向第二个对话框添加任何代码时通知父级,即
我们的代码库中的添加到剪贴板代码非常低级 - 分配全局内存等等。对于简单的情况,我只想将一些纯文本放在剪贴板上,是否有任何例程可以包装所有这些内容? 一个例子是 CRichEditCtrl 具有 Co
我对 mfc 中事件和消息之间的区别有点困惑。 他们是一样的吗? 最佳答案 由于您专门询问 MFC,我假设您指的是可以在 MFC 类的属性窗口中定义的事件处理程序和消息处理程序。 在“事件”下,您可以
如何以编程方式检测我的 MFC 应用程序当前是否正在显示模式对话框或属性表?目前我正在使用以下内容,但我觉得该代码也会触发无模式对话框。 bool HasModalDialog(const CWnd*
我有两个按钮: 单选按钮:“十六进制” 按钮:“A” 我想在用户选中“十六进制”按钮时启用“A”(“A”在创建时的状态为“禁用”),我该怎么做?谢谢大家。 最佳答案 您需要使用 CButton 's
通常情况下,窗口的厚度为 4 个像素,可以通过 GetSystemMetrics 方法获取。我可以更改它的值,例如 2 个像素吗? 非常感谢! 最佳答案 简单的回答:不。不适用于特定窗口。 复杂的答案
我需要打开一个从同一个类实例化的对话框两次。当我尝试这个时 CdelmeDlg dlg; dlg.DoModal(); dlg.DoModal(); 第二个调用只打开对话框一瞬间,然后关闭。我敢打赌消
如何通过代码在 mfc 中减少标题栏的窗口? 最佳答案 用: ModifyStyle (WS_CAPTION, 0); // to hide ModifyStyle (0, WS_CAPTION);
我使用 AfxMessageBox 关键字显示消息框。基本的东西。 但是,由于路径的长度,它显示如下: 有什么方法可以阻止它以这种方式自动换行吗? 抱歉,如果这是一个愚蠢的问题。但如果我只有一个句子,
所以,我有一个 MFC 程序的插件。我正在使用鼠标事件 Hook (来自 SetWindowsHookEx)来捕获点击。主机应用程序可以打开任意数量的(可能重叠的)子窗口,但我只想拦截特定子窗口中的点
我正在尝试将图像添加到现有按钮..我在一定程度上做到了这一点,问题是我可以添加一个所有者绘制的图像,但无法添加我想要的确切图像..示例见下文代码 CButton* pBtn= (CButton*)Ge
我想在对话框的标题栏上放置一些控件。一种可能的解决方案是,我只是从对话框中删除标题栏并绘制自己的标题栏。 但是如果我自己画标题栏,标题栏的外观不会根据窗口的主题而改变。而且我也不得不忍受接近、最小化和
我已经使用 MinGW 开发了 WinAPI 应用程序,没有问题。现在,我可以用 MFC 做同样的事情吗? 最佳答案 你不能。 MFC 代表 Microsoft Foundation Classes,
(我正在使用VS ++ 2005) 我在对话框上放置了编辑框控件(ID为ID_edit_box),并为其关联了两个变量(使用处理程序向导):控件(c_editbox)和值(v_editbox)变量。我
我有一个自定义 MFC 对话框 CMyDialog,使用资源编辑器添加了一个类型为 CMyControl 的自定义控件 - 该对话框有一个控件的成员变量并且有 DDX设置。 该控件正在接收绘制消息,并
直到现在,我从未真正需要我正在开发的大型 MFC(如果重要,则为单文档界面)应用程序的 Winapp ExitInstance()。但现在我这样做了,主要是为了清理内存分配、卸载一些 DLL 等。好吧
我是一名优秀的程序员,十分优秀!