Rotate bitmap data in AS3 180deg for export

三世轮回 提交于 2019-12-10 15:48:18

问题


I have a bitmap in AS3 flash and I am sending it over to javascript using a base64 encoded jpg string.

All that works great. I need to send the img over scaled down, and rotated 180deg. The scaling works, but not the rotation. The rotation never takes. I know Im am obviously doing it wrong, but don't know the right way.

So basically I just need to rotate the image 180deg so when it is sent to javascript it is upside down.

Here is my transform code

var scaleFactor:int = 5;

var tempBitmap:BitmapData = new BitmapData(img.width/scaleFactor, img.height/scaleFactor);
var drawMatrix:Matrix = new Matrix(1/scaleFactor, 0, 0, 1 /scaleFactor );
drawMatrix.rotate(Math.PI); //180deg

tempBitmap.draw(img, drawMatrix);

回答1:


I think you need to translate your object after rotation otherwise it gets clipped so you don't see it, I did an example with a bitmap in a MovieClip just on the stage using CS5.

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.MovieClip;

var scaleFactor:int = 1;

var tempBitmap:BitmapData = new BitmapData(img.width, img.height);

var rotationMatrix:Matrix = new Matrix();
rotationMatrix.rotate(Math.PI);
rotationMatrix.translate(img.width, img.height);

tempBitmap.draw(box_mc, rotationMatrix);
var output:Bitmap = new Bitmap(tempBitmap);

addChild(output);

I didn't mess with the scaling, you can do that yourself I guess. The one I put on the stage is on the right, the bitmapData drawn one is top left of stage, and correctly inverted.

UPDATE

Also have a look at fl.motion.MatrixTransformer as per 32bitkid comment below!




