Tuesday, October 02, 2007

Flash "memory leak" in Director

For our current project, I've been trying to nail down what appeared to be a memory leak in Director with respect to Flash members. It's not technically a "leak," per se, but the end result is the same: memory gets allocated that cannot be de-allocated. After some investigation, here's what is going on.

I was using Flash members to store bitmap graphics for a project which required cartoony characters. These character graphics were 256x512 pixels in size, so I could either use 16k to store a Flash member that contained all the frames for the animation, or I could use 512k per frame of animation to store the bitmaps. No brainer, right?

Well, there's a problem. Apparently, if you use "the posterFrame" property of a Flash member, Director's engine will become unable to unload it. My guess is that this is because it is flagged as "changed" in the same way that a bitmap cast member cannot be unloaded after you change its image using its image property. I suppose this makes sense, because the posterFrame set would be lost if the member was unloaded.

So, basically, we have a situation where, if we store graphics in a Flash member and extract them via the posterFrame property, you can never unload them.

What to do? As with most things in Director, there is a workaround. Since the Flash member can never be unloaded when you set its posterframe, the trick is to not set its posterframe, but instead set the posterframe of a duplicate. Make a copy of the Flash member, yank the posterframes from that, and then erase it. The original Flash member can remain unloaded in this case, and the member which cannot be unloaded is instead erased. Here's the code:

on getFlashImage theMember, thePosterFrame

-- We can accept either a literal member reference, a string, or a number.
if (theMember.ilk = #member) then m = theMember
else m = member(theMember)

-- Duplicate the member, and set its posterframe
theTempMember = member(m.duplicate(), m.castlibnum)
theTempMember.posterframe = thePosterFrame

-- Grab the image
i = theTempMember.image.duplicate()

-- Erase the temporary member

-- Unload the original member

-- Return the image
return i

end getFlashImage

No comments: