我有一个2752x2200的位图图像。我只能在我的MFC对话框中显示1/3(显示大小问题),所以如果我不缩放图像,我只得到左上角的917x733块(左上角1/3块)。我想将图像缩小3倍,以便整个图像显示在图像大小为1/3的区域中。我已经像这样设置了灰度位图:
//////////////////////////////////////////////////////////////////////////
////////// Setup Bitmap ////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//// FILEHEADER ////
BITMAPFILEHEADER* bf = new BITMAPFILEHEADER;
bf->bfType = 0x4d42;
bf->bfSize = 6054400 + 54 + sizeof(BITMAPINFO);
bf->bfOffBits = 54;
//// INFOHEADER ////
BITMAPINFOHEADER* bi = new BITMAPINFOHEADER;
bi->biSize = 40;
bi->biWidth = 2752;
bi->biHeight = -2200;
bi->biPlanes = 1;
bi->biBitCount = 8;
bi->biCompression = 0;
//bi->biSizeImage = 6054400; //not required
bi->biXPelsPerMeter = 2835;
bi->biYPelsPerMeter = 2835;
bi->biClrUsed = 0;
bi->biClrImportant = 0;
//// INFO ////
BITMAPINFO* pbmi = (BITMAPINFO*)alloca( sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD)*256);
pbmi->bmiHeader.biSize = sizeof (pbmi->bmiHeader);
pbmi->bmiHeader.biWidth = 2752;
pbmi->bmiHeader.biHeight = -2200;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 8;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 0;
pbmi->bmiHeader.biXPelsPerMeter = 14173;
pbmi->bmiHeader.biYPelsPerMeter = 14173;
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biClrImportant = 0;
//create grayscale color palette
for(int i=0; i<256; i++)
{
pbmi->bmiColors[i].rgbRed = i;
pbmi->bmiColors[i].rgbGreen = i;
pbmi->bmiColors[i].rgbBlue = i;
pbmi->bmiColors[i].rgbReserved = 0;
}
//// IMAGE DATA ////
pFrame->GetImage(m_imageData);
//////////////////////////////////////////////////////////////////////
////// Create image that's printed to dialog box /////////////////////
//////////////////////////////////////////////////////////////////////
HDC hdc = ::GetDC(NULL);
hbit = CreateDIBitmap(hdc, bi, CBM_INIT, m_imageData,
pbmi, DIB_RGB_COLORS);
然后我将位图绘制到我的对话框中,如下所示:
BITMAP* bi = new BITMAP;
CBitmap bmp;
bmp.Attach(hbit);
CClientDC dc(pWnd);
CDC bmDC;
bmDC.CreateCompatibleDC(&dc);
CBitmap *pOldbmp = bmDC.SelectObject(&bmp);
bmp.GetBitmap(bi);
dc.StretchBlt(384,21,bi->bmWidth,bi->bmHeight,&bmDC,0,0,
bi->bmWidth,bi->bmHeight,SRCCOPY);
bmDC.SelectObject(pOldbmp);
使用此代码,图像看起来很好,但它只是整个图像的左上方块:
在我尝试缩小图像时,我更改了一行:
dc.StretchBlt(384,21,bi->bmWidth,bi->bmHeight,&bmDC,0,0,
bi->bmWidth,bi->bmHeight,SRCCOPY);
为:
dc.StretchBlt(384,21,bi->bmWidth/3,bi->bmHeight/3,&bmDC,0,0,
bi->bmWidth,bi->bmHeight,SRCCOPY); // 1/3 original size
现在我的输出看起来缩小了,它显示整个图像(好),但一切看起来都是扭曲的(坏):
(请注意图像边框周围的圆环。那些不应该在那里,当你实际看到我的图像流的实时视频时,它们会产生脉动并基本上破坏图像。)
我的问题是: 造成这种失真的原因是什么,我可以做些什么来解决它?
编辑:尝试StretchDIBits()之后:
StretchDIBits(dc.m_hDC, 384, 21, bi->bmWidth/3, bi->bmHeight/3, 0,
0,bi->bmWidth,bi->bmHeight, myObv->GetImageData(),
myObv->GetPBMI(), DIB_RGB_COLORS, SRCCOPY);
我的输出看起来像这样:
i.imgur.com/DA49P8x.png
答案 0 :(得分:3)
如果要缩放位图,则windows api可能无法在视觉上很好地执行,因为它的设计旨在优化性能。在StretchBlt之前添加以下行以增强位图操作:
SetStretchBltMode(dc.m_hDC, HALFTONE);
答案 1 :(得分:2)
而不是StretchBLT
尝试StretchDIBits
:
StretchDIBits(dc.m_hDC, 384, 21, bi->bmWidth/3, bi->bmHeight/3, 0, 0,
bi->bmWidth, bi->bmHeight, m_imageData, pbmi, DIB_RGB_COLORS, SRCCOPY);