Image Size & App Memory Useage

My test image is a 10,753 x 7571 pixel transparent png, which is 13.3MB in the Finder view and 77.6/117.6MB when opened in CS6 Photoshop.

If I open this image into a Window picture variable with no depth the Activity Monitor says the app’s memory jumps from 10.5MB to 640.9MB.

I know the current process I am working on will not require any image to be more 5142 pixels in width or height. In an effort to reduce the amount of memory required by the app when a image is being opened it is immediately reduced in size to a maximum width or height of 5,200 pixels before being assigned to a window variable. After reducing the size of the image before assigning it to a window variable for later use the application’s memory in Activity Monitor is reduced from 640.9MB to 73.4MB.

Here is the initial code I use to reduce the image size whereas PickFilePic, PickFileName, PickFileParent are properties of Window1

  Dim PickFile as FolderItem
  Dim PickFilePic2 as Picture
  Dim Smaller as Double
  Dim SmallerWidth, SmallerHeight as Integer
  
  PickFile = GetOpenFolderItem("")
  
  If PickFile <> Nil then
    PickFilePic = Picture.Open(PickFile)
    PickFileName = Left(PickFile.Name, Instr(PickFile.Name, ".") - 1)//Name of Picture File Less Extension
    PickFileParent = PickFile.Parent//Parent Folder of Picture File
    
    Smaller = Min(5200 / PickFilePic.Width, 5200 / PickFilePic.Height)
    SmallerWidth = Smaller * PickFilePic.Width
    SmallerHeight = Smaller * PickFilePic.Height
    PickFilePic2 = New Picture(SmallerWidth, SmallerHeight)
    PickFilePic2.Graphics.DrawPicture PickFilePic, 0, 0, SmallerWidth, SmallerHeight, 0, 0, PickFilePic.Width, PickFilePic.Height
    
    PickFilePic = PickFilePic2
    PickFileURL.Text = PickFile.AbsolutePath
  Else
    Return
  End If

Is this memory use correct?

Given that PickFilePic2 will no longer exist after this code fires in a button’s action event would setting PickFilePic2 to Nil with an additional line of code be of any advantage - i.e. would it cause the temporary picture to be set to nil a fraction of second sooner or would it actually take longer since its another line of code to read before the event is completed?

PickFile2 would be nil’d a tiny fraction of a second sooner but not enough sooner that you would ever be able to tell

Your image should be 310MB in size roughly (1075375714 bytes) so if it’s using 640MB of memory, then it sounds like either you or the framework is keeping a second copy around for some reason? I believe I’ve seen cases where this happens…

Or maybe you are ending up with the old-style Picture object which has Picture + Mask as two separate items : that could account for the double-size memory.

What does Picture.Open() provide, I wonder : old or new-style picture object?

Not sure what the situation is these days but I know a long time ago DrawPicture on a Mac would cause an additional copy of the picture to be cached which had the effect of doubling the memory usage. The solution I used at the time was to set the UseOldRenderer property of the graphics object to True. However, I cannot remember if I needed to do this for the source, destination or both.

From the Language Reference:

I’ve experimented a little more by adding a pushbutton and a window property to hold the picture. The pushbutton code is:

  Dim PickFile as FolderItem
  
  PickFile = GetOpenFolderItem("")
  If PickFile <> Nil then
    PickFilePic = Picture.Open(PickFile)
    PickFilePic.Mask = Nil
  Else
    Return
  End If

I then opened Activity Monitor and kept opening the same picture into the window’s picture property several times.

The first time I pressed the button the app’s memory initially jumped up to 640.2MB as the picture was assigned to the window property. Shortly thereafter as the mask was set to nil for the window property it jumped down to 329.4MB. I am opening the same png with transparency as mentioned before from disk while running 10.9.5.

The strange thing is that after pressing the button several more times opening the same picture in the same variable the application’s memory (in the ide) has grown. By the fifth time I pressed the button the size of the app’s memory had jumped to 1.25GB before the mask was set to nil. The size of the memory required after the mask was set to nil climbed as follows (in MB): 329.4, 330.2, 330.3, 330.5, & 331.10.

Is this a memory leak?

Does it happen in a built/compiled app too?

