skip to content

Codificant imatges en base64 amb Adobe Air

by ViTo • August 16, 2011 1 comment

Lately I have been playing with the Adobe Air platform. Having previous experience with web development, I think it’s a great way to get something up and running pretty quickly across multiple platform and with capabilities not yet widely available via HTML5. Basically, you can still do most of your development using html + css + js and refer to the flash libraries hooked into the framework for some additional capabilities, such as capturing video from a webcam or playing an mp3 file.

Get Adobe Air

This past week, I was involved with a pet project that performs some picture resizing and then dynamically shows them to the user without saving a temp file. One of the ways to do that in Adobe Air would be through the data URI scheme, which allows to embed the actual image source into its declaration encoded as a base64 string.

Here’s an example I got from Wikipedia:


So, going back to my application, the workflow goes something like this:

All these steps can be easily performed with the functionalities available within the Air framework except step #5. I’ve been unable to locate a javascript library that allows the conversion between a binary ByteArray object and an encoded base64 string. So I just translated an equivalent ActionScript3 (as3) library I came across here into javascript.

Then, using the library you can easily do something like this without saving the dynamic image into a temp file:

	var BmpData = new air.BitmapData( WIDTH, HEIGHT, true, 0x000000);
	/* BmpData manipulation */

	var jpgEncoder = new window.runtime.com.adobe.images.JPGEncoder();
	var jpeg = jpgEncoder.encode(BmpData);
	var b64string = Base64.encode(jpeg).toString();	
	$("").attr("src", "data:image/jpg;base64," + b64string).appendTo("body");

And here’s the whole code of the base64 Air javascript library:

/* Base64 library for Javascript.
* Based on: Ma Bingyao code.
* Optimized by: Jean-Philippe Auclair  / jpauclair.wordpress.com
* Adapted to JS by: Francesc Calvo / vito@vito.es
* Copyright (C) 2007 Ma Bingyao 
* LastModified: Aug 17, 2011
* This library is free.  You can redistribute it and/or modify it.
*/
var Base64 =
{
encode : function( data  /*air.ByteArray() */){
	 if (!data) return;

	 var out = new air.ByteArray();
	 var encChar = this._encodeChars;

	 data.position = 0;   
     out.length = (2 + data.length - ((data.length + 2) % 3)) * 4 / 3;

	 var i = 0;
     var r = data.length % 3;   
     var len = data.length - r;   
     var c;

     while (i < len) {   
          //Read 3 Characters (8bit * 3 = 24 bits)
          c = data.readUnsignedByte() << 16 | data.readUnsignedByte() << 8 | data.readUnsignedByte();              i += 3;           //Convert to 4 Characters (6 bit * 4 = 24 bits)           c = (encChar[c >>> 18] << 24) | (encChar[c >>> 12 & 0x3f] << 16) | (encChar[c >>> 6 & 0x3f] << 8 ) | encChar[c & 0x3f];           out.writeInt(c);      }                                  if (r == 1) {     //Need two "=" padding              c = data[i];           c = (encChar[c >>> 2] << 24) | (encChar[(c & 0x03) << 4] << 16) | 61 << 8 | 61;
          out.writeInt(c);
     }   
     else if (r == 2) { //Need one "=" padding   
          c = data[i++] << 8 | data[i];              c = (encChar[c >>> 10] << 24) | (encChar[c >>> 4 & 0x3f] << 16) | (encChar[(c & 0x0f) << 2] << 8 ) | 61;
          out.writeInt(c);
     }   

     out.position = 0;
     return out.readUTFBytes(out.length);   
     },

decode : function (str){
	 if (!str) return;

	 var decChar = this._decodeChars;
     var c1, c2, c3, c4;
     var i, len, out;   

	 len = str.length;   
     i = 0;   
     out = new air.ByteArray();   
     var byteString = new air.ByteArray();   
     byteString.writeUTFBytes(str);

     while (i < len) 
     {   
         //c1   
         do {   
             c1 = decChar[byteString[i++]]; 
         } while (i < len && c1 == -1);   
         if (c1 == -1) break;   

         //c2       
         do {   
             c2 = decChar[byteString[i++]]; 
         } while (i < len && c2 == -1);   
         if (c2 == -1) break;    

         out.writeByte((c1 << 2) | ((c2 & 0x30) >> 4));   

         //c3   
         do {   
             c3 = byteString[i++];
             if (c3 == 61) return out;   

             c3 = decChar[c3];   
         } while (i < len && c3 == -1);   
         if (c3 == -1) break;   

         out.writeByte(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2));   

         //c4   
         do {   
             c4 = byteString[i++];
             if (c4 == 61) return out;

             c4 = decChar[c4];   
         } while (i < len && c4 == -1);   
         if (c4 == -1) break;   

         out.writeByte(((c3 & 0x03) << 6) | c4);   

     }   
     return out;   
},

_encodeChars : function(){
     var encodeChars = new Array();

     var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     for (var i = 0; i < 64; i++){
          encodeChars.push(chars.charCodeAt(i));
     }
     return encodeChars;
}(),

_decodeChars: function(){
    var decodeChars = new Array();

     decodeChars.push(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,   
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,   
     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,   
     -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,   
     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,   
     -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,   
     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
	return decodeChars;
}()

};

I’ll upload the code to github in the next few days so you can easily download the whole javascript file.

Comments RSS

  1. VILIC

    Hmm…

    var encodeChars = new Array();
    var chars = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”;
    for (var i = 0; i < 64; i++){
    encodeChars.push(chars.charCodeAt(i));
    }

    Equals

    var encodeChars = "ABCD…".split("");

    And, you can use something like

    var decodeChars = [-1, -1, …];