Annabi Gihed
Annabi Gihed

Reputation: 141

Scale an image with c++ / MFC

I’m trying to create a preview for “SMB” file, in which it’s a sort of image that can be generated with AutoCAD, I must load this image into a CRect that has 100 width and 100 height. However this image have a high resolution, and it contains a very small fish drawn in it. When the preview is created only white space is shown. In other cases where the image has a reasonable size its shown correctly.

I would like to know how to scale an image, in a way where I can zoom in the center of the image and lose the rest, just to keep it in the limits of the CRect object in which are 100 width and 100 height.

Here is the code I’m currently using :

HBITMAP hBitmap;
hBitmap = CreateDIBitmap(pDc->m_hDC, 
                        &EnteteSymb.BitmapInfoHeader,                           
                        (LONG)CBM_INIT, 
                        EnteteSymb.BitmapData,
                        (LPBITMAPINFO)&EnteteSymb.BitmapInfoHeader, 
                        DIB_RGB_COLORS);
CDC DCMem;
DCMem.CreateCompatibleDC(pDc);
DCMem.SelectObject(hBitmap);

int X       = Rect.left + MARGES_X;
int Y       = Rect.top  + MARGES_Y;
int Width   = Rect.right - Rect.left - ( 2 * MARGES_X );
int Height  = ( Rect.bottom ) - ( Rect.top + MARGES_Y ) - 1;

pDc->StretchBlt( X, Y, Width, Height, &DCMem, 0, 0, 100, 100,  SRCCOPY);

DCMem.DeleteDC();
DeleteObject(hBitmap);

Upvotes: 3

Views: 3395

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

When you offset a rectangle you have to change both Rect.left and Rect.right, same with ::top and ::bottom. You can use OffsetRect or MoveToXY.

If Rect is the destination rectangle of width and height 100, use the following:

int margin_x = 10;
int margin_y = 10;
CRect Rect(0, 0, 100, 100);
Rect.MoveToXY(margin_x, margin_y);

Use GetObject to find the dimension of the source rectangle:

BITMAP bm;
GetObject(hBitmap, sizeof(bm), &bm);
CRect source(0, 0, bm.bmWidth, bm.bmHeight);

Make sure source is greater than destination rectangle. Then use BitBlt for one to one mapping.

if(source.Width() > Rect.Width() && source.Height() > Rect.Height())
{
    int x = (source.Width() - Rect.Width()) / 2;
    int y = (source.Height() - Rect.Height()) / 2;
    dc.BitBlt(Rect.left, Rect.top, Rect.Width(), Rect.Height(), &memdc, x, y, SRCCOPY);
}

StretchBlt is usually used to fit the whole image in to a destination rectangle. If you were to use StretchBlt the function would look as follows:

dc.StretchBlt(Rect.left, Rect.top, Rect.Width(), Rect.Height(), 
    &memdc, x, y, Rect.Width(), Rect.Height(), SRCCOPY);

Read more about BitBlt and StretchBlt and see description of destination and source rectangle.

Upvotes: 2

Related Questions