title: Flash : preserve transparency when resizing picture
body: <p>I use a flash program in my website to resize pictures before transfert, for preserve my bandwidth.</p>
  
  <p>But, when i try to transfer a .png file with transparency, the resize don't maintain transparency in the .png file result.
  It's a problem for use it after...</p>
  
  <p>This the code :</p>
  
  <pre><code>public class ImageStrip extends MovieClip
  {
      var _img:Bitmap;
      public var _iHelper:imgHelper;
      public var fileName:String;
  
      public var isEncoding:Boolean=false;
      public var isDirty:Boolean = true;
  
      public var encodedByteArray:ByteArray;
      private var asyncEncoder:AsyncJPEGEncoder;
      private static const _MAX_WIDTH     : Number = 800;
      private static const _MAX_HEIGHT    : Number = 800;
  
      public function ImageStrip(img:Bitmap, fileName:String) {
  
  
          stripSelected.alpha=stripOver.alpha = 0;
          this.fileName=(fileName.substr(0, fileName.search("z-z-z-z")));
          var fSize:String = (fileName.substr(fileName.search("z-z-z-z") + 7));
          var fName:String;
          if (this.fileName.length&lt;15)
               fName = this.fileName;
          else
              fName =  this.fileName.substr(0,14)+'.. ';
          fName += " "+fSize;
  
          removeBT.addEventListener(MouseEvent.CLICK, eventRemoveClicked);
          _img = new Bitmap(img.bitmapData);
          caption.text = fName;
  
          _iHelper = new imgHelper(_img);
          _iHelper.addEventListener("invalidate", eventImageInvalidated);
          addChild(_iHelper);
          _iHelper.resizePic(44, 44, true);
          _iHelper.x = _iHelper.y = 4;
          addEventListener(MouseEvent.CLICK, eventMouseClicked);
          addEventListener(MouseEvent.ROLL_OVER, eventOver);
          addEventListener(MouseEvent.ROLL_OUT, eventOut);
          addEventListener(Event.ADDED_TO_STAGE, onAdded);
          pbar.mode = ProgressBarMode.MANUAL;
          pbar.reset();
          pbar.setProgress(0, 1);
          doEncode();
      }
  
      public function onAdded(e:Event):void 
      {
          removeBT.label =  Local.getInstance().getString("remove");
      }
  
      public function eventImageInvalidated(e:*=null) {
          pbar.reset();
          pbar.visible = true;
          pbar.setProgress(0, 1);
          doEncode();
      }
  
      public function doEncode() {
          if (!asyncEncoder){
              asyncEncoder = new AsyncJPEGEncoder(90);
              asyncEncoder.addEventListener("complete", eventJpgComleted);
              asyncEncoder.addEventListener("progress", eventJpgProgress);
          }
          else {
              asyncEncoder.cancel();
          }
          var btData:BitmapData = _iHelper.resizeBitmapData(_MAX_WIDTH, _MAX_HEIGHT);
          isEncoding = true;
          encodedByteArray = asyncEncoder.encode(btData);
      }
  
      private function eventJpgComleted(e:*) {
          isEncoding = false;
          isDirty = false;
          pbar.visible = false;
      }
      private function eventJpgProgress(e:ProgressEvent) {
          //trace('Progress : : ' + e.bytesLoaded / e.bytesTotal);
  
          var pbar:ProgressBar = pbar as ProgressBar;
          pbar.value = (e.bytesLoaded / e.bytesTotal);
      }
  
      public function set isUploading(value:Boolean) {
          pbar.indeterminate = value;
          pbar.visible = value;
      }
  
      public function set selected(flag:Boolean) {
          if (flag)
              TweenLite.to(stripSelected, 0.6, { autoAlpha:1 } );
          else
              TweenLite.to(stripSelected, 0.6, { autoAlpha:0 } );
      }
  
      private function eventOver(e:MouseEvent) {
          TweenLite.to(stripOver, 0.6, { autoAlpha:1 } );
      }
      private function eventOut(e:MouseEvent) {
          TweenLite.to(stripOver, 0.6, { autoAlpha:0 } );
      }
  
      private function eventRemoveClicked(E:MouseEvent) {
          dispatchEvent(new Event("removeStrip", true, true));
      }
  
      private function eventMouseClicked(e:MouseEvent) {
          e.stopImmediatePropagation();
          // not the remove button ...
          if (!(e.target is Button))
              dispatchEvent(new Event("stripClicked", true, true));
  
      }
  
  }
  </code></pre>
  
  <p>And this function :</p>
  
  <pre><code>public class imgBox extends MovieClip
  {
      public var _img                 : imgHelper;
      private var _MAX_WIDTH              : Number;
      private var _MAX_HEIGHT             : Number;
      private var boxFrame:MovieClip;
      private var statusMsg:TextField;
  
      public var byteData:ByteArray;
  
      [Embed(source="rotate_right.png")]
      [Bindable]
      public var iconSymbol1:Class; 
      [Embed(source="rotate_left.png")]
      [Bindable]
      public var iconSymbol2:Class;
  
      public function imgBox(w:Number,h:Number,_bitmap:Bitmap) 
      {
          _MAX_WIDTH = w;
          _MAX_HEIGHT = h;
  
          var borderColor:uint  = 0x666666;
          var borderSize:uint   = 1;
          var vMenu:verticalMenu;
  
          _img = new imgHelper(_bitmap);
          _img.addEventListener("invalidate", eventImageInvalidated);
          if ( _bitmap.width &gt; _MAX_WIDTH || _bitmap.height &gt; _MAX_HEIGHT ) 
               _img.resizePic(_MAX_WIDTH, _MAX_HEIGHT, false);
  
          boxFrame = new MovieClip;
          boxFrame.graphics.lineStyle(borderSize, borderColor);
          boxFrame.graphics.drawRect(0, 0, _img.width+4,_img.height+4);
          addChild(boxFrame);
  
          addChild(_img);
          boxFrame.x = 60 + _img.theImage.x;
          boxFrame.y = _img.theImage.y;
          _img.x = 62;
          _img.y = 2;
  
          //vMenu = new verticalMenu();
          //var myMenu:Array = new Array( { label:'Rotate', _function:eventRotateHit } );// ,
                                  //  { label:'Upload', _function:eventUploadHit } );
          //vMenu.buildMenu(myMenu);
  
  
  
          var  button:Button = new Button();
          //button.label = Local.getInstance().getString("rotateright");
          button.setStyle("icon", iconSymbol1);
  
          button.width = 48;          
          button.height = 48;         
          button.addEventListener(MouseEvent.CLICK, eventRotateHit);
          addChild(button);
  
          var  buttonbis:Button = new Button();
          //buttonbis.label = Local.getInstance().getString("rotate");
          buttonbis.setStyle("icon", iconSymbol2);
          buttonbis.width = 48;           
          buttonbis.height = 48;
          buttonbis.y = 60;
          buttonbis.addEventListener(MouseEvent.CLICK, eventRotateHit2);
          addChild(buttonbis);
  
      }       
  
      private function eventImageInvalidated(e:Event) {
          e.stopImmediatePropagation();
  
          dispatchEvent(new Event("invalidate", true, true));// invalidate for re-encoding the image.
  
      }
  
      private function eventUploadHit(e:*) {
          trace('Upload Hit');
          this.dispatchEvent(new Event("uploadImage"));
      }
  
      public function showStatus(msg:String) {
              TweenLite.to(boxFrame, 0.5, { height: _img.height + 24 } );
              var vMenu:verticalMenu = new verticalMenu();;
              if (statusMsg){
                  removeChild(statusMsg);
                  statusMsg = null;
              }
              statusMsg = new TextField();
              statusMsg.htmlText = msg;
              statusMsg.styleSheet = vMenu._textStyleSheet;
              statusMsg.width = _img.width;
              addChild(statusMsg);
              statusMsg.y = _img.height + 2;
              statusMsg.x = boxFrame.x + 10;
  
      }
  
      public function hideStatus(msg:String = "") {
              if (statusMsg){
                  removeChild(statusMsg);
                  statusMsg = null;
              }
              TweenLite.to(boxFrame, 0.5, { height: _img.height + 4 } );
      }
  
      private function eventRotateHit(e:*) {
          trace('rotate Image');
          if (statusMsg){
                  removeChild(statusMsg);
                  statusMsg = null;
              }
  
          _img.rotate(Math.PI / 2);
          _img.resizePic(_MAX_WIDTH, _MAX_HEIGHT, false);
          boxFrame.width = _img.width + 4;
          boxFrame.height = _img.height + 4;
  
          boxFrame.x = 60 + _img.theImage.x;
          boxFrame.y = _img.theImage.y;
  
      }
  
      private function eventRotateHit2(e:*) {
          trace('rotate Image');
          if (statusMsg){
                  removeChild(statusMsg);
                  statusMsg = null;
              }
  
          _img.rotate(Math.PI/-2);
          _img.resizePic(_MAX_WIDTH, _MAX_HEIGHT, false);
          boxFrame.width = _img.width + 4;
          boxFrame.height = _img.height + 4;
  
          boxFrame.x = 60 + _img.theImage.x;
          boxFrame.y = _img.theImage.y;           
  
      }
  
      public function dispose() {
  
      }
  
      public function prepare(w:Number, h:Number, q:Number) {
          var btData:BitmapData = _img.resizeBitmapData(w, h);
          byteData = new JPGEncoder(q).encode(btData);
  
      }
  
  }
  </code></pre>
  
  <p>Here the imgHelper code :</p>
  
  <pre><code>public class imgHelper extends MovieClip
  {
      public var tt:TextField;
      public var theImage:Bitmap;
      private var myMask:MovieClip;
  
  
      private var _boxDimW:Number;
      private var _boxDimH:Number;
  
  
  
  
      public function imgHelper(img:Bitmap=null) 
      {
          theImage = img;
          if (theImage)
              addChild(theImage);
           tt = new TextField;
          tt.text = '0%';
      /*  addChild(tt);*/
  
      }
  
      public override function get width():Number {
          return theImage.width;
      }
  
      public override function get height():Number {
          return theImage.height;
      }
      public  function get _scaleX():Number {
          return theImage.scaleX;
      }
      public  function set _scaleX(sx) {
           theImage.scaleX = sx;
      }
  
      public  function get _scaleY():Number {
          return theImage.scaleY;
      }
      public  function set _scaleY(sy:Number) {
           theImage.scaleY = sy;
      }
  
      public function load(url:String)
      {
          //trace('loading : ' + url);
          var loader:Loader = new Loader();
          loader.contentLoaderInfo.addEventListener(Event.COMPLETE, picLoaded);
          loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errLoading);
          loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
          var lContext:LoaderContext = new LoaderContext(true);
  
  
  
          var request:URLRequest = new URLRequest(url);
          try {
              loader.load(request,lContext);
  
  
          } catch (error:Error) {
              trace("Unable to load requested document.");
          }
  
      }
      private function progress(e:ProgressEvent)
      {
          tt.text = Math.round(e.bytesLoaded /e.bytesTotal *100) + '%';
      }
  
      private function errLoading(e:*)
      {
          tt.visible = false;
          dispatchEvent(new Event("imgLoaded",true,true));
      }
  
      private function picLoaded(e:*)
      {
          var picLoader:Loader = Loader(e.target.loader);
          theImage = Bitmap(picLoader.content);
          addChild(theImage);
  
          tt.visible = false;
          dispatchEvent(new Event("imgLoaded",true,true));
      }
  
      public function resizePic(rW:Number,rH:Number,crop:Boolean=false)
      {
          var img = theImage;
          _boxDimW = rW;
          _boxDimH = rH;
  
          if (img.width &gt; img.height)
          {
              img.width = rW;
              img.height = img.height * img.scaleX;
          }
          else
          {
              img.height = rH;
              img.width = img.width * img.scaleY;
          }
  
  
          if (crop)
          {
              if (img.width &lt; img.height)
              {
                  var oldScaleX = img.scaleX;
                  img.width = rW;
                  img.scaleY += img.scaleX-oldScaleX;
  
              }
              else
              {
                  var oldScaleY = img.scaleY;
                  img.height = rH;
                  img.scaleX += img.scaleY-oldScaleY;
  
              }
  
              maskIt(rW, rH);
  
          }
          else {
              if (img.height &lt; img.width) {
                  img.y=(rH-img.height)/2
              }
              else {
                  img.x=(rW-img.width)/2
  
              }
          }
  
  
  
      }
  
  
  
      public function resizeBitmapData (rW:Number, rH:Number):BitmapData {
          var img:Bitmap = new Bitmap(theImage.bitmapData);
          trace('resize bitmap : ' + img.height + '-' + img.width);
          trace('resize bitmap : ' + rH + '-' + rW);
          if (img.width &gt; img.height) {
                  if (img.height&gt;rH)
                      rH = img.height * (rW / img.width);
                  else{ // do not resize
                      rH = img.height;
                      rW = img.width;
                  }
          }
          else {
              if (img.width&gt;rW)
                  rW = img.width * (rH / img.height);
              else{ // do not resize
                      rH = img.height;
                      rW = img.width;
                  }
  
          }
  
          var bmpData:BitmapData = new BitmapData(rW, rH);
          var scaleMatrix:Matrix = new Matrix( rW / img.width , 0, 0, rH / img.height   , 0,0);
          var colorTransform:ColorTransform = new ColorTransform();
          bmpData.draw(theImage, scaleMatrix , colorTransform, null, null, true);
          return (bmpData);
      }
  
      public function rotate(dir:Number) {
  
  
          var workingImage:Bitmap = new Bitmap(theImage.bitmapData.clone());
          var bmpData:BitmapData = new BitmapData(workingImage.height, workingImage.width);
          if (dir &gt; 0)
              {
                  var transMatrix:Matrix = new Matrix(Math.cos(dir),Math.sin(dir),-Math.sin(dir),Math.cos(dir), workingImage.height,0);
              }
              else
              {
                  var transMatrix:Matrix = new Matrix(Math.cos(dir),Math.sin(dir),-Math.sin(dir),Math.cos(dir),0, workingImage.width);
              }
          var colorTransform:ColorTransform = new ColorTransform();
          bmpData.draw(workingImage, transMatrix, colorTransform, null, null, true);
          TweenLite.to(theImage, 0.5, { autoAlpha:0 } );
          //removeChild(theImage);
          theImage = new Bitmap(bmpData);
          addChild(theImage);
          //trace(theImage.y + '--' + theImage.x+'--'+theImage.height+'--'+theImage.width);
          if (theImage.height &lt; theImage.width) {
                  theImage.y += (_boxDimH - theImage.height) / 2
              }
              else {
                  theImage.x +=(_boxDimW-theImage.width)/2
  
              }
  
  
          theImage.alpha = 0;
          TweenLite.to(theImage, 1, { autoAlpha:1 } );
          trace('sending event !');
          dispatchEvent(new Event("invalidate", true, true));// invalidate for re-encoding the image.
      }
  
  
      public function maskIt(w:Number, h:Number)
      {
          if (myMask) {
              removeChild(myMask);
              myMask = null;
          }
          myMask = new MovieClip();
          myMask.graphics.beginFill(0xFFCC00);
          myMask.graphics.drawRect(0, 0, w,h);
          addChild(myMask);
          this.mask = myMask;
      }
  
      public function dispose() {
  
      }
  
  } 
  </code></pre>
  
  <p>AsyncJPGEncoder :</p>
  
  <pre><code>package Classes.utils
  {
  import flash.display.BitmapData;
  import flash.events.Event;
  import flash.events.EventDispatcher;
  import flash.events.IEventDispatcher;
  import flash.events.ProgressEvent;
  import flash.utils.ByteArray;
  import flash.utils.setInterval;
  import flash.utils.clearInterval;
  import com.adobe.images.JPGEncoder;
  import com.adobe.images.BitString;
  
  [Event(name="progress", type="flash.events.ProgressEvent")]
  [Event(name="complete", type="flash.events.Event")]
  [Event(name="cancel", type="flash.events.Event")]
  
  public class AsyncJPEGEncoder extends JPGEncoder implements IEventDispatcher
  {
      private var _dispatcher:EventDispatcher;
      private var _encodeTimer:int;
      private var DCY:Number;
      private var DCU:Number;
      private var DCV:Number;
      private var _ypos:int;
      public var attachedImageStrip:Number = -1;
  
      public function AsyncJPEGEncoder(quality:Number=50)
      {
          super(quality);
          _dispatcher = new EventDispatcher(this);
      }
  
      /**
       * Created a JPEG image from the specified BitmapData
       *
       * @param image The BitmapData that will be converted into the JPEG format.
       * @return a ByteArray representing the JPEG encoded image data.
       * @langversion ActionScript 3.0
       * @playerversion Flash 9.0
       * @tiptext
       */ 
  
  
      override public function encode(image:BitmapData):ByteArray
      {
          // Initialize bit writer
          byteout = new ByteArray();
          bytenew=0;
          bytepos=7;
  
          // Add JPEG headers
          writeWord(0xFFD8); // SOI
          writeAPP0();
          writeDQT();
          writeSOF0(image.width,image.height);
          writeDHT();
          writeSOS();
  
          // Encode 8x8 macroblocks
          DCY=0;
          DCU=0;
          DCV=0;
          bytenew=0;
          bytepos=7;
  
          _ypos = 0;
          flash.utils.clearInterval(_encodeTimer);
          _encodeTimer = flash.utils.setInterval(doEncode, 1, image);
  
  
          return byteout;
  
      }
      import flash.display.Stage;
  
      private function doEncode(image:BitmapData):void 
      {
          for (var xpos:int=0; xpos&lt;image.width; xpos+=8) 
          {
              RGB2YUV(image, xpos, _ypos);
              DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
              DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
              DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
          }
          _ypos += 8;
  
          var e:ProgressEvent =  new ProgressEvent(ProgressEvent.PROGRESS);
          if (_ypos&lt;image.height)
          {
              e.bytesLoaded = _ypos;
              e.bytesTotal = image.height;
              dispatchEvent(e);
          }
          else
          {
              flash.utils.clearInterval(_encodeTimer);
              e.bytesLoaded = image.height;
              e.bytesTotal = image.height;
              dispatchEvent(e);
              finishEncode();
          }
  
      }
  
      private function finishEncode():void 
      {
          // Do the bit alignment of the EOI marker
          if ( bytepos &gt;= 0 ) {
              var fillbits:BitString = new BitString();
              fillbits.len = bytepos+1;
              fillbits.val = (1&lt;&lt;(bytepos+1))-1;
              writeBits(fillbits);
          }
  
          writeWord(0xFFD9); //EOI
          //return byteout;
  
          var e:Event = new Event(Event.COMPLETE);
          dispatchEvent(e);
  
      }
  
      public function cancel():void 
      {
          var e:Event = new Event(Event.CANCEL);
          dispatchEvent(e);
  
          flash.utils.clearInterval(_encodeTimer);
      }
  
      public function getBytes():ByteArray
      {
          return byteout;
      }
  
  
      public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
          _dispatcher.addEventListener(type, listener, useCapture, priority);
      }
  
      public function dispatchEvent(evt:Event):Boolean{
          return _dispatcher.dispatchEvent(evt);
      }
  
      public function hasEventListener(type:String):Boolean{
          return _dispatcher.hasEventListener(type);
      }
  
      public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
          _dispatcher.removeEventListener(type, listener, useCapture);
      }
  
      public function willTrigger(type:String):Boolean {
          return _dispatcher.willTrigger(type);
      }
  
  
  }
  }
  </code></pre>
  
  <p>Thank you so much for your help!</p>
  
  <p>Fred</p>