4 Replies Latest reply on May 26, 2011 7:03 AM by D Baron

    Open a disk image file and crop it to an Image control

    D Baron Level 1

      Hi Folks,

       

      I am trying to allow my users (in a browser) to select/open a disk file (image type) so that they can see it and then save it to the server.  I can use the FileReference object just fine, and load its 'result' directly into a MX:Image control.  However, before I do that I would like to crop the selected imaged to a square shape.  I'd also like to resize the image down, but that will come later, once I get the cropping working.

       

      I am essentially taking the FileReference result bytearray and converting that to a BitmapData object.  Then, I 'extract' a square of data from that BitmapData object into a new BitmapData object.  Then I need to get *that* BitmapData object into the mx:image control.  I tried using a Bitmap to do so, however the resulting mx:image, while 'sized' correctly, displays as a blank white region.  All along, the variables seem to be 'full' of data and seem to have properly set attributes.  I've looked up quite a few sites that demonstrate cropping, and copying images, but they always start out with 'pre-loaded' images.  I have modeled my code after theirs, where appropriate.

       

      Here is my code:

       

                //this gets called when the user clicks a button to 'look for a disk file'

                  private function setPhoto():void
                  {
                      //create the FileReference instance
                      _fileRef = new FileReference();
                     
                      _fileRef.addEventListener(Event.SELECT, onFileSelected);
                     
                      //listen for the file has been opened
                      _fileRef.addEventListener(Event.COMPLETE, onFileLoaded);
                     
                      var arr:Array = [];
                      arr.push(new FileFilter("Images", ".gif;*.jpeg;*.jpg;*.png"));
                      _fileRef.browse(arr); //then let go and let the event handlers deal with the result...

       

                  }
                 
                  private function onFileSelected(evt:Event):void
                  {
                      _fileRef.load(); //the result of the 'load' will be handled by the 'complete' handler
                  }
                 
                  private function onFileLoaded(evt:Event):void
                  {
                      var tempLoader:Loader = new Loader();
                      tempLoader.loadBytes(_fileRef.data);
                      tempLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderComplete);
                     
                      //imgPhoto.source = _fileRef.data;  //this would work just fine, though, it wouldn't be cropped
                  }
                 
                  private function onLoaderComplete(event:Event):void
                  {
                      var loaderInfo:LoaderInfo = LoaderInfo(event.target);
                      var loadBD:BitmapData = new BitmapData(loaderInfo.width,loaderInfo.height);
                      //ok, now that we have the 'original' file in the bitmap data, we can crop it and then later resize it
                      //so, we need a 'square' of image cropped out of the original
                      //so...first we get a square of the 'full size' image
                      //if the image is taller than wide, we will take a square as wide as the image, and as tall as it is wide, starting 5% down from the top
                      //if the image is wider than tall, we will take a square as tall as the image, and as wide as it is tall, from the horizontal middle
                      var curW:int = loadBD.width;
                      var curH:int = loadBD.height;
                      var cropX:int = 0;
                      var cropY:int = 0;
                      var cropW:int = curW;
                      var cropH:int = curH;
                      var needCrop:Boolean = true; //default is to crop
                      var croppedBD:BitmapData;
                     
                      if (curH > curW)
                      {
                          cropY = Math.round(curH * .05); //start at 5% down
                          cropH = cropW;
                      }
                      else if (curW > curH)
                      {
                          cropX = Math.round(curW/2) - Math.round(curH/2); //start at the middle, go 'back' by half the height
                          cropW = cropH;
                      }
                      else
                      {
                          needCrop = false; //it's already a square!  nothing to do (aside from the resize)
                      }
                     
                      if (needCrop)
                      {
                          croppedBD = new BitmapData(cropW, cropH); //at this point it is 'empty', so fill it up
                          var fillPoint:Point = new Point(0,0); //since we're gonna fill into the top, left pixel on down and over
                          var fillRect:Rectangle = new Rectangle(cropX,cropY,cropW,cropH);
                          croppedBD.copyPixels(loadBD,fillRect,fillPoint);
                      }
                      else
                      {
                          croppedBD = loadBD;
                      }
                     
                      imgPhoto.source = new Bitmap(croppedBD);  //this produces a properly sized, but blank-white image
                  }

       

      And here is the mxml for the image:

      <mx:Image id="imgPhoto" x="40" y="126" maxWidth="200" maxHeight="200" />

       

      Thanks!

       

      -David