GDI + and Delphi, PNG resource, DrawImage, ColorConversion & # 8594; From memory

I started playing with GDI + in Delphi 2009. Among the things I wanted to do was load a PNG resource and apply color conversion to it when drawing it to a Graphics object. I am using the code provided at http://www.bilsen.com/gdiplus/ . To do this, I just added a new constructor to TGPBitmap, which uses the same code that is located in <www.codeproject.com> /KB/GDI-plus/cgdiplusbitmap.aspx(++) or <www.masm32.com> / board / index.php? topic = 10191.0 (MASM), converted to Delphi.

For reference, the converted code is as follows:

constructor TGPBitmap.Create(const Instance: HInst; const PngName: String; dummy : PngResource_t); const cPngType : string = 'PNG'; var hResource : HRSRC; imageSize : DWORD; pResourceData : Pointer; hBuffer : HGLOBAL; pBuffer : Pointer; pStream : IStream; begin inherited Create; hResource := FindResource(Instance, PWideChar(PngName), PWideChar(cPngType)); if hResource = 0 then Exit; imageSize := SizeofResource(Instance, hResource); if imageSize = 0 then Exit; pResourceData := LockResource(LoadResource(Instance, hResource)); if pResourceData = nil then Exit; hBuffer := GlobalAlloc(GMEM_MOVEABLE, imageSize); if hBuffer <> 0 then begin try pBuffer := GlobalLock(hBuffer); if pBuffer <> nil then begin try CopyMemory(pBuffer, pResourceData, imageSize); if CreateStreamOnHGlobal(hBuffer, FALSE, pStream) = S_OK then begin GdipCheck(GdipCreateBitmapFromStream(pStream, FNativeHandle)); end; finally GlobalUnlock(hBuffer); pStream := nil; end; end; finally GlobalFree(hBuffer); end; end; end; 

This code works fine, as I can download the downloaded image without any problems. However, if I try to apply color conversion when drawing it, I get a wonderful error: (GDI + Error) Out of Memory.

If I load a bitmap from a file or create a temporary one, to which I draw an initial raster map, and then use a temporary one, then it works just fine.

What bothers me if I take a C ++ project from codeproject , add the same PNG as a resource and use the same color conversion (in other words, do the same thing that I do in Delphi in the same order and with those the same function calls that happen in one DLL), then it works.

C ++ code is as follows:

  const Gdiplus::ColorMatrix cTrMatrix = { { {1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.5, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0} } }; Gdiplus::ImageAttributes imgAttrs; imgAttrs.SetColorMatrix(&cTrMatrix, Gdiplus::ColorMatrixFlagsDefault, Gdiplus::ColorAdjustTypeBitmap); graphics.DrawImage(*pBitmap, Gdiplus::Rect(0, 0, pBitmap->m_pBitmap->GetWidth(), pBitmap->m_pBitmap->GetHeight()), 0, 0, pBitmap->m_pBitmap->GetWidth(), pBitmap->m_pBitmap->GetHeight(), Gdiplus::UnitPixel, &imgAttrs); 

Delphic colleague:

 const cTrMatrix: TGPColorMatrix = ( M: ((1.0, 0.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 0.5, 0.0), (0.0, 0.0, 0.0, 0.0, 1.0))); var lImgAttrTr : IGPImageAttributes; lBitmap : IGPBitmap; begin // ... lImgAttrTr := TGPImageAttributes.Create; lImgAttrTr.SetColorMatrix(cTrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); aGraphics.DrawImage ( lBitmap, TGPRect.Create ( 0, 0, lBitmap.Width, lBitmap.Height ), 0, 0, lBitmap.Width, lBitmap.Height, UnitPixel, lImgAttrTr ); 

I absolutely do not know what could be causing this problem, and Google did not help. Any ideas, comments and explanations are highly appreciated.

+4
source share
2 answers

I can’t fully follow your code, so let’s look at this more general statement: an external memory error often occurs when converting colors, if not the source and target 32bbp bitmaps.

+1
source

I had the same problem. The pixel format of an image loaded from a resource is not really PixelFormat32bppARGB. It must be, but it seems that it is not. My solution that works:

 // Create local bimap with PixelFormat32bppARGB flag Gdiplus::Bitmap local_bmp(WIDTH, HEIGHT, PixelFormat32bppARGB); Gdiplus::Graphics gfx(&local_bmp); // Redraw the original bitmap on the local without transformation. gfx.DrawImage(&resource_bmp, 0, 0); // ... set the matrix and attributes // Do the transformation on the local_bmp screenGfx.DrawImage(&local_bmp,Rect(0, 0, WIDTH, HEIGHT), 0, 0, WIDTH, HEIGHT, Gdiplus::UnitPixel, &imgAttrs); 
+1
source

Source: https://habr.com/ru/post/1303909/


All Articles