gpt4 book ai didi

c++ - 遗留 C++ 代码在 Windows 10 下不显示位图

转载 作者:行者123 更新时间:2023-11-28 04:09:26 28 4
gpt4 key购买 nike

我必须获得一些在 Windows 10 下运行的遗留 (XP) MFC 代码。它在 Windows 7 下运行良好。我没有尝试过任何其他版本。

想法是内存中有一个缓冲区,其中包含 RGB 格式的图像像素值。然后将图像显示到屏幕上,将其转换为位图,然后复制到 DC。

这是将对象显示到屏幕上的函数。它似乎有效,但随后屏幕上除了一个白框之外什么也没有显示。

(评论已经在那里了!其他人一定也从中获得了一些乐趣!)

WORD* CFBuffer24::getBitmap(int nBitsPerPixel)
{
// check operation is valid
ASSERT(m_pFB[RED] && m_pFB[GREEN] && m_pFB[BLUE]);

if (nBitsPerPixel == 24)
{
if(NULL == m_pbm24)
m_pbm24 = new UCHAR[((m_fbSize.cx*3+3) & ~3)*m_fbSize.cy];
ASSERT(m_pbm24);
UCHAR* rptr = m_pFB[RED]->getPointer(0,0);
UCHAR* gptr = m_pFB[GREEN]->getPointer(0,0);
UCHAR* bptr = m_pFB[BLUE]->getPointer(0,0);
UCHAR* sptr = m_pbm24;
if (m_dGamma == 1.0)
{
for (int i = 0; i < m_fbSize.cx*m_fbSize.cy; i++, rptr++, gptr++, bptr++)
{
// Assumes 24bit display ie. B R G format
*sptr++ = *bptr;
*sptr++ = *gptr;
*sptr++ = *rptr;
}
}
else
{
UCHAR* wLUT = new UCHAR[256];
for (int i = 0; i < 256; i++)
{
int val = (int) (255.0 * pow((double) i / 255.0,1.0/m_dGamma) + 0.5);
if (val > 255)
val = 255;
wLUT[i] = UCHAR(val);
}
for (i = 0; i < m_fbSize.cx*m_fbSize.cy; i++, rptr++, gptr++, bptr++)
{
// Assumes 16bit display ie. 5R:6G:5B format
*sptr++ = wLUT[*bptr];
*sptr++ = wLUT[*gptr];
*sptr++ = wLUT[*rptr];
}
delete [] wLUT;
}
return((WORD*)m_pbm24);
}
//
if (nBitsPerPixel == 16)
{
if(NULL == m_pbm16)
m_pbm16= new WORD[((m_fbSize.cx*2+3) & ~3)*m_fbSize.cy];
ASSERT(NULL != m_pbm16);

UCHAR* rptr = m_pFB[RED]->getPointer(0,0);
UCHAR* gptr = m_pFB[GREEN]->getPointer(0,0);
UCHAR* bptr = m_pFB[BLUE]->getPointer(0,0);
WORD* sptr = m_pbm16;
if (m_dGamma == 1.0)
{
for (int i = 0; i < m_fbSize.cx*m_fbSize.cy; i++, rptr++, gptr++, bptr++)
{
// Assumes 16bit display ie. 5R:6G:5B format
*sptr++ = (WORD) ((((WORD)*bptr>>3)&0x001F) |
(((WORD)*gptr<<3)&0x07E0) |
(((WORD)*rptr<<8)&0xF800));
}
}
else
{
WORD* wLUT = new WORD[256];
for (int i = 0; i < 256; i++)
{
wLUT[i] = (WORD) (255.0 * pow((double) i / 255.0,1.0/m_dGamma) + 0.5);
if (wLUT[i] > 255)
wLUT[i] = 255;
}
for (i = 0; i < m_fbSize.cx*m_fbSize.cy; i++, rptr++, gptr++, bptr++)
{
// Assumes 16bit display ie. 5R:6G:5B format
*sptr++ = (WORD) (((wLUT[*bptr]>>3)&0x001F) |
((wLUT[*gptr]<<3)&0x07E0) |
((wLUT[*rptr]<<8)&0xF800));
}
delete [] wLUT;
}
return(m_pbm16);
}
// Bits per pixel must be wrong
return 0;
}

