将位图缩小到所需尺寸

发布于 2024-07-24 23:39:20 字数 1593 浏览 7 评论 0原文

我有一个大尺寸(2000 x 2000)的位图,我需要将该位图缩小到一个小尺寸(150 x 150)。 我已经为其编写了代码,但它不起作用。 有人可以帮助找到问题吗? 问题是目标位图只是空白。 我选择了错误的 DC? 我已确保源和目的地都是正确的。 完成 bitblt 后,我​​还需要对目标位图做更多的事情吗?

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;
}

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

笨笨の傻瓜 2024-07-31 23:39:20

好吧,即使代码可以工作,也需要进行一些清理工作。
RAII 是您在 MFC 中工作时真正需要的习惯用法之一!

if( !pNewBitmap->CreateCompatibleBitmap(&dcDest, newWidth, newHeight) )
{
   return FALSE;
}

当您返回 FALSE 或存在异常时,您

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

在离开该函数之前尚未调用清理。

创建一个小的帮助器类来始终进行清理,您不必担心 return 或 throw 语句。

class SelectObjectAndCleanUp
{
    CDC& deviceContext;
    CBitmap *const oldSource;
public:
    SelectObjectCleanUp( CDC& deviceContext, CBitmap* source ) 
    : deviceContext(deviceContext),
      oldSource( deviceContext.SelectObject(source) ) {
    }

    ~SelectObjectCleanUp() {
            deviceContext.SelectObject(oldSource) 
    }
};

// use of the helper
SelectObjectCleanUp  sourceSelectionAndCleanup(dcSource, pBitmap );
SelectObjectCleanUp  destionationSelectionAndCleanup(dcDest, pNewBitmap );

Well even if the code works there is some cleaniing up to do.

RAII is one of the idiom you realy need when you are working in MFC!

if( !pNewBitmap->CreateCompatibleBitmap(&dcDest, newWidth, newHeight) )
{
   return FALSE;
}

When you return FALSE or there is an exception you haven't called

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

to cleanup before you left the function.

Create a small helper class to cleanup all the time, you don't have to worry about return or throw statements.

class SelectObjectAndCleanUp
{
    CDC& deviceContext;
    CBitmap *const oldSource;
public:
    SelectObjectCleanUp( CDC& deviceContext, CBitmap* source ) 
    : deviceContext(deviceContext),
      oldSource( deviceContext.SelectObject(source) ) {
    }

    ~SelectObjectCleanUp() {
            deviceContext.SelectObject(oldSource) 
    }
};

// use of the helper
SelectObjectCleanUp  sourceSelectionAndCleanup(dcSource, pBitmap );
SelectObjectCleanUp  destionationSelectionAndCleanup(dcDest, pNewBitmap );
记忆之渊 2024-07-31 23:39:20

我对 C++ 不太熟悉,但是您是否在创建新位图之前将新位图选择到新 DC 中? 另外,当您调用 CreateCompatibleBitmap 时,我认为您想要使用屏幕 DC(用于创建目标 DC 的 DC),而不是兼容的内存 DC。 因此,使用 GetDC 获取屏幕 DC,并将其传递给 CreateCompatibleDC 和 CreateCompatibleBitmap。

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.

鸠魁 2024-07-31 23:39:20

有一个很棒的免费 C++ 图像库,名为 CxImage,它是在zlib 许可证。

无需重新发明轮子。

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

No need to reinvent the wheel.

晚雾 2024-07-31 23:39:20
  • 下载http://www.gdiwatch.com/,它可能会告诉你错误在哪里(它也可以与 vs 2008 一起使用 - 只需将注册表项从 vs2005 手动复制到 vs2008 目录即可)

  • 您是否尝试过在 SelectObject() 调用之前执行 CreateCompatibleBitmap() ?

  • 新位图的 GetBitmap() 是否返回正确的大小,即新位图是否有效?

其余的看起来都不错,我相信它应该像这样工作。 它可以与其他 StretchBltMode 一起使用吗?

  • 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?

橘寄 2024-07-31 23:39:20

感谢所有偷看并提出解决方案的人,无论如何,经过一些调试后我发现了问题。 这是解决方案!

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);

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文