【发布时间】:2020-01-27 10:24:46
【问题描述】:
我必须让一些旧版 (XP) MFC 代码在 Windows 10 下运行。它在 Windows 7 下运行良好。我没有尝试任何其他版本。
这个想法是内存中有一个缓冲区,其中包含 RGB 中的图像像素值。 然后将图像显示到屏幕上,将其转换为位图,然后复制到 DC。
这是将对象显示到屏幕上的函数。 它似乎可以工作,但屏幕上除了一个白框外什么都没有显示。
(cmets 已经在那里了!其他人一定也从中获得了一些乐趣!)
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 上,它们很好。也许这是一个线索,但我无法弄清楚它的含义。
【问题讨论】:
-
如果你关闭那个 16 位颜色并让它运行原生会发生什么?
-
没有该设置软件将无法运行。它检查窗口的颜色深度的属性,然后如果它不是 16 位或 24 位颜色则终止。它对这些缓冲区进行了大量的图像处理,如果我能提供帮助,我宁愿不改变这一切。
-
我找到了这段代码:link,但它使用了某种 RGBQUAD 对象,我不确定是否可以创建。如果有某种方法,那么它可能会起作用
-
那么为什么不修复它让它以原生颜色深度运行呢?
-
把条件改成
if( m_nBitsPerPixel != 16 && m_nBitsPerPixel != 24 && m_nBitsPerPixel != 32 )剩下的还是错。在您的代码中的某处,您可能有与CFBuffer24相关的GetDIBits或GetBitmapBits,请显示该函数。