5 Replies Latest reply on Jun 9, 2008 3:00 PM by slaingod

    image select, resize and locally store (flex3 air example)

    Starlover_jacob Level 1
      Hi there,
      After a few days of struggling with images, resize functions and file dialog boxes I created a nice example application that shows how you can select an image, resize it and save the resized image in the application storing directory.
      I hope you can profit from it.
      Greets, jacob

      example code for flex 3 air.


      <?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;
      public var imageFile:File;
      public var fileresultimage:Object;
      public var fileresultlabel:Object;
      // File.applicationStorageDirectory gets you to the local storage dir
      //On Windows, this is the "projectname" directory
      //(for example, C:\Documents and Settings\application data\projectname).
      // On Mac OS, it is /Users/userName/Documents.
      public var docsDir:File = File.applicationStorageDirectory;

      public function imageFileDialog(image:Object,label:Object):void
      {

      fileresultimage=image;
      fileresultlabel=label;
      var imagesFilter:FileFilter =
      new FileFilter("Foto (*.jpg, *.gif, *.png)", "*.jpg;*.gif;*.png");
      if(imageFile==null)
      {
      imageFile = new File();
      }
      imageFile.addEventListener(Event.SELECT, imageSelected);
      imageFile.browseForOpen("Select an Image",[imagesFilter]);
      }
      // if there is a file selected
      public function imageSelected(event:Event):void
      {
      var newFile:File = event.target as File;

      //if there is a file object on the screen
      if(fileresultimage!=null)
      fileresultimage.source=imageFile.url;

      //if there is a label object on the screen
      if(fileresultlabel!=null)
      fileresultlabel.text=imageFile.url;

      if (newFile.exists==true)
      {
      var loader:Loader = new Loader();
      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleImageComplete);
      loader.load(new URLRequest(imageFile.url));
      }
      }

      // when load of the selected image is complete we save a smaller version of it.
      public function handleImageComplete(event:Event):void
      {

      var loader:Loader = Loader(event.target.loader);
      // width and heigt of selected image
      var originalimgwidth:Number=event.target.width;
      var originalimgheight:Number=event.target.height;

      //put original image into bitmapdata
      var bitmapje:BitmapData;
      bitmapje=new BitmapData(originalimgwidth, originalimgheight, true, 0x00000000);
      //bitmapje.draw(loaderInfo.loader.content,null,null,null,null,true);//null object reference
      bitmapje.draw(loader.content,null,null,null,null,true);
      // call the resize function and give the original image,maxx,and maxy with it.
      var thumb:BitmapData=resizeimage(bitmapje,150,150);

      var newimagefile:File=new File();
      // T = Thumbnail
      // 1 = next id in the db
      // for now we use a random number
      var random:Number= Math.random();
      random = Math.ceil(random*100);// to get a positive number

      var filenameForSave:String="T"+random; //new filename;
      newimagefile=docsDir.resolvePath("Thumbs/" + filenameForSave + ".png"); //image path


      var stream:FileStream = new FileStream; // create new filestream
      stream.open(newimagefile, FileMode.WRITE); // open filestream
      var data:ByteArray = encodeToPng(thumb); // convert bitmapdata to a png bytearry
      stream.writeBytes(data, 0, data.length); // writing the image
      stream.close();
      // show the saved thumb
      savedthumb.source=newimagefile.nativePath;
      bitmapje=null;
      thumb=null;

      }
      // resize function
      private function resizeimage(image:BitmapData,maxx:Number,maxy:Number):BitmapData
      {
      var bmp:BitmapData =image;
      var true_width:Number = bmp.width;
      var true_height:Number = bmp.height;
      var resize:Boolean=false;

      if (true_width>maxx) resize=true;
      if (true_height>maxy) resize=true;
      if (resize==true)
      {
      var width:Number=maxx;
      var height:Number = (width / true_width) * true_height;
      true_width=width;
      true_height=height;

      if (true_height>maxy)
      {
      height=maxy;
      width = (height/true_height)*true_width;
      }
      else
      {
      width=true_width;
      height=true_height;
      }
      }
      else
      {
      width=true_width;
      height=true_height;
      }
      //new calculated width and heigt relative to the given maxx and maxy.
      width=Math.ceil(width);
      height=Math.ceil(height);


      //create a new image object with the calculated widht and height for the smaller image
      var mysmallimage:Image=new Image();
      mysmallimage.width=width;
      mysmallimage.height=height;

      //new matrix for smaller image
      var m : Matrix = new Matrix() ;
      //scale the matrix to the correct sizes.
      m.scale( mysmallimage.width / bmp.width, mysmallimage.height / bmp.height ) ;
      //draw the image into the image object
      mysmallimage.graphics.beginBitmapFill( bmp, m, false, true ) ;
      mysmallimage.graphics.drawRect( 0, 0, mysmallimage.width, mysmallimage.height ) ;
      mysmallimage.graphics.endFill();

      //put the smaller image into bitmapdata so it can be returned.
      var littlebitmapdata:BitmapData=new BitmapData(mysmallimage.width,mysmallimage.height,true,0x00000000);
      littlebitmapdata.draw(mysmallimage);

      // set the temporary small image to null so the GC can remove it from the memmory.
      mysmallimage=null;
      bmp=null;

      //returning the small image.
      return littlebitmapdata;
      }

      // encoder to png
      private function encodeToPng(bmd:BitmapData):ByteArray
      {
      var png:PNGEncoder= new PNGEncoder();
      return png.encode(bmd);
      }
      ]]>
      </mx:Script>
      <!--<mx:Image id="tempimage" x="404" y="36" complete="temploadcomplete()"/>-->
      <mx:Image id="myimg" x="10" y="55" width="314" height="227" verticalAlign="middle" horizontalAlign="center"/>
      <mx:TextInput id="imageurl" x="53" y="303" width="160" maxWidth="160"/>
      <mx:Button x="221" y="303" label="Bladeren" click="imageFileDialog(myimg,imageurl)"/>
      <mx:Image x="346" y="55" id="savedthumb"/>
      <mx:Text x="23" y="0" text="Original image with limit width and height to show it on the screen." height="47" width="177"/>
      <mx:Text x="346" y="0" text="Local stored thumbnail"/>
      </mx:WindowedApplication>




      To bad the attach code button still isn't fixed :(
        • 1. Re: image select, resize and locally store (flex3 air example)
          basakarunava
          Hi Jacob,
          Thanks very much for the solution. I was trying to solve the problem for days, without success.
          Will you be able to provide the backend script for saving the file data?
          Also, may I post your link to other forums, so that others may benefit?
          • 2. Re: image select, resize and locally store (flex3 air example)
            Starlover_jacob Level 1
            Hi there,

            Will you be able to provide the backend script for saving the file data?Will you be able to provide the backend script for saving the file data?

            This example is created for a desktop application. Saving the file is included in this example, it saves in the application storage directory.
            // File.applicationStorageDirectory gets you to the local storage dir
            //On Windows, this is the "projectname" directory
            //(for example, C:\Documents and Settings\application data\projectname).
            // On Mac OS, it is /Users/userName/Documents.

            If you attempt to use certain functionality in a website, you need other functionality for storing the image on the server. There are lots of examples on that one.. Perhaps i need it in the future. If i do i will post an example on the forum.

            Also, may I post your link to other forums, so that others may benefit?
            Sure you may post the example on other websites and forums.
            I found it difficult to find nice examples, so the more the better ;)
            Just put underneath the example something like:
            Created By: Jacob Hingst From Holland
            No copyright attached, so free for your use.
            • 3. Re: image select, resize and locally store (flex3 air example)
              Hi Jacob,

              I've tried out your script as it seems to be a good starter for an application I'm about to write.
              In my case, I don't want to create tiny thumbnails, just smaller 900x900 pixel images from 8 megapixel camera images.
              If I use a maxx and maxy of 900, the resulting "thumbnail" shows some ugly jaggies, as if the image wasn't resized with "smooth" turned on. Any idea if it's possible to get even smoother results?

              PS. Not sure if it's worth mentioning, but I'm converting from and to JPEG rather than PNG...
              • 4. Re: image select, resize and locally store (flex3 air example)
                Starlover_jacob Level 1
                Hi there,
                First of all, sorry for the late answer.

                About the usage of pngencode.. i use jpgencode now two, because pngencode will create large images (mb instead of kb).

                About the smoothing of the resized photo: I noticed it. If you resize the photo in photoshop and compare it with the resized photo of this functionality, the results are not as good as the photoshop resize. I tried to solve this problem, but i could not get better results than this. I desided that in my project the users will not notice this difference bycause they will not look at it as we (professional designers) do.
                So the result was acceptable.

                If you would find a better solution of resizing the image with good results, just let me know.. I'm very interested.
                Greets, Jacob
                • 5. Re: image select, resize and locally store (flex3 air example)
                  slaingod Level 1
                  There is a way to turn bitmap smoothing on for live images.

                  http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=2&postI d=4001

                  The easiest way to send the image to a server (in either Flex or AIR) is to use the base64 encoding and just send the data back as a POST variable in your HTTPService request, though this does double the size of the data to be sent essentially. Ie. 50k jpeg takes like 80-100k of upload. Then on your server you simply decode the base64 parameter and write directly to disk.