How to rotate image from cameraUI for iOS in actionscript 3.0

末鹿安然 提交于 2019-12-23 04:42:04

问题


I'm building an App with actionscript 3.0 in my Flash builder. This is a followup question to this question, It works but when I take the picture, the image comes out rotated to the left. how can I check which way the user is holding the phone? and then what code do I use to rotate the image to it's corresponding place?

Thanks in advanced!

EDIT: I'm using this code to rotate the image, but it seems to only rotate the image being displayed not the image file, any ideas?

var mat:Matrix = new Matrix();
mat.translate(-W/2, -H/2);
mat.rotate(Math.PI/2);
mat.translate(+W/2, +H/2);
mat.concat(myObj.transform.matrix);
myObj.transform.matrix = mat;

~Myy


回答1:


You can use Stage.deviceOrientation or Stage.orientation* to determine which way round the phone is.

*not sure if this one works on iOS

Is it the BitmapData result itself that you want to rotate (ie create a new BitmapData with rotated image) or just rotate a Bitmap on the display list?

Edit:

Ok, heres some code to rotate a BitmapData object:

function rotateBitmapData(angle:int, source:BitmapData):BitmapData
{
    var newWidth:int = source.rect.width;
    var newHeight:int = source.rect.height;
    if (angle==90 || angle==270)
    {
        newWidth = source.rect.height;
        newHeight = source.rect.width;
    }
    var newBmd:BitmapData = new BitmapData(newWidth, newHeight, source.transparent);
    var tx:Number = 0;
    var ty:Number = 0;
    if (angle==90 || angle==180)
    {
        tx = newWidth;
}
    if (angle==180 || angle==270)
    {
        ty = newHeight;
    }
    var matrix:Matrix = new Matrix();
    matrix.createBox(1, 1, Math.PI*angle/180, tx, ty);
    newBmd.draw(source, matrix);
    return newBmd;
}

angle should be 0,90,180 or 270. It will return a new BitmapData object rotated by specified angle.




回答2:


You can't get stage.orientation data when you have the cameraUI view active, so here's how i solved the same issue, please note that this controller has many reusable functions, i first get the raw image data from media promise (this raw data has EXIF data that i will read to get image orientation from the camera) i then convert this byteArray to BitmapData and then resize and scale as i need. One thing to note is that if you convert the raw image data to Bitmap data you will lose EXIF data so read it before you modify the image, hope this helps and i posted it here late i know but there's no other solution in the web and maybe someone will need this sometime. Cheers

SnapshotController.as

