11

I've loaded a CBitmap object from a resource ID, and I'm now wanting to scale it to 50% its size in each dimension. How might I go about this?

Smashery
  • 57,848
  • 30
  • 97
  • 128

3 Answers3

6
  1. Select your CBitmap obj into a memDC A (using CDC::SelectObject())
  2. Create a new CBitmap with desired sized and select it into another MemDC B
  3. Use CDC::stretchblt(...) to stretch bmp in MemDC A into MemDC B
  4. Deselect your CBitmap objects (by selecting what was returned from the previous calls to SelectObject)
  5. Use your new CBitmap
Smashery
  • 57,848
  • 30
  • 97
  • 128
SysAdmin
  • 5,455
  • 8
  • 33
  • 34
  • 1
    I'm not really certain about how to use all of those functions; in which order, using which version of the function, and how a CDC becomes usable for a CBitmap. Could you please provide some code? – Smashery May 06 '10 at 00:58
  • And which of the Raster Operation codes to use? http://msdn.microsoft.com/en-us/library/dd183370(v=VS.85).aspx – Smashery May 06 '10 at 06:57
  • @Smashery - SRCCOPY would do fine – SysAdmin May 06 '10 at 07:27
  • The problem was with Deselecting the CBitmap object. I've edited your answer to note this. – Smashery May 07 '10 at 00:23
5

Here's a worked out implementation of @Smashery's answer.

I use this to scale based on DPI, but it should be easy to adapt to arbitrary scales.

std::shared_ptr<CBitmap> AppHiDpiScaleBitmap (CBitmap &bmp)
{
    BITMAP bm = { 0 };
    bmp.GetBitmap (&bm);
    auto size = CSize (bm.bmWidth, bm.bmHeight);

    CWindowDC screenCDC (NULL);
    auto dpiX = screenCDC.GetDeviceCaps (LOGPIXELSX);
    auto dpiY = screenCDC.GetDeviceCaps (LOGPIXELSY);

    auto hiSize = CSize ((dpiX * size.cx) / 96, (dpiY * size.cy) / 96);

    std::shared_ptr<CBitmap> res (new CBitmap ());
    res->CreateCompatibleBitmap (&screenCDC, hiSize.cx, hiSize.cy);

    CDC srcCompatCDC;
    srcCompatCDC.CreateCompatibleDC (&screenCDC);
    CDC destCompatCDC;
    destCompatCDC.CreateCompatibleDC (&screenCDC);

    CMemDC srcDC (srcCompatCDC, CRect (CPoint (), size));
    auto oldSrcBmp = srcDC.GetDC ().SelectObject (&bmp);

    CMemDC destDC (destCompatCDC, CRect(CPoint(), hiSize));
    auto oldDestBmp = destDC.GetDC ().SelectObject (res.get());

    destDC.GetDC ().StretchBlt (0, 0, hiSize.cx, hiSize.cy, &srcDC.GetDC(), 0, 0, size.cx, size.cy, SRCCOPY);

    srcDC.GetDC ().SelectObject (oldSrcBmp);
    destDC.GetDC ().SelectObject (oldDestBmp);

    return res;
}
Frank Krueger
  • 69,552
  • 46
  • 163
  • 208
1
void ResizeBitmap (CBitmap &bmp_src, CBitmap& bmp_dst, int dstW, int dstH)
{
BITMAP bm = { 0 };
bmp_src.GetBitmap (&bm);
auto size = CSize (bm.bmWidth, bm.bmHeight);
CWindowDC wndDC(NULL);
CDC srcDC;
srcDC.CreateCompatibleDC(&wndDC);
auto oldSrcBmp = srcDC.SelectObject(&bmp_src);

CDC destDC;
destDC.CreateCompatibleDC(&wndDC);
bmp_dst.CreateCompatibleBitmap (&wndDC, dstW, dstH);
auto oldDestBmp = destDC.SelectObject (&bmp_dst);

destDC.StretchBlt(0, 0, dstW, dstH, &srcDC, 0, 0, size.cx, size.cy, SRCCOPY);
}
Danil
  • 701
  • 8
  • 7