Reputation: 1432
I have a 2752x2200 bitmap image. I can only display 1/3 of it on my MFC dialog box (for obvious size issues), so if I don't scale the image I only get the top-left 917x733 block (the top-left 1/3 block). I want to zoom the image out by a factor of 3 so that the whole image is dislayed in an area the size of 1/3 of the image. I have set up the grayscale bitmap like so:
//////////////////////////////////////////////////////////////////////////
////////// 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);
And then I'm drawing the bitmap onto my dialog box like this:
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);
The image looks fine with this code, but it's only the top left block of the full image:
In my attempt to scale the image down, I changed the line:
dc.StretchBlt(384,21,bi->bmWidth,bi->bmHeight,&bmDC,0,0,
bi->bmWidth,bi->bmHeight,SRCCOPY);
to:
dc.StretchBlt(384,21,bi->bmWidth/3,bi->bmHeight/3,&bmDC,0,0,
bi->bmWidth,bi->bmHeight,SRCCOPY); // 1/3 original size
Now my output looks zoomed out and it's showing the whole image(good), but everything looks distorted (bad):
(Note the circular rings around the border of the image. Those shouldn't be there and when you actually see the live video of my image stream, they pulsate and basically ruin the image).
My question is: What is causing this distortion and is there something simple I can do to fix it?
EDIT: After trying 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);
my output looked like this:
i.imgur.com/DA49P8x.png
Upvotes: 0
Views: 2738
Reputation: 565
If you are zooming the bitmap, the windows api may not perform well visually because it is designed to optimized for performance. Add the following line before StretchBlt to enhance the bitmap operation:
SetStretchBltMode(dc.m_hDC, HALFTONE);
Upvotes: 3
Reputation: 308138
Instead of StretchBLT
try 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);
Upvotes: 2