回答2:


    /** flips individual blocks within a bitmap. Specifically used for doing sprite sheets. But I am sure you could find another use if you wanted.
     * @param   inBM
     * @param   spritePixelWidth
     * @param   spritePixelHeight
     * @param   inTransformType   :An enum from TransFiveConstants. Example: TransFiveConstants.VERTICAL_FLIP
     * @return  a bitmap data object where all the sprites within the sprite sheet bitmap have been rotated or transformed **/
    public static function makeTransformedCopyOfSpriteSheet(inSpriteSheet:BitmapData, spritePixelWidth:int, spritePixelHeight:int, inTransformType:int):BitmapData
    {
        //Do error check to make sure we evenly fit into the bitmap we are doing transforms on.
        CONFIG::debug{
            if ( (inSpriteSheet.width  % spritePixelWidth ) != 0) { throw new Error("input error: width  does not go in evenly! Fix it."); }
            if ( (inSpriteSheet.height % spritePixelHeight) != 0) { throw new Error("input error: height does not go in evenly! Fix it."); }
        }//CONFIG_debug

        //Calculate width and height in sprites of the inSpriteSheet.
        var widthInSprites :int = inSpriteSheet.width  / spritePixelWidth ;
        var heightInSprites:int = inSpriteSheet.height / spritePixelHeight;

        /** Bitmap that takes rectangle chunks out of inSpriteSheet, one at a time. **/
        var inBM:BitmapData = new BitmapData(spritePixelWidth, spritePixelHeight, true, 0x00);

        //Inlined copy of code in makeTransformedCopy
        ////////////////////////////////////////////////////////////////////
        var flipWidthHeight:Boolean = false;
        if (inTransformType == TransFiveConstants.ROTATE_NEG_90 ||
            inTransformType == TransFiveConstants.ROTATE_POS_90  )
        {
            flipWidthHeight = true;
        }
        var outWID:int = (flipWidthHeight ? inBM.height : inBM.width );
        var outHGT:int = (flipWidthHeight ? inBM.width  : inBM.height);
        ////////////////////////////////////////////////////////////////////

        /** Bitmap that is a [rotated||transformed] version of inputBitmap: **/
        var outBM:BitmapData = new BitmapData(outWID, outHGT, true, 0x00);


        var outputSpriteSheetWidth :int = outBM.width  * widthInSprites;
        var outputSpriteSheetHeight:int = outBM.height * heightInSprites;
        /** The output of this function **/
        var outputSpriteSheet      :BitmapData = new BitmapData(outputSpriteSheetWidth, outputSpriteSheetHeight, true, 0x00);

        //scan through the sheet with a rectangle and make all the transformed copies you need.
        //Every time you make a transformed chunk/copy, move it from the inSpriteSheet to the outputSpriteSheet

        /** Places the [rotated||transformed] chunk in correct spot on outputSpriteSheet **/
        var finalDestination:Point = new Point();

        var cookieCutter:Rectangle = new Rectangle();
        cookieCutter.width         = spritePixelWidth ;
        cookieCutter.height        = spritePixelHeight;
        for (var xx:int = 0; xx < widthInSprites ; ++xx){
        for (var yy:int = 0; yy < heightInSprites; ++yy){
            cookieCutter.x = xx * spritePixelWidth;
            cookieCutter.y = yy * spritePixelHeight;

            //Cut chunk out of main sprite sheet:
            inBM.copyPixels(inSpriteSheet, cookieCutter, ZZ, null, null, true);

            //Transform the chunk you cut out of the main sprite sheet:
            makeTransformedCopy(inBM, inTransformType, outBM);

            //Paste the transformed copy into the output sheet:
            finalDestination.x = xx * outBM.width; //if outBM is rotated, this width will NOT BE SAME AS spritePixelWidth
            finalDestination.y = yy * outBM.height;
            outputSpriteSheet.copyPixels(outBM, outBM.rect, finalDestination, null, null, true);
        }}//next [xx, yy]

        return outputSpriteSheet;
    }//makeTransformedCopyOfSpriteSheet

    /** Flips/Mirrors and Rotates using a 1D index scan remap. "transformUsingScanRemap"
     * 
     *  Meaning, I put data into a 1D array, then change my assumptions on the "scan order" ( left-right, then top-bottom is default convention),
     *  I can effectively rotate or transform the pixel input.
     * 
     *  All we have to do is pack the bitmap into a 1D array. (scanning left-right, top-to-bottom)
     *  And then convert it BACK to the 2D array using a different formula assuming the data is packed via a different scan order.
     * 
     *  EXAMPLE:
     *  If we change our assumption to assume it is left-right, then BOTTOM-to-top, and make a formula for mapping 1D indexes
     *  to 2D values based on that scan order assumption, we achieve a vertical flip.
     * 
      * @param  inBM            :Bitmap we are making a transformed copy of.
      * @param  inTransformType :The enum for the type of [transform||rotation] to use. For values check TransFiveConstants.as
      * @param  outputBitmap    :Supply this to OVERWRITE an existing bitmap instead of create a NEW bitmap for output.
      * @return a transformed or rotated bitmap **/
    public static function makeTransformedCopy(inBM:BitmapData, inTransformType:int, outputBitmap:BitmapData = null):BitmapData
    {
        //If the bitmap is being ROTATED, we will have to flip the output width and height.
        var flipWidthHeight:Boolean = false;
        if (inTransformType == TransFiveConstants.ROTATE_NEG_90 ||
            inTransformType == TransFiveConstants.ROTATE_POS_90  )
        {
            flipWidthHeight = true;
        }

        var outWID:int = (flipWidthHeight ? inBM.height : inBM.width );
        var outHGT:int = (flipWidthHeight ? inBM.width  : inBM.height);

        //You can supply a reference to the OUTPUT of this function if you are doing some type of batch processing
        //And want to avoid repetitively constructing new intermediary bitmaps:
        if (outputBitmap == null)
        {
            var outputBitmap:BitmapData = new BitmapData(outWID, outHGT, true, 0x00);
        }
        else
        {
            if (outputBitmap.width  != outWID) { ICU.error("Bad output bitmap supplied. Size is wrong."); }
            if (outputBitmap.height != outHGT) { ICU.error("Bad output bitmap supplied. Size is wrong."); }
        }


        /** Max x index when remapping 1D values. **/
        var maxXXX:int = outWID - 1;
        /** Max y index when remapping 1D values. **/
        var YYYmax:int = outHGT - 1;

        /** Number of full columns, using 1D scan order for this orientation. **/
        var fullColumns:int = 0;

        /** Number of full rows, using 1D scan order for orientation specified. **/
        var fullRows:int = 0; 

        /**What is left over after we have calculated the rows or collumns we have. **/
        var remainder:int = 0;



        var curPix:uint;
        var index:int = ( -1);
        var trans:IntPoint = new IntPoint();

        inBM.lock();
        outputBitmap.lock();
        for (var yy:int = 0; yy < inBM.height; yy++) {
        for (var xx:int = 0; xx < inBM.width ; xx++) {

            ++index;

            //using 1D index position, remap that to correct 2D position.
            //To do different transforms and rotations, simply change your assumptions on how we
            //map from 1D to 2D.
            //Standard 1D to 2D assumes scan lines go left-right, then top-bottom. Row by row.
            //2D to 1D formula for standard: 
            //1D = (Y * width) + X.
            //how many full widths you can get out of 1D == Y. Remainder == X.
            //2D.Y = (1D/width);
            //2D.X = 1D - (2D.Y * width);

            if (inTransformType == TransFiveConstants.NO_TRANSFORM)
            {                                               //[1][2] Assumed scan order   (AKA 1D to 2D Mapping)
                fullRows  = (index / outWID);               //[3][4] used to get full 
                remainder = index - (fullRows * outWID);    //[5][6] rows and remainder.

                trans.iy = fullRows;
                trans.ix = remainder;
            }else
            if (inTransformType == TransFiveConstants.VERTICAL_FLIP)
            {                                               //[5][6] Assumed scan order  (AKA 1D to 2D Mapping)
                fullRows  = (index / outWID);               //[3][4] used to get full 
                remainder = index - (fullRows * outWID);    //[1][2] rows and remainder.

                trans.iy = YYYmax - fullRows;
                trans.ix = remainder;
            }else
            if (inTransformType == TransFiveConstants.ROTATE_NEG_90)
            {                                                   //[2][4][6] Assumed scan order  (AKA 1D to 2D Mapping)
                fullColumns = (index / outHGT);                 //[1][3][5] used to get full rows and remainder.
                remainder   = index - (fullColumns * outHGT);    

                trans.ix = fullColumns;
                trans.iy = YYYmax - remainder;
            }else
            if (inTransformType == TransFiveConstants.ROTATE_POS_90)
            {                                                   //[5][3][1] Assumed scan order  (AKA 1D to 2D Mapping)
                fullColumns = (index / outHGT);                 //[6][4][2] used to get full rows and remainder.
                remainder   = index - (fullColumns * outHGT);    

                trans.ix = maxXXX - fullColumns;
                trans.iy = remainder;
            }else
            if (inTransformType == TransFiveConstants.FLOOR_MIRROR)
            {                                               //[2][1] Assumed scan order   (AKA 1D to 2D Mapping)
                fullRows  = (index / outWID);               //[4][3] used to get full 
                remainder = index - (fullRows * outWID);    //[6][5] rows and remainder.

                trans.iy = fullRows;
                trans.ix = maxXXX - remainder;
            }
            else
            {
                throw new Error("Transform type not recognized");
            }

            //Copy and paste the pixel now that we know where to put it:
            curPix = inBM.getPixel32(xx, yy);
            outputBitmap.setPixel32(trans.ix, trans.iy, curPix);

        }}//next [xx, yy]
        inBM.unlock();
        outputBitmap.unlock();

        return outputBitmap;
    }//transformUsingScanRemap


来源:https://stackoverflow.com/questions/10813952/rotate-bitmap-data-in-as3-180deg-for-export

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!