Rotate bitmap data in AS3 180deg for export

I have a bitmap in AS3 flash, and I'm sending it to javascript using a base64 encoded jpg string.

Everything works great. I need to send img in reduced and rotated 180 degrees. Scaling works, but not rotation. Rotation never happens. I know that I'm obviously doing it wrong, but I don’t know the right way.

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

Here is my conversion 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); 
+4
source share
2 answers

I think you need to translate your object after rotation, otherwise it will be cropped so that you do not see it, I made an example with a bitmap in MovieClip only on 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 did not bother with scaling, you can do it yourself, I think. The one that I put on the scene is on the right, the bitmapDate, drawn alone, is located on the top left of the scene and is correctly inverted.

UPDATE

Also check out fl.motion.MatrixTransformer according to 32bitkid comment below!

enter image description here

+5
source
  /** 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 
0
source

Source: https://habr.com/ru/post/1415112/


All Articles