gpt4 book ai didi

c++ - MFC 将 Handle 转换为指针并将 DIB 转换为 DDB

转载 作者:行者123 更新时间:2023-11-28 05:37:00 25 4
gpt4 key购买 nike

我试图通过对像素值数组进行硬编码来创建位图,将此像素数组转换为 DIB,然后将此 DIB 转换为 DDB。在网上找了两个转换CreateBitmapFromPixels和DIBToDDB的函数。我的问题是程序会在第 244 行崩溃。我发现,在第 243 行,lpbi 没有从 hDIB 检索信息。然后,我在第 229 行和第 230 行添加了代码,以查看在创建 BITMAPINFO 结构的函数中执行相同的操作是否有帮助。仍然,没有从 HBITMAP 中得到任何东西。我想知道将句柄转换为指针是否有任何问题,它有什么作用,还有其他方法可以将 HBITMAPINFOHEADER 从句柄获取到 DIB,以便我可以解决问题。

 HBITMAP ColorChange2Dlg::CreateBitmapFromPixels( HDC hDC,
UINT uWidth, UINT uHeight, UINT uBitsPerPixel, LPVOID pBits)
{
if(uBitsPerPixel < 8) // NOT IMPLEMENTED YET
return NULL;

if(uBitsPerPixel == 8)
return Create8bppBitmap(hDC, uWidth, uHeight, pBits);

HBITMAP hBitmap = 0;
if ( !uWidth || !uHeight || !uBitsPerPixel )
return hBitmap;
LONG lBmpSize = uWidth * uHeight * (uBitsPerPixel/8) ;
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biBitCount = uBitsPerPixel;
bmpInfo.bmiHeader.biHeight = uHeight;
bmpInfo.bmiHeader.biWidth = uWidth;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
if(bmpInfo.bmiHeader.biBitCount==32) {
bmpInfo.bmiHeader.biCompression=BI_RGB;
//bmpInfo.bmiColors=NULL;
}
// Pointer to access the pixels of bitmap
UINT * pPixels = 0;
hBitmap = CreateDIBSection( hDC, (BITMAPINFO *)&
bmpInfo, DIB_RGB_COLORS, (void **)&
pPixels , NULL, 0);

if ( !hBitmap )
return hBitmap; // return if invalid bitmaps

//SetBitmapBits( hBitmap, lBmpSize, pBits);
// Directly Write
memcpy(pPixels, pBits, lBmpSize );
LPBITMAPINFOHEADER lpbi; //Line 229
lpbi = (LPBITMAPINFOHEADER)hBitmap; //Line 230
return hBitmap;
}

HBITMAP ColorChange2Dlg::DIBToDDB( HANDLE hDIB, CDC& dc )
{
LPBITMAPINFOHEADER lpbi;
HBITMAP hbm;
CPalette pal;
CPalette* pOldPal;
//CClientDC dc(NULL);
if (hDIB == NULL)
return NULL;
lpbi = (LPBITMAPINFOHEADER)hDIB; //Line 243
int nColors = lpbi->biClrUsed ? lpbi->biClrUsed : 1 << lpbi->biBitCount; //Line 244


BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
LPVOID lpDIBBits;
if( bmInfo.bmiHeader.biBitCount > 8 )
lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors +
bmInfo.bmiHeader.biClrUsed) +
((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
else
lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
// Create and select a logical palette if needed
if( nColors <= 256 && dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries = nColors;
for( int i=0; i < nColors; i++)
{
pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
pLP->palPalEntry[i].peFlags = 0;
}
pal.CreatePalette( pLP );
delete[] pLP;
// Select and realize the palette
pOldPal = dc.SelectPalette( &pal, FALSE );
dc.RealizePalette();
}
hbm = CreateDIBitmap(dc.GetSafeHdc(), // handle to device context
(LPBITMAPINFOHEADER)lpbi, // pointer to bitmap info header
(LONG)CBM_INIT, // initialization flag
lpDIBBits, // pointer to initialization data
(LPBITMAPINFO)lpbi, // pointer to bitmap info
DIB_RGB_COLORS ); // color-data usage
if (pal.GetSafeHandle())
dc.SelectPalette(pOldPal,FALSE);
return hbm;
}

void ColorChange2Dlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CClientDC dc(this);
COLORREF *pix = (COLORREF *)malloc(255*255*sizeof(COLORREF));
//int x = 1;
if(pix!=NULL){
for(int i=0;i<255;i++)
{
for(int j=0;j<255;j++)
{
pix[i*255+j] = RGB(i,j,0);
}
}
}
CDC tempDC;
tempDC.CreateCompatibleDC(&dc);
HBITMAP dib = CreateBitmapFromPixels(tempDC.m_hDC,255,255,8*sizeof(COLORREF),(BYTE*)pix);
HBITMAP finalMap = DIBToDDB(dib,tempDC);
HBITMAP oldMap = (HBITMAP)tempDC.SelectObject(finalMap);
dc.BitBlt(201,50,255,255,&tempDC,0,0,SRCCOPY);
tempDC.SelectObject(oldMap);
tempDC.DeleteDC();
}

最佳答案

要编写兼容的代码,最好不要直接访问位。您可以使用渐变函数和 GDI 或 GDI+ 绘制函数来做任何您想做的事情。

您想到的代码 pix[i*255+j] = RGB(i,j,0); 是 32 位图像的。每个像素指向一种颜色。它不是调色板图像,其中每个像素都指向颜色表中的一个条目。

如果显示是 32 位(大多数现代计算机都是,但要检查以确保),您可以使用以下代码执行此操作

CBitmap m_bitmap;
void CMyWnd::make_bitmap()
{
if (m_bitmap.GetSafeHandle()) return;
int w = 255;
int h = 255;
int *pix = new int[w*h];
for (int i = 0; i < w; i++)
for (int j = 0; j < h; j++)
pix[i + j*w] = RGB(i, j, 0);
m_bitmap.CreateBitmap(w, h, 1, 32, pix);
delete[]pix;
}

绘制位图:

void CMyWnd::paint_bitmap(CDC &dc)
{
if (!m_bitmap.GetSafeHandle()) return;
CDC memdc;
memdc.CreateCompatibleDC(&dc);
HBITMAP oldbitmap = (HBITMAP)memdc.SelectObject(m_bitmap);

BITMAP bm;
m_bitmap.GetBitmap(&bm);

dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memdc, 0, 0, SRCCOPY);
memdc.SelectObject(oldbitmap);
}

void CMyWnd::OnPaint()
{
__super::OnPaint();
CClientDC dc(this);
paint_bitmap(dc);
}


编辑:由于历史原因,RGB 值被反向保存为 BGR。请改用此函数:

void CMyWnd::make_bitmap()
{
if (m_bitmap.GetSafeHandle()) return;

int w = 256;
int h = 256;
BYTE *pix = new BYTE[4*w*h];

for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
int p = (i + j*w) * 4;
pix[p + 0] = 0;//blue
pix[p + 1] = i;//green
pix[p + 2] = j;//red
pix[p + 3] = 0;//not used in GDI functions
}
}

m_bitmap.CreateBitmap(w, h, 1, 32, pix);

delete[]pix;
}

关于c++ - MFC 将 Handle 转换为指针并将 DIB 转换为 DDB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38045466/

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