2 Replies Latest reply: Mar 9, 2008 6:50 AM by Starlover_jacob RSS

    base 64 image??

    jefflemon
      How can I display a base 64 encoded image in flex (its from a database)
        • 1. Re: base 64 image??
          Starlover_jacob Community Member
          Hi, I am working on the same problem.. saving an image into a blob (sqlite)(in air).
          and of course it needs to get out again. I guess we have to look at bitmapdata to get the image from the db and show it on the screen..
          Only i am first struggling with an image resize function.. because i don't want to save an 6mb image into my db.
          I know how to get a smaller image in php and save it into a blob(mysql) db.. so if it helps you, just let me know.

          I think we can help each other.

          Greetz, jacob
          • 2. Re: base 64 image??
            Starlover_jacob Community Member
            Here the solution,
            a flex3 air example of encoding and decoding an image.

            I use a custom encoder and decoder because for some reason the flex debugger crashes on the following line:
            var b64encodedThumb:Base64Encoder = new Base64Encoder();
            b64encodedThumb.encodeBytes(thumbpixels);
            var b64ThumbString:String = b64encodedThumb.flush(); // here the line it crashes on.

            I wanted to save the image as b64 string into the sqlite db as a BLOB, but it gets BIG! So be warned.
            The example i created works and can save the image into a sqlite database, but i am not gonna use this. (my image 150x150 pixels turns out to be 300kb inside the db, so i am gonna save the images locally and save a link to that image into my database.
            (you'll might ask why it turns out to be so big? Well when you create a bitmapdata of your image, you end up with all the pixels of that image without compression. So what you actually save is a bmp, and as you know a bmp is much bigger than a jpg or a png)

            What i didn't try is first save the image as png in a temp folder and then store that image as an encoded string into the db.
            After correct saving delete the temp image. That way it could result to a smaller size, but i don't know if that's possible.

            The example:


            <?xml version="1.0" encoding="utf-8"?>
            <mx:WindowedApplication xmlns:mx=" http://www.adobe.com/2006/mxml" layout="absolute">
            <mx:Script>
            <![CDATA[
            import mx.graphics.codec.PNGEncoder;
            // loader to show image
            private var myloader:Loader;

            // keystring for base64 encoding and decoding.
            public var keyStr:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";



            public function clicktogetphoto():void
            {
            // image to base64 and back to image
            // original image
            var bmpData:BitmapData = new BitmapData( myimage.width, myimage.height, false, 0xe4e4e4 ) ;
            bmpData.draw( myimage,null,null,null,null,true );

            // to bytearray
            var bounds:Rectangle = new Rectangle(0,0,bmpData.width,bmpData.height);
            var fullpixels:ByteArray = bmpData.getPixels(bounds);
            fullpixels.position = 0; //set pointer to begin of bytearray

            // to base64 string
            var b64String:String=encode64(fullpixels);

            // You could put here the save function to save the base64 image into the sqlite database.
            //(save also width and heigt of image into database so you can recreate the image when you get it out of the db.)

            // base64 string decoded back to bytearray (before this you get the base64 image from the database to show it on screen.
            var decodedstring:ByteArray=decode64(b64String);
            decodedstring.position=0;//set pointer to begin of bytearray

            // create a new bitmapdata for the new image.
            var rect:Rectangle = new Rectangle(0,0,bmpData.width,bmpData.height);
            var newbmpdata:BitmapData=new BitmapData(rect.width, rect.height, false, 0Xe4e4e4);
            newbmpdata.setPixels( rect , decodedstring);

            // encode the new bitmapdata to a png so you can show it on screen.
            var imageByteArray:ByteArray = encodeToPng(newbmpdata);

            // new loader for the new image.
            myloader= new Loader();
            myloader.contentLoaderInfo.addEventListener (Event.COMPLETE, onConvertFinished);
            myloader.loadBytes(imageByteArray,null);

            }

            public function onConvertFinished(evt:Event):void
            {
            mynewloadedimage1.addChild(myloader.content);
            }

            // function to encode bitmapdata to a png bytearray
            private function encodeToPng(bmd:BitmapData):ByteArray
            {
            var png:PNGEncoder= new PNGEncoder();
            return png.encode(bmd);
            }


            private function encode64(byteArr:ByteArray):String
            {
            var output:String = "";
            var chr1:Number, chr2:Number, chr3:Number;
            var enc1:Number, enc2:Number, enc3:Number, enc4:Number;
            var i:Number = 0;
            do
            {
            chr1 = byteArr[i++];
            chr2 = byteArr[i++];
            chr3 = byteArr[i++];
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2))
            {
            enc3 = enc4 = 64;
            }
            else if (isNaN(chr3))
            {
            enc4 = 64;
            }
            output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
            keyStr.charAt(enc3) + keyStr.charAt(enc4);
            }
            while (i < byteArr.length);
            return output;
            }


            // decode image string to bytearray
            private function decode64(input:String):ByteArray
            {
            var output:ByteArray = new ByteArray();
            var chr1:Number, chr2:Number, chr3:Number;
            var enc1:Number, enc2:Number, enc3:Number, enc4:Number;
            var i:Number = 0;
            // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
            //input = input.replace(/[^A-Za-z0-9+/=]/g, "");
            do
            {
            enc1 = keyStr.indexOf(input.charAt(i++));
            enc2 = keyStr.indexOf(input.charAt(i++));
            enc3 = keyStr.indexOf(input.charAt(i++));
            enc4 = keyStr.indexOf(input.charAt(i++));
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            output.writeByte(chr1);
            if (enc3 != 64)
            {
            output.writeByte(chr2);
            }
            if (enc4 != 64)
            {
            output.writeByte(chr3);
            }
            }
            while (i < input.length);
            return output;
            }
            ]]>
            </mx:Script>
            <mx:Image id="myimage" source="assets/image.png" x="0" y="0"/>
            <mx:Button id="mybuttonGetphoto" click="clicktogetphoto()" label="getphoto" x="404" y="416"/>
            <mx:Image x="501" y="0" id="mynewloadedimage1" width="340" height="287"/>
            </mx:WindowedApplication>