Resize Flex Image correctly and add Bitmap smoothing

If you have ever used the Flex Image component, set its minWidth / minHeight or percentWidth / percentHeight you may have noticed some strange layout issues, and that the scaled quality is not that good. You can use 3rd party Image components to get round these issues, or this very simple load handler on the image. When using these properties, the Image component itself is NOT changed, rather the content within it. So it may appear to have scaled down, but the outer bounds of the Image component (not the bitmap within it) remain the original size.

Also, when scaling the Image component, bitmap smoothing is not enabled, and as it is private you cant do anything about it - so your scaled down image is a bit jagged. There are 3rd party Image components to get round these issues, or this very simple load handler on the image...

 
private function imageLoaded(event:Event):void 
{ 
    var img:Image = event.target as Image; 

    // re set the image source to a new Bitamp that is created from the current image 
    // bitmap data, but this time with smoothing enabled 	
    img.source = new Bitmap( Bitmap(img.content).bitmapData, "auto", true ); 

    // Set the scaling of the image to 20px 	
    img.scaleX = img.scaleY = (20 / img.contentHeight); 
} 

Encoding image byte data as a String.

I was recently working with ways to hide (or obscure) images in an application's source code. I'm not sure there's many uses for encoding image data in a string; It's certainly not an easy or efficient way of working with images.  

Never the less though here's a few notes on converting images to strings of byte data and back. First step was to write a small application that could load up an image and parse its data into a String format that could be copied/pasted/saved.



<mx:Application 	xmlns:mx="http://www.adobe.com/2006/mxml" 	xmlns:local="*" 	layout="vertical" 	xmlns:net="flash.net.*" xmlns:display="flash.display.*"> 
 <mx:Script> 
 <![CDATA[ 
 [Bindable] 			private var text:String = ""; 
 private var loader:Loader; 
 
private function process( bytes:ByteArray ) :void 
 { 
    bytes.position = 0; 
    var str:String = ""; 
 
    for(var i:int=0; i < bytes.length; i++)
    { 
        var byte:String = bytes.readUnsignedByte().toString(16); 
 
        if(byte.length<2) 
            byte= "0" + byte;  					str += byte; 				}  				text = str; 
    } 
 
    private function load( ) :void 
    {
        if(!loader) 					loader = new Loader(); 
        loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onLoadComplete );
        loader.load( new URLRequest(urlInput.text) ); 
    } 
 
    private function onLoadComplete( e:Event ) :void 
    { 
        process( (e.target as LoaderInfo).bytes ); 
    } 
 ]]> 	</mx:Script> 
 
<mx:TextArea text="{text}" width="100%" height="100%" /> 	
<mx:TextInput id="urlInput" width="100%" /> 	
<mx:Button id="processBtn" label="Process" click="load( )" />  
</mx:Application>
 

The main part of this is the process method, which takes a ByteArray and converts it into a string. In this case the bytes are supplied from the loaded image via the LoaderInfo object. This application will then display the string in a big text area. (The string may well be very long!).

Second step is a little class that extends the Flex Image component and adds one property, byteSource, which it exposes as a getter/setter.  Below is the code for the setter:

 
public function set byteSource( val:String ) :void 
{ 
    var newBytes:ByteArray = new ByteArray(); 
    var dataArr1:Array = val.split(""); 
    var dataArr2:Array = []; 
 
    for( var j:int=0; j < dataArr1.length; j+=2 ) 
    { 
        dataArr2.push("0x"+dataArr1[j]+dataArr1[j+1]);
    } 
 
    for( var k:int=0; k < dataArr2.length; k++ ) 
    { 
        newBytes[k] = dataArr2[k]; 	}  	this.source = newBytes;
        _byteSource = val;
    }
}

This method takes a string like the one generated from the application above, converts it into a ByteArray, and assigns that to the components source property. This component can now be added to any project, and supplied a string from which it will display an image. E.g.

 
<controls:ByteImage byteSource="{ImageObject.image}" /> 

Where ImageObject.image is a static constant String of image data.