1

I use a flash program in my website to resize pictures before transfert, for preserve my bandwidth.

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...

This the 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<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));

    }

}

And this function :

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 > _MAX_WIDTH || _bitmap.height > _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);

    }

}

Here the imgHelper 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 > 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 < 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 < 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 > img.height) {
                if (img.height>rH)
                    rH = img.height * (rW / img.width);
                else{ // do not resize
                    rH = img.height;
                    rW = img.width;
                }
        }
        else {
            if (img.width>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 > 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 < 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() {

    }

} 

AsyncJPGEncoder :

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<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<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 >= 0 ) {
            var fillbits:BitString = new BitString();
            fillbits.len = bytepos+1;
            fillbits.val = (1<<(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);
    }


}
}

Thank you so much for your help!

Fred

Fred_Me
  • 15
  • 5
  • Could you post your `imgHelper` class? I suspect the BitmapData is creates may not have transparency. Also, you seem to be using a JPEG encoder. JPEG does not support transparency, you should use a PNG encoder instead. – shanethehat Jul 25 '11 at 09:14
  • I added the imgHelper class. I will try to find the PNGencoder! Thanks for help – Fred_Me Jul 25 '11 at 09:51
  • You have a lot of inflated code. For example your imgHelper should extend the Image class. But back to your question I am a little confused. What I understand you are doing is taking an image that was downloaded from your server and resizing it and sending it back to your server? Resizing an image and sending it off to a server is like 20 lines or less of code. – The_asMan Jul 25 '11 at 19:30
  • Yes, it's true : i have a lot of inflated code! Because i'm not a flash programer and i picked a free code to transform it for my own usage. In fact, the total module does more: it allows the management of x image, resizes all on the client, can rotate clockwise or counterclockwise, and then sends the entire stream. But does not support transparency ... – Fred_Me Jul 26 '11 at 09:11

1 Answers1

0

As I mentioned in the comments, you should probably be using a PNG encoder rather than JPEG if you need to output transparency.

Looking at your imgHelper class, there are a couple of places where you create BitmapData objects, but do not specify that they should allow transparency. To do this they should look like:

new BitmapData(width,height,true,0);

The third parameter is setting transparency to true, and the fourth is removing the background color.

shanethehat
  • 15,460
  • 11
  • 57
  • 87
  • Thank you so much! I am going to try that and i will tell you if it works! – Fred_Me Jul 25 '11 at 10:16
  • I changed JPGEncoder by PNGEncoder, but an another class (AsyncJPGEncoder) is the problem now : very complicated to change... And JPGEncoder and PNGEncoder are very different... I don't know how to make corrections :/ – Fred_Me Jul 25 '11 at 12:56
  • It is a bit of a monster. Essentially you are going to need to extend the current PNGEncoder then break the encoding execution in a similar way to your JPEG class to remove the syncronous nature. – shanethehat Jul 25 '11 at 17:43
  • excuse my question but... why remove the syncronous nature? :/ – Fred_Me Jul 26 '11 at 09:13
  • I presumed that was a requirement because you are doing that currently. If you're happy for the encode to be synchronous then just use [PNGEncoder](https://github.com/mikechambers/as3corelib/blob/master/src/com/adobe/images/PNGEncoder.as), but you should consider why the code originally extended JPEGEncoder in the way it does. – shanethehat Jul 26 '11 at 09:18