Yes, it does. To make sure nothing else was causing the problem I created a new blank project and first added a image property to the window. I then added a pushbutton to the window with the following code:

  Dim PickFile as FolderItem
  
  PickFile = GetOpenFolderItem("")
  
  If PickFile <> Nil then
    PickFilePic = Picture.Open(PickFile)
  Else
    Return
  End If

A then pressed the button several times, waiting for the image to load into the window variable each time. Activity Monitor reported the following memory usage: 637.8, 638.1, 638.2, 638.5

A tiff produced 328.6, 329.1, 329.2

I also tried a smaller jpg that started with a memory usage of 45MB, but it would typically grow .1 MB every time or every two times it was opened.

10.9.5 OS X on 2.8 Ghz Quad-Core Intel Xeon

I found some code at the following url (http://documentation.xojo.com/index.php/Runtime) and inserted in the previous button action event. Here are the results of pressing the button four times and opening the same png picture each time. The first number is the memory in the text filed, while the reminder are from the listbox. The first group of numbers are from the IDE and the second are from a compiled app.

  Dim PickFile as FolderItem
  
  PickFile = GetOpenFolderItem("")
  
  If PickFile <> Nil then
    ListBox1.DeleteAllRows
    TextField1.Text = ""
    PickFilePic = Picture.Open(PickFile)
    
    Dim lastObjectIndex As Integer = Runtime.ObjectCount - 1
    For i As Integer = 0 To lastObjectIndex
      Listbox1.AddRow(Str(Runtime.ObjectID(i)))
      Listbox1.Cell(ListBox1.LastIndex, 1) = Runtime.ObjectClass(i)
      Listbox1.Cell(ListBox1.LastIndex, 2) = Str(Runtime.ObjectRefs(i))
    Next
    TextField1.Text = Str(Runtime.MemoryUsed)
    
  Else
    Return
  End If

IDE:

661300928

171100675	Array	1
171100867	Picture	1
171100803	Picture	1
7403715	FolderItem	1
8310451	Delegate	1
8356307	TextField	1
8126787	Listbox	5
8158195	TextField	2
8168067	Delegate	1
8158387	PushButton	3
26028883	Window1.Window1	3
5036691	MenuItem	1
5037251	MenuItem	1
5037475	MenuItem	1
5038019	MenuItem	1
5034307	MenuItem	1
5035827	MenuItem	1
5034723	MenuItem	1
5090563	MenuItem	1
5034883	MenuItem	1
5031571	QuitMenuItem	1
5090435	MenuItem	1
5086899	MainMenuBar.MainMenuBar	11
5088963	MDIWindow	1
5085987	App	2

661381136

7855427	Array	1
7853907	Picture	1
7618115	Picture	1
25934531	FolderItem	1
29531859	Delegate	1
8356307	TextField	1
8126787	Listbox	5
8158195	TextField	2
8168067	Delegate	1
8158387	PushButton	3
26028883	Window1.Window1	3
5036691	MenuItem	1
5037251	MenuItem	1
5037475	MenuItem	1
5038019	MenuItem	1
5034307	MenuItem	1
5035827	MenuItem	1
5034723	MenuItem	1
5090563	MenuItem	1
5034883	MenuItem	1
5031571	QuitMenuItem	1
5090435	MenuItem	1
5086899	MainMenuBar.MainMenuBar	28
5088963	MDIWindow	1
5085987	App	2

661947472

25749315	Array	1
26085123	Picture	1
25738067	Picture	1
4234083	FolderItem	1
4774227	Delegate	1
8356307	TextField	1
8126787	Listbox	5
8158195	TextField	2
8168067	Delegate	1
8158387	PushButton	3
26028883	Window1.Window1	3
5036691	MenuItem	1
5037251	MenuItem	1
5037475	MenuItem	1
5038019	MenuItem	1
5034307	MenuItem	1
5035827	MenuItem	1
5034723	MenuItem	1
5090563	MenuItem	1
5034883	MenuItem	1
5031571	QuitMenuItem	1
5090435	MenuItem	1
5086899	MainMenuBar.MainMenuBar	46
5088963	MDIWindow	1
5085987	App	2

661766496

4550467	Array	1
4542515	Picture	1
4543315	Picture	1
171089955	FolderItem	1
26280739	Delegate	1
8356307	TextField	1
8126787	Listbox	5
8158195	TextField	2
8168067	Delegate	1
8158387	PushButton	3
26028883	Window1.Window1	3
5036691	MenuItem	1
5037251	MenuItem	1
5037475	MenuItem	1
5038019	MenuItem	1
5034307	MenuItem	1
5035827	MenuItem	1
5034723	MenuItem	1
5090563	MenuItem	1
5034883	MenuItem	1
5031571	QuitMenuItem	1
5090435	MenuItem	1
5086899	MainMenuBar.MainMenuBar	62
5088963	MDIWindow	1
5085987	App	2

Compiled App:

657391152

4377587	Array	1
4985395	Picture	1
5001875	Picture	1
6831667	FolderItem	1
7195859	Delegate	1
4362819	TextField	1
43239955	Listbox	5
43240531	TextField	2
43241187	Delegate	1
42991763	PushButton	3
5297075	Window1.Window1	3
5330211	MenuItem	1
5330707	MenuItem	1
5327091	MenuItem	1
5327379	MenuItem	1
5327747	MenuItem	1
5328163	MenuItem	1
5328739	MenuItem	1
5325955	MenuItem	1
5325827	MenuItem	1
5354627	QuitMenuItem	1
4444259	MenuItem	1
4445875	MainMenuBar.MainMenuBar	11
4446067	MDIWindow	1
4445955	App	2

658092896

43987571	Array	1
5021251	Picture	1
5042211	Picture	1
43516115	FolderItem	1
6251619	Delegate	1
4362819	TextField	1
43239955	Listbox	5
43240531	TextField	2
43241187	Delegate	1
42991763	PushButton	3
5297075	Window1.Window1	3
5330211	MenuItem	1
5330707	MenuItem	1
5327091	MenuItem	1
5327379	MenuItem	1
5327747	MenuItem	1
5328163	MenuItem	1
5328739	MenuItem	1
5325955	MenuItem	1
5325827	MenuItem	1
5354627	QuitMenuItem	1
4444259	MenuItem	1
4445875	MainMenuBar.MainMenuBar	31
4446067	MDIWindow	1
4445955	App	2

658424496

43998643	Array	1
43805043	Picture	1
43987859	Picture	1
5547379	FolderItem	1
4385571	Delegate	1
4362819	TextField	1
43239955	Listbox	5
43240531	TextField	2
43241187	Delegate	1
42991763	PushButton	3
5297075	Window1.Window1	3
5330211	MenuItem	1
5330707	MenuItem	1
5327091	MenuItem	1
5327379	MenuItem	1
5327747	MenuItem	1
5328163	MenuItem	1
5328739	MenuItem	1
5325955	MenuItem	1
5325827	MenuItem	1
5354627	QuitMenuItem	1
4444259	MenuItem	1
4445875	MainMenuBar.MainMenuBar	48
4446067	MDIWindow	1
4445955	App	2

659011072

43755667	Array	1
43539155	Picture	1
43747171	Picture	1
5814355	FolderItem	1
6902707	Delegate	1
4362819	TextField	1
43239955	Listbox	5
43240531	TextField	2
43241187	Delegate	1
42991763	PushButton	3
5297075	Window1.Window1	3
5330211	MenuItem	1
5330707	MenuItem	1
5327091	MenuItem	1
5327379	MenuItem	1
5327747	MenuItem	1
5328163	MenuItem	1
5328739	MenuItem	1
5325955	MenuItem	1
5325827	MenuItem	1
5354627	QuitMenuItem	1
4444259	MenuItem	1
4445875	MainMenuBar.MainMenuBar	64
4446067	MDIWindow	1
4445955	App	2

I know this is not what you are concerned with, but it looks like there may be a leak of MenuBar objects?

4445875	MainMenuBar.MainMenuBar	64

I forgot to mention that the above was done with 2014 3.2 so I downloaded 2015 2.2 and a compiled show similar results of growing memory, but the the leak with the menubar objects appears to be less. I ran the app and clicked the button 4 times with results of 10, 14, 18, and 22. I then quit the app and clicked the same button four more times using the same image and the results were 11, 15, 19, and 23. Hope that helps.