3

I have an array of 11 white TBitmaps (32-bit 512x512 pixles = 1 MB) and I want to assign them to TPngImage array to reduce memory usage, I expect the 1 mb white bitmap to become 1.76 KB png and the memory usage drop dramatically I monitored that with task manager and the difference is just 0.824 MB why is that? and what is the best/fast way to lossless compress TBitmaps in memory?


for I := 0 to 10 do
begin
  Bitmaps[I] := TBitmap.Create;
  Bitmaps[I].PixelFormat := pf32bit;
  Bitmaps[I].Canvas.Pen.Color := clWhite;
  Bitmaps[I].SetSize(512,512);
  Bitmaps[I].Canvas.Rectangle(0,0,512,512);
end;

for I := 0 to 10 do begin Pngs[I] := TPngImage.Create; Pngs[I].Assign(Bitmaps[I]); Bitmaps[I].Free; end;


Update

Form @bummi research I think the best thing to do is to save the pngs in a memory stream array, that makes the difference 9.7 MB.


for I := 0 to 10 do
begin
  Png :=  TPngImage.Create;
  Png.Assign(Bitmaps[I]);
  Streams[I] := TMemoryStream.Create;
  Png.SaveToStream(Streams[I]);
  Bitmaps[I].Free;
  Png.Free;
end;
isa
  • 1,055
  • 16
  • 26
  • 3
    Your loop shows **11** bitmaps – OnTheFly Apr 25 '13 at 16:07
  • 1
    Did you tried minimizing your program window ? Task manager Working Set is not what you current used FastMM4 heap is. When you created your bitmaps it may or may not ask Windows for more heap, but when you freed them applicatio ndid not released it to windows immediately. If it do - it would be agonizingly slow application. Read about heap, memory managers and working set – Arioch 'The Apr 25 '13 at 16:21
  • 1
    Which version of Delphi? What is `TPngImage`? Are you sure it actually stores the compressed bitmap? And @Arioch'The is right, you cannot actually measure memory usage in a meaningful way using task manager. You need to get a decent tool. – David Heffernan Apr 25 '13 at 16:31
  • @DavidHeffernan well, i was wrong however. For 1MB bitmaps FastMM4 *would* directly use `VirtualAlloc`. The rest holds though – Arioch 'The Apr 25 '13 at 16:39
  • 3
    Reading through the sources of pngimage the data seem to be decompressed on loading(assigning) and compressed on saving. There seems to be no compressed data in memory. – bummi Apr 25 '13 at 17:21
  • @bummi, your research is worth to be an answer. – OnTheFly Apr 25 '13 at 18:07
  • I do wonder why you are concerned about 10MB. Or is the real problem greater. Compressing is a sound approach to save space but you trade CPU for memory. That might be a trade you are happy with. I'm not remotely surprised that the in memory storage is uncompressed. No fun trying to operate on a compressed image!! Hence my comment above. – David Heffernan Apr 25 '13 at 22:16
  • 1
    You might answer your own question .... – bummi Apr 26 '13 at 17:07

2 Answers2

1

When you released TBitmap you released two things:

  • memory to FastMM4 Delphi Heap manager
  • HBITMAP Windows GDI Handle

Sometimes Windows would shrink Working Set if you minimize all the program's windows and then restore them back, but it is not granted. Re-arranging process memory due to relatively small today 10MB difference would not be slowing down for nothing.

Read more starting with answer at https://stackoverflow.com/a/14380287/976391

http://fastmm.sourceforge.net/ comes with readme and demo how to measure memory usage inside process, if it makes you curios.

But if you really want to reduce RAM usage - then do not allocate it. Just make one TBitmap and assign al PNGs from it. Though again, your Widows clearly said that 10MB is not the figure to care about.


also, as user539848 spotted, you have 11 bitmaps, not 10. To avoid off-by-one errors you better do not use magical constants but use reliable compiler constructs.

for I := Low(Bitmaps) to High(Bitmaps) do
begin
  Bitmaps[I] :=...
Community
  • 1
  • 1
Arioch 'The
  • 15,799
  • 35
  • 62
0

The TPngImage keep all the pixels ready and unpacked in order to be able to quickly pain them. TPngImage takes about the same amount of memory as TBitmap.

So, simply assigning a bitmap to the TPngImage will just copy the data. Thus, after freeing the bitmap your program will end up using the same amount of memory.

If you expect memory usage to drop to 1.76 KB png, you have to compress the PNG to a memory stream and free the TPngImage, as the code in your update does.

Maxim Masiutin
  • 3,991
  • 4
  • 55
  • 72