2015-02-09 72 views
0

以下是我的代码(感谢其他人)阅读图像文件并返回Gdiplus :: Bitmap。我的问题是,在创建位图(它似乎工作)和调用代码时,我完成位图的代码(在底部)是正确的,我可以只调用delete pBitmap;Gdiplus ::位图释放内存

在此先感谢

HRESULT ImageUtilities::LoadImageFromFile(
    std::string path, 
    UINT destinationWidth, 
    UINT destinationHeight, 
    UINT frame, 
    Gdiplus::Bitmap **ppBitmap, 
    double *resX, 
    double *resY) 
{ 
    CComPtr<IWICBitmapFrameDecode> pSource; 
    CComPtr<IWICBitmapDecoder> pDecoder; 
    CComPtr<IWICFormatConverter> pConverter; 
    CComPtr<IWICBitmapScaler> pScaler; 

    // get image factory 
    IWICImagingFactory *pImageFactory = WICImagingFactory::GetInstance().GetFactory(); 

    // get/determine image decoder 
    HRESULT hr = pImageFactory->CreateDecoderFromFilename(MultiByteToUnicode(path).c_str(), NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &pDecoder); 

    // get the specified frame from the image 
    if (SUCCEEDED(hr)) 
    { 
     // Validate the given frame index nFrame 
     UINT nCount = 0; 
     // Get the number of frames in this image 
     if (SUCCEEDED(pDecoder->GetFrameCount(&nCount))) 
     { 
     if (frame >= nCount) 
      frame = nCount - 1; // If the requested frame number is too big, default to the last frame 
     } 

     // get the frame 
     if (SUCCEEDED(hr)) 
     { 
     hr = pDecoder->GetFrame(0, &pSource); 
     } 
    } 

    // get the image converter 
    if (SUCCEEDED(hr)) 
    { 
     // Convert the image format to 32bppPBGRA (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED) 
     hr = pImageFactory->CreateFormatConverter(&pConverter); 
    } 

    if (SUCCEEDED(hr)) 
    { 
     pSource->GetResolution(resX, resY); 
     // if a new width or height was specified, create an IWICBitmapScaler and use it to resize the image 
     if (destinationWidth != 0 || destinationHeight != 0) 
     { 
     UINT originalWidth, originalHeight; 
     hr = pSource->GetSize(&originalWidth, &originalHeight); 
     if (SUCCEEDED(hr)) 
     { 
      if (destinationWidth == 0) 
      { 
       FLOAT scalar = static_cast<FLOAT>(destinationHeight)/static_cast<FLOAT>(originalHeight); 
       destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth)); 
      } 
      else if (destinationHeight == 0) 
      { 
       FLOAT scalar = static_cast<FLOAT>(destinationWidth)/static_cast<FLOAT>(originalWidth); 
       destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight)); 
      } 

      hr = pImageFactory->CreateBitmapScaler(&pScaler); 
      if (SUCCEEDED(hr)) 
      { 
       hr = pScaler->Initialize(pSource, destinationWidth, destinationHeight, WICBitmapInterpolationModeCubic); 
      } 
      if (SUCCEEDED(hr)) 
      { 
       hr = pConverter->Initialize(pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, 
        NULL, 
        0.f, 
        WICBitmapPaletteTypeMedianCut 
       ); 
      } 
     } 
     } 
     else // Don't scale the image. 
     { 
     hr = pConverter->Initialize(pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, 
      NULL, 
      0.f, 
      WICBitmapPaletteTypeMedianCut 
      ); 
     } 
    } 

    // finally create a GDI+ Bitmap from the WIC bitmap. 
    if (SUCCEEDED(hr)) 
    { 
     // calculate stride and necessary buffer size 
     UINT uWidth, uHeight; 
     hr = pConverter->GetSize(&uWidth, &uHeight); 
     const UINT cbStride = 4 * uWidth; 
     const UINT cbBufferSize = cbStride * uHeight; 

     // allocate buffer then copy pixels 
     // NOTE: we are responable to delete this buffer when we delete the Bitmap 
     BYTE *pBitmapBuffer = new BYTE[cbBufferSize]; 

     WICRect rc; 
     rc.X = 0; rc.Y = 0; rc.Width = uWidth; rc.Height = uHeight; 
     hr = pConverter->CopyPixels(&rc, cbStride, cbBufferSize, (BYTE *)pBitmapBuffer); 

     // create a Gdiplus::Bitmap object 
     Gdiplus::Bitmap *pBitmap = new Gdiplus::Bitmap(uWidth, uHeight, cbStride, 
     PixelFormat32bppPARGB, pBitmapBuffer); 

     delete[] pBitmapBuffer; 

     if (Gdiplus::Ok != pBitmap->GetLastStatus()) 
     { 
     return E_FAIL; 
     } 

     *ppBitmap = pBitmap; 
    } 

    return hr; 
} 

我改变了上面下面,事情似乎运行更好

Gdiplus::Bitmap *pBitmap = new Gdiplus::Bitmap(uWidth, uHeight, PixelFormat32bppPARGB); 

     Gdiplus::BitmapData bd; 
     Gdiplus::Rect rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); 
     Gdiplus::Status status = pBitmap->LockBits(&rect, Gdiplus::ImageLockModeWrite, PixelFormat32bppPARGB, &bd); 
     if (Gdiplus::Ok == status) 
     { 
     memcpy(bd.Scan0, pBitmapBuffer, cbStride*uHeight); 
     status = pBitmap->UnlockBits(&bd); 
     } 


     delete[] pBitmapBuffer; 

回答

0

内存管理看起来是正确的给我。如果您没有将数据指针传递给位图构造函数(或者将其传递给NULL指针),则不负责释放图像数据。

这不是一个好主意,假设新的位图对象的步幅是你期望的。在这种情况下,我认为它会生效,但如果将像素格式更改为不是4字节大小的格式,GDI +可能会在行中添加一些填充。要做到这一点干净,你应该从BitmapData中读取步幅,并单独复制每一行。

您也可以在Bitmap被锁定时直接使用BitmapData中的Scan0来执行CopyPixels调用,而不分配中间缓冲区。