bool CImDisplay::CheckDisplaySize(CSize Imsize)
{
if (Imsize != m_Imsize) // resize the buffer
{
m_Imsize = Imsize;
// check the display capabilities
CDC* pDC;
pDC = m_pWnd->GetDC();
//Get the display capabilities
m_nBitPlanes = pDC->GetDeviceCaps( PLANES ); //Usually 1
m_nBitsPerPixel = pDC->GetDeviceCaps( BITSPIXEL );//Usually number of colours
m_pWnd->ReleaseDC(pDC);
if( m_nBitsPerPixel != 16 && m_nBitsPerPixel != 24 )
{
::MessageBox(::GetActiveWindow(),"Video mode is not compatable with\noutput resolution. Change Screen/Settings to 16 or 24 bits.","Unable to Display image", MB_ICONSTOP);
return false;
}
if (m_pBuf != 0)
delete [] m_pBuf;
m_pBuf = new UCHAR[m_Imsize.cx * m_Imsize.cy * m_nBitsPerPixel / 8];
if( !m_Map.CreateBitmap( m_Imsize.cx, m_Imsize.cy, m_nBitPlanes, m_nBitsPerPixel, m_pBuf ) )
::MessageBox(::GetActiveWindow(),"Can not create bitmap","Unable to Display image", MB_ICONSTOP);
}
return true;
}

void CImDisplay::Display(CFBuffer24* Image, CRect subRect)
{
CheckWindowPointer();
// Build the bastard bitmap
CSize imsize = Image->getBufferSize();
CheckDisplaySize(imsize);

// Write the Data to the Bit map
// Copies the image from our 24bit buffer into a bitmap and returns the pointer to the bitmap
DWORD dRet = m_Map.SetBitmapBits(imsize.cx*imsize.cy*m_nBitsPerPixel/8, Image->getBitmap(m_nBitsPerPixel) );
//Draw the bastard thing
CDC* pDC;
pDC = m_pWnd->GetDC();
CDC MemDC;
MemDC.CreateCompatibleDC( pDC );
CBitmap *pOldBitmap = MemDC.SelectObject( &m_Map );
pDC->SetStretchBltMode(COLORONCOLOR); // this gets the colours looking correct
pDC->StretchBlt( m_Location.TopLeft().x, m_Location.TopLeft().y,
m_Location.Width(), m_Location.Height(),
&MemDC, imSubRect.left, imSubRect.top,
imSubRect.Width(), imSubRect.Height(), SRCCOPY );
MemDC.SelectObject( pOldBitmap ); //Release the object
m_pWnd->ReleaseDC(pDC);
}

我在 Windows 10 上以兼容 16 位颜色运行该程序。这样它才能实际运行,否则运行良好。

当我使用 CreateCompatibleBitmap() 而不是 CreateBitmap() 时,我已经能够在 Windows 10 上显示某些内容,但颜色都是乱码。在 Windows 7 上,它们很好。也许这是一条线索,但我无法理解它的含义。

最佳答案

如果宽度不是 4 的倍数,您的代码可能会错误计算位图所需的空间。它应该是 required_size = ( (width * bits_per_pixel/8 + 3) & ~3 ) * height

如果 CFBuffer24 正确处理步幅(每行字节数),您可以直接将 blit 拉伸(stretch)到设备上下文:

void CImDisplay::Display(CFBuffer24* Image, CRect subRect)
{
CheckWindowPointer();

CDC* pDC = m_pWnd->GetDC();

m_nBitPlanes = pDC->GetDeviceCaps( PLANES ); //Usually 1
m_nBitsPerPixel = pDC->GetDeviceCaps( BITSPIXEL );
if( m_nBitsPerPixel != 16 && m_nBitsPerPixel != 24 && m_nBitsPerPixel != 32 )
{
::MessageBox(::GetActiveWindow(),"Video mode is not compatable with\noutput resolution. Change Screen/Settings to 16 or 24 bits.","Unable to Display image", MB_ICONSTOP);
return;
}

if ( m_nBitsPerPixel == 32 )
m_nBitsPerPixel = 24;

m_Imsize = Image->getBufferSize();

// Bitmap rows are aligned to multiplies of 4 bytes
int stride = (m_Imsize.cx * m_nBitsPerPixel / 8 + 3) & ~3;

BITMAPINFO bi =
{
sizeof( BITMAPINFOHEADER ),
stride,
-m_Imsize.cy, // If bitmap looks upside down remove minus
1,
m_nBitsPerPixel,
BI_RGB,
0,
0,
0,
0,
0
};

pDC->SetStretchBltMode(COLORONCOLOR);

::StretchDIBits(
pDC,
m_Location.TopLeft().x,
m_Location.TopLeft().y,
m_Location.Width(),
m_Location.Height(),
// !!!! I don't know what imSubRect is. Is it related to subRect?
imSubRect.left,
imSubRect.top,
imSubRect.Width(),
imSubRect.Height(),
Image->getBitmap(m_nBitsPerPixel),
&bi,
DIB_RGB_COLORS,
SRCCOPY );

m_pWnd->ReleaseDC(pDC);
}

以上代码将 24 位到 32 位的转换留给 StretchDIBits。性能方面应该没问题。或者,您可以在 CFBuffer24 中实现 32 位大小写。

关于c++ - 遗留 C++ 代码在 Windows 10 下不显示位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58128682/

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