0 Replies Latest reply on May 30, 2007 2:22 PM by UDev

    Trying to Crop and Resize an image

    UDev
      Hi all,

      I've got a project here where I need to be able to take an image loaded from a webserver, manipulate it and then output the result in a textual form. The three main things I need to be able to do is move, resize (both maintaining the aspect ratio, and not), and crop. I have all three working, however I've run into some very odd bugs when I try to resize and then crop.

      If I crop first, I can resize without problems - I can even crop multiple times before resizing without problems. The problems arise when I resize, and then crop. At this point the area that I try to select does not match where the mouse moves, all of the x values are short by about 20 px and all of the y's by about 10 px. When I actually do the crop the image does not shrink to fit the new size (which it does otherwise) and the content does not scale up to the size of the image. I've checked to make sure that the coordinate systems all match, and as far as I can see they should not be doing the things they're doing. Oddly enough, once I uncrop the image the mouse begins selecting the correct area again, but the image still does not scale properly. Can anyone see what's going wrong in my code? Is there something obvious that I'm missing?

      Notes:
      There is a canvas (named canvas) that overlays the image. I'm using that to draw the selection box as the mouse is dragged around. The variable 'g' is canvas's graphics object.

      /**
      * Crops the image using BitmapData
      * @param event The MouseEvent generated when the user unclicks the mouse
      */
      private function doCrop(event:MouseEvent):void
      {
      if (locked)
      {
      g.clear();
      if (!pt1.equals(pt2))
      {
      try {
      //If the image has been cropped before, convert the local points to points on the *original* image
      if (stack.length > 0)
      {
      pt1.x += last[last.length-1].x;
      pt1.y += last[last.length-1].y;
      pt2.x += last[last.length-1].x;
      pt2.y += last[last.length-1].y;
      }
      last.push(calcFrameOfReference(pt1, pt2));
      var rect:Rectangle = calcRectPoint(pt1, pt2); //This line calculates the bounding box

      //If the bounding rectangle is less than or equal to the size as this image
      if (rect.width < this.width && rect.height < this.height)
      {
      stack.push(getBitmapData(this)); //Get the Bitmap of this image, and push it onto the stack
      var output:BitmapData = new BitmapData(rect.width, rect.height); //Create a new buffer of size w x h
      var pt:Point = new Point(0,0); //Create a point from which you wish to copy (0,0 is the logical choice)
      output.copyPixels(stack[0],rect,pt); //Copy the pixels in the rectangle from the original image to the buffer
      this.source = new Bitmap(output); //Set our source to be the buffer
      }
      }
      catch (e:Error)
      {
      mx.controls.Alert.show("The area you selected is invalid. Please try again.","Error");
      }
      }
      else
      {
      mx.controls.Alert.show("Select a larger area. Please try again.","Error");
      }
      }
      else
      {
      mx.controls.Alert.show("Unable to crop while in incorrect mode\rThis shouldn't ever happen\rPlease report this to the person in charge", "Error");
      }
      //Clear point data to keep user from relpeatedly cropping without thinking (accidental doubleclicks)
      pt1.x = pt2.x = 0;
      pt1.y = pt2.y = 0;
      }



      /**
      * Uncrops the image by popping the last iteration of it off of the internal image stack
      */
      public function undo():void
      {
      //If we're in crop mode
      if (locked)
      {
      g.clear();
      if (stack.length > 0)
      {
      this.source = new Bitmap(stack.pop()); //Change our source back to the backup copy
      last.pop(); //Clear the point, since we're now back a step
      }
      else
      {
      // mx.controls.Alert.show("Unable to uncrop: You are already at the earliest version of this image", "Error");
      }
      }


      /**
      * Draws the selection box
      * @param event The MouseEvent that is generated by moving the mouse
      */
      private function drawMouseMove(event:MouseEvent):void
      {
      if (isClicked)
      { //Standard MouseMove code
      pt2.x = event.localX;
      pt2.y = event.localY;
      //Calculate the rectangle to draw
      var rect:Rectangle = calcRectPoint(pt1, pt2);
      //Drawing code
      g.clear(); //Clear all drawn graphics
      g.beginFill(0x0000FF,0.15); //Reset the style (since clear, clears it)
      g.drawRect(rect.x, rect.y, rect.width, rect.height); //Draw a new rectangle
      g.endFill(); //Appears in some docs, but not all. May not be needed, does not appear to have any effect...
      this.addChildAt(canvas, this.numChildren-1); //Place the canvas overtop of everything
      }
      }


      /**
      * Does the actual resizing of the images
      * @param event The MouseEvent generated when you move the mouse
      */
      private function resizeMouseMove(event:MouseEvent):void
      {
      //Using stage coord system here because
      //A) The code gets really twitchy if you try and use local
      //B) The original code used the global ones, and it works perfectly
      pt2.x = event.stageX;
      pt2.y = event.stageY;
      //Grab the mouse cursor in the local coords
      var localPt:Point = parent.globalToLocal(pt2);
      var newWidth:int;
      var newHeight:int;
      //If the mouse is to the right of the origin of the image
      if (localPt.x >= this.x + minResize)
      {
      newWidth = localPt.x - this.x;
      //If the width is different
      if (this.explicitWidth != newWidth)
      {
      this.explicitWidth = newWidth;
      canvas.explicitWidth = newWidth;
      //The clutch: Set the height to be appropriate for the aspect ratio
      if (aspectRatio > 0 && maintainAspectRatio)
      {
      this.explicitHeight = (newWidth * aspectRatio);
      canvas.explicitHeight = (newWidth * aspectRatio);
      }
      }
      }

      //Now we do the same thing again
      //It looks like you shouldn't need this part, but you do
      //If you do not do this part the resize gets very twitchy
      if (localPt.y >= this.y + minResize)
      {
      newHeight = localPt.y - this.y;
      if (this.explicitHeight != newHeight)
      {
      this.explicitHeight = newHeight;
      canvas.explicitHeight = newHeight;
      if (aspectRatio > 0 && maintainAspectRatio)
      {
      this.explicitWidth = (newHeight * aspectRatio);
      canvas.explicitWidth = (newHeight * aspectRatio);
      }
      }
      }
      }