views:

494

answers:

5

Hi,

I have a bitmap of large dimension (2000 x 2000) i need to shrink that bitmap to a small dimension (150 x 150). i have written a code for it, but its not working. Can anybody help in finding the problem? The problem is the destination bitmap is just blank. I am selecting wrong DC's? I have made sure that both the source and destinations are correct. After doing bitblt do i need to do some more thing to destination bitmap?

BOOL ReSizeBitmap(CBitmap *pBitmap, CBitmap *pNewBitmap)
{

    // Get new bitmap size
    BITMAP bmOld;
    if( !pBitmap->GetBitmap(&bmOld) )
    {
     return FALSE;
    }

    CRect rcPrev(0, 0, bmOld.bmWidth, bmOld.bmHeight);
    int newWidth  = 150;
    int newHeight = 150;

    if( newWidth < 1 || newHeight < 1 )
    {
     ::SetLastError(ERROR_INVALID_PARAMETER);
     return FALSE;
    }

    BOOL bResult = FALSE;
    try
    { 
      CDC dcDest;
      CDC dcSource;

      dcSource.CreateCompatibleDC(NULL);
      dcDest.CreateCompatibleDC(NULL);

      CBitmap* pSourceOld = dcSource.SelectObject(pBitmap);
      CBitmap* pDestold = dcDest.SelectObject(pNewBitmap);

      if( !pNewBitmap->CreateCompatibleBitmap(
       &dcDest, newWidth, newHeight) )
      {

       return FALSE;
      }

      int oldStretchMode = dcDest.SetStretchBltMode(HALFTONE);

      bResult = dcDest.StretchBlt(
       0, 0, 150, 150,
       &dcSource, 0, 0, bmOld.bmWidth, bmOld.bmHeight,
       SRCCOPY); 
      dcDest.SetStretchBltMode(oldStretchMode);

      dcSource.SelectObject(pSourceOld);
      dcDest.SelectObject(pDestold);


     bResult = TRUE;
    }
    catch(CResourceException* /*e*/)
    {

    }

    return bResult;
}
A: 

There is a great free C++ image library called CxImage that is open source under the zlib license.

No need to reinvent the wheel.

Dana Holt
+1  A: 
TimW
+1  A: 

I'm not too familiar with C++, but are you selecting the new bitmap into your new DC before it's created? Also, when you call CreateCompatibleBitmap, I think you want to use your screen DC (the one you used to create the destination DC), not your compatible memory DC. So, get the screen DC with GetDC, and pass that into both CreateCompatibleDC AND CreateCompatibleBitmap.

wkf
My thought too - you need to create the bitmap before you select it.
Mark Ransom
A: 
  • Download http://www.gdiwatch.com/, it may show you where the error is (it can be made to work with vs 2008, too - just copy the registry keys manually from the vs2005 to vs2008 directories)

  • Have you tried doing the CreateCompatibleBitmap() before the SelectObject() call?

  • Does GetBitmap() of the new bitmap return the correct size, i.e. is the new bitmap valid?

The rest seem ok, it should work like this I believe. Does it work with other StretchBltModes?

Roel
can you please tell what the procedure to make it work for 2008
coolcake
- Install the version for 2005- Look in the registry with regedit, search for 'GDIWatch'- You'll find keys in the 2005 hives- Copy them exactly to the corresponding 2008 hivesIt's not hard, just a few keys.
Roel
A: 

Thanks to all of the guys who peeped and suggested solutions, any how after some debugging i found the problem. Here is the solution!!!

CBitmap *SrcBmp; HBITMAP hBmp; hBmp= (HBITMAP)LoadImage( NULL, L"c:\source.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE ); SrcBmp = CBitmap::FromHandle(hBmp);

BITMAP BmpInfo;
SrcBmp->GetBitmap(&BmpInfo);


CDC SrcDC;
SrcDC.CreateCompatibleDC(NULL);

CBitmap DestBmp;
DestBmp.CreateCompatibleBitmap(&SrcDC,150,150);

CDC DestDC;
DestDC.CreateCompatibleDC(NULL);

CBitmap *pOldBmp1 = SrcDC.SelectObject(SrcBmp);
CBitmap *pOldBmp2 = DestDC.SelectObject(&DestBmp);

DestDC.StretchBlt(0,0,150,150,&SrcDC,0,0,BmpInfo.bmWidth,BmpInfo.bmHeight,SRCCOPY);

CImage image;
image.Attach(DestBmp);
image.Save(_T("C:\\test.bmp"), Gdiplus::ImageFormatBMP);

SrcDC.SelectObject(pOldBmp1);
DestDC.SelectObject(pOldBmp2);
coolcake
But color images are displayed as black and white.
coolcake