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.