package controllers
{

    import flash.display.BitmapData;
    import flash.display.JPEGEncoderOptions;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.IEventDispatcher;
    import flash.events.MediaEvent;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.media.CameraUI;
    import flash.media.MediaPromise;
    import flash.media.MediaType;
    import flash.utils.ByteArray;
    import flash.utils.IDataInput;

    import mx.utils.Base64Encoder;

    import classes.APIupload;


    public class SnapshotController
    {
        private var cameraUI:CameraUI = new CameraUI();
        private var dataSource:IDataInput; 
        private var tempDir:File = new File();
        private var imageOrientation:int = 0 ;


        public function SnapshotController()
        {

        }

        public function LaunchCameraUI():void
        {

            if( CameraUI.isSupported ) {
                trace( "Initializing camera..." ); 
                cameraUI.addEventListener( MediaEvent.COMPLETE, imageSelected ); 
                cameraUI.launch( MediaType.IMAGE ); 
            } else {
                trace( "CameraUI is not supported."); 
            }
        }

        private function imageSelected( event:MediaEvent ):void {
            trace( "Media selected..." ); 
            var imagePromise:MediaPromise = event.data; 


            dataSource = imagePromise.open(); 
            if( imagePromise.isAsync ) {
                trace( "Asynchronous media promise." ); 
                var eventSource:IEventDispatcher = dataSource as IEventDispatcher; 
                eventSource.addEventListener( Event.COMPLETE, onMediaLoaded );
            } else {
                trace( "Synchronous media promise." ); 
                readMediaData(); 
            }
        } 
        private function onMediaLoaded( event:Event ):void {
            trace("Media load complete"); 
            readMediaData();
        } 

        private function readMediaData():void { 
            var imageBytes:ByteArray = new ByteArray(); 
            dataSource.readBytes( imageBytes );

            imageOrientation = getOrientation(imageBytes);

            //saveImageFile(imageBytes);
            //Saving this byteArray will save a big file with the EXIF in it.

            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.INIT, onMediaPromiseLoaded);
            loader.loadBytes(imageBytes);

        } 


        private function onMediaPromiseLoaded(e:Event):void
        {
            trace("Media file loaded");
            var base64Enc:Base64Encoder = new Base64Encoder();
            var mpLoaderInfo:LoaderInfo = e.target as LoaderInfo;
            mpLoaderInfo.removeEventListener(Event.COMPLETE, onMediaPromiseLoaded);

            var scale:Number = 0.25;
            var matrix:Matrix = new Matrix();
            matrix.scale(scale, scale);


            var jpgQuality:int = 80;


            var bmd:BitmapData = new BitmapData(mpLoaderInfo.width*scale, mpLoaderInfo.height*scale);
            bmd.draw(mpLoaderInfo.content,matrix,null,null,null,true);  

            var rotatedBMD:BitmapData = rotateBitmapData(bmd, imageOrientation);
            var bytes:ByteArray = rotatedBMD.encode(new Rectangle(0,0, rotatedBMD.width , rotatedBMD.height), new JPEGEncoderOptions(jpgQuality), bytes);




            saveImageFile(bytes); //this is the smaller file saved. it does not have EXIF data but you can write your own using AS3 eXIF class.

        } 

        private function rotateBitmapData( bitmapData:BitmapData, degree:int = 0 ) :BitmapData
        {
            var newBitmap:BitmapData;
            var matrix:Matrix = new Matrix();
            matrix.rotate( degree * (Math.PI / 180)  );

            if ( degree == 90 ) {
                newBitmap = new BitmapData( bitmapData.height, bitmapData.width, true );
                matrix.translate( bitmapData.height, 0 );
            } else if ( degree == -90 || degree == 270) {
                newBitmap = new BitmapData( bitmapData.height, bitmapData.width, true );
                matrix.translate( 0, bitmapData.width );
            } else if ( degree == 180 ) {
                newBitmap = new BitmapData( bitmapData.width, bitmapData.height, true );
                matrix.translate( bitmapData.width, bitmapData.height );
            }else if(degree == 0){
                newBitmap = new BitmapData( bitmapData.width, bitmapData.height, true );
                //matrix.translate( bitmapData.width, bitmapData.height );
            }

            newBitmap.draw( bitmapData, matrix, null, null, null, true )
            return newBitmap;
        }

        private function saveImageFile(ba:ByteArray):void{
            var now:Date = new Date(); 
            var filename:String = "IMG" + now.fullYear + now.month + now.day + now.hours + now.minutes + now.seconds + ".jpg";
            var temp:File = File.documentsDirectory.resolvePath( filename );
            var stream:FileStream = new FileStream(); 
            stream.open( temp, FileMode.WRITE ); 
            stream.writeBytes( ba ); 
            stream.close();
        }



        private function getOrientation(jpeg:ByteArray):int{
            if (jpeg == null) {
                return 0;
            }
            var offset:int = 0;
            var length:int = 0;


            while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) {
                var marker:int = jpeg[offset] & 0xFF;

                // Check if the marker is a padding.
                if (marker == 0xFF) {
                    continue;
                }
                offset++;

                // Check if the marker is SOI or TEM.
                if (marker == 0xD8 || marker == 0x01) {
                    continue;
                }
                // Check if the marker is EOI or SOS.
                if (marker == 0xD9 || marker == 0xDA) {
                    break;
                }

                // Get the length and check if it is reasonable.
                length = pack(jpeg, offset, 2, false);
                if (length < 2 || offset + length > jpeg.length) {
                    trace("Invalid length");
                    return 0;
                }

                // Break if the marker is EXIF in APP1.
                if (marker == 0xE1 && length >= 8 &&
                    pack(jpeg, offset + 2, 4, false) == 0x45786966 &&
                    pack(jpeg, offset + 6, 2, false) == 0) {
                    offset += 8;
                    length -= 8;
                    break;
                }

                // Skip other markers.
                offset += length;
                length = 0;
            }

            if (length > 8) {
                // Identify the byte order.
                var tag:int = pack(jpeg, offset, 4, false);
                if (tag != 0x49492A00 && tag != 0x4D4D002A) {
                    trace("Invalid byte order");
                    return 0;
                }
                var littleEndian:Boolean = (tag == 0x49492A00);

                // Get the offset and check if it is reasonable.
                var count:int = pack(jpeg, offset + 4, 4, littleEndian) + 2;
                if (count < 10 || count > length) {
                    trace( "Invalid offset");
                    return 0;
                }
                offset += count;
                length -= count;

                // Get the count and go through all the elements.
                count = pack(jpeg, offset - 2, 2, littleEndian);
                while (count-- > 0 && length >= 12) {
                    // Get the tag and check if it is orientation.
                    tag = pack(jpeg, offset, 2, littleEndian);
                    if (tag == 0x0112) {
                        // We do not really care about type and count, do we?
                        var orientation:int = pack(jpeg, offset + 8, 2, littleEndian);
                        switch (orientation) {
                            case 1:
                                return 0;
                            case 3:
                                return 180;
                            case 6:
                                return 90;
                            case 8:
                                return 270;
                        }
                        trace( "Unsupported orientation");
                        return 0;
                    }
                    offset += 12;
                    length -= 12;
                }
            }

            trace( "Orientation not found");
            return 0;

        }

        private function pack(bytes:ByteArray,offset:int,length:int,
                              littleEndian:Boolean):int {
            var step:int = 1;
            if (littleEndian) {
                offset += length - 1;
                step = -1;
            }

            var value:int = 0;
            while (length-- > 0) {
                value = (value << 8) | (bytes[offset] & 0xFF);
                offset += step;
            }
            return value;
        }

    }
}



回答3:


You can use StageOrientationEvent.ORIENTATION_CHANGING Event :

stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, OrientationChangeHandler);

private function OrientationChangeHandler(e:StageOrientationEvent):void
        {
            switch (e.afterOrientation)
            {


                case StageOrientation.DEFAULT :

                break;
            case StageOrientation.ROTATED_RIGHT :

                break;
            case StageOrientation.ROTATED_LEFT :

                break;
            case StageOrientation.UPSIDE_DOWN :

                break;
            }
        }

this can help you.



来源:https://stackoverflow.com/questions/14970353/how-to-rotate-image-from-cameraui-for-ios-in-actionscript-3-0

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