This was posted to flexcoders today. Here’s the problem: we’ve got a transparent PNG that is loaded into a <mx:Image /> control. Normally this control handles PNG transparency just fine. However, someone posted an example of a problematic PNG. If you set the source of the Image control to use the URL for the PNG on the server, then the image loads fine with transparency. But if you try to embed the image using the @Embed syntax, then the transparency is ignored and an ugly background color shows up.
I don’t know really exactly where the problem lies. The Image component (which is really just a glorified SWFLoader) should load the exact same image whether it’s loading from a URL or an embedded asset. But it doesn’t, and the test case posted on flexcoders proves this. Now, whether there’s something weird about the image I have no idea. But the fact is that it should have transparency and using @Embed within an Image component breaks the transparency.
So here’s a solution. Basically what I did was extend the SWFLoader class and change part of the loadContent() method. To do this I had to make a copy of the SWFLoader class (I called it BaseSWFLoader) and change the needed methods to protected instead of private. Once I did that I was able to create a subclass that could override loadContent and act differently for embedded assets.
The approach I took was to get the ByteArray of the embedded asset, then load that ByteArray using the loadBytes method of the Loader class. When I tried loading the problematic embedded PNG using loadBytes, it magically loaded fine with the transparency.
There’s a trick here, which is to set the mimeType of the embedded asset. If you set the mimeType to application/octet-stream, then when it gets handled by the custom ByteArraySwfLoader class I created we can get access to the raw ByteArray of the embedded asset. This means we can pass the ByteArray to a Loader component, which will be able to handle it using the loadBytes() method. If you don’t set the mimeType of the embedded asset then you don’t get the ByteArray of the asset, instead you just get a Bitmap object.
The small example below shows the problematic PNG loaded using both the <Image /> control and my custom class. Both work fine if we’re loading via a URL. But if we’re loading by using the @Embed syntax then the normal Image component messes up the transparency.