2009-06-09 3 views
1

У меня есть растровое изображение большого размера (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; 
} 
+0

есть ли вопрос где-то? – Glen

+0

И ваш вопрос? –

+0

спасибо за указание! – coolcake

ответ

0

Существует большая бесплатная библиотека C++ изображения называется CxImage, что является открытым исходным кодом под лицензией ZLIB.

Не нужно изобретать велосипед.

1

Ну, даже если код работает, есть некоторая очистка до этого.
RAII - одна из тех идиом, которые вам действительно нужны, когда вы работаете в MFC!

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

При возврате FALSE или есть исключение вы не вызвали

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

для очистки, прежде чем оставить функцию.

Создайте небольшой класс-помощник для очистки все время, вам не нужно беспокоиться о возврате или выводе заявлений.

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

Я не слишком хорошо знаком с C++, но вы выбираете новое растровое изображение в своем новом DC до его создания? Кроме того, когда вы вызываете CreateCompatibleBitmap, я думаю, вы хотите использовать свой экранный DC (тот, который вы использовали для создания DC назначения), а не совместимый DC. Итак, получите DC с помощью GetDC и передайте это как в CreateCompatibleDC, так и в CreateCompatibleBitmap.

+0

Моя мысль тоже - вам нужно создать растровое изображение, прежде чем вы его выберите. –

0
  • Скачать http://www.gdiwatch.com/, он может показать вам, где ошибка (это может быть сделано, чтобы работать с VS 2008, тоже - просто скопировать ключи реестра вручную из VS2005 в VS2008 каталогов)

  • Есть вы пытались сделать CreateCompatibleBitmap() перед вызовом SelectObject()?

  • Получает ли GetBitmap() нового растрового изображения правильный размер, т. Е. Является ли новый битмап действительным?

Остальное, кажется, все в порядке, должно работать так, как я полагаю. Работает ли он с другими StretchBltModes?

+0

Не могли бы вы рассказать, в какой процедуре сделать работу за 2008 год – coolcake

+0

- Установить версию на 2005 год - Зайти в реестр с помощью regedit, найти 'GDIWatch' - Вы найдете ключи в ульях 2005 года - Скопируйте их точно к соответствующим ульям 2008 года Это не сложно, всего несколько ключей. – Roel

0

Благодаря всем ребятам, которые подсматривали и предлагали решения, каким-либо образом после некоторой отладки я нашел проблему. Вот решение !!!

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

Но цветные изображения отображаются как черно-белые. – coolcake

Смежные вопросы