0

我正在我的 Flash 构建器中构建一个带有 actionscript 3.0 的应用程序。这是此问题的后续问题,它有效,但是当我拍照时,图像向左旋转。如何检查用户拿着手机的方式?然后我用什么代码将图像旋转到相应的位置?

提前致谢!

编辑: 我正在使用此代码旋转图像,但它似乎只旋转正在显示的图像而不是图像文件,有什么想法吗?

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;

~喵喵

4

3 回答 3

2

当您激活 cameraUI 视图时,您无法获取stage.orientation数据,所以这是我解决相同问题的方法,请注意这个控制器有许多可重用的功能,我首先从 media promise 获取原始图像数据(这个原始数据有 EXIF 数据我将读取以从相机获取图像方向)然后将此 byteArray 转换为 BitmapData,然后根据需要调整大小和缩放。需要注意的一件事是,如果您将原始图像数据转换为位图数据,您将丢失 EXIF 数据,因此请在修改图像之前阅读它,希望这会有所帮助,我很晚才在这里发布我知道但网络上没有其他解决方案和也许有人会在某个时候需要这个。干杯

快照控制器.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;
        }

    }
}
于 2014-05-02T20:24:14.640 回答
1

您可以使用Stage.deviceOrientationStage.orientation * 来确定手机的方向。

*不确定这个是否适用于iOS

您想要旋转的是 BitmapData 结果本身(即创建一个带有旋转图像的新 BitmapData)还是只是旋转显示列表上的 Bitmap?

编辑:

好的,这是一些旋转 BitmapData 对象的代码:

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;
}

角度应为 0,90,180 或 270。它将返回按指定角度旋转的新 BitmapData 对象。

于 2013-02-20T04:09:20.390 回答
0

您可以使用StageOrientationEvent.ORIENTATION_CHANGING事件:

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;
            }
        }

这可以帮助你。

于 2013-02-20T05:00:31.060 回答