About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Oct

    5

    在 iOS 中读取照片的 Exif 并自动旋照片方向技术要点

    • 0 Comments
    • Flash Platform
    • 发布:古树
    • 引用:0
    • 浏览:

    要点一

    侦听 CameraRoll 对象的 MediaEvent.SELECT 事件时,在 iOS 系统中是不同于 Android 系统的,不要试图访问 MediaPromise 对象的 file 与 relativePath 的,它们的值都为 null。

    要点二

    通过 mediaPromise.open() 可以得到一个照片文件的数据,但需要先判断 mediaPromise.isAsync 是否为同步或异步,如果是同步的话可以直接读取照片文件的数据,异步的话就要侦听 Event.COMPLETE 事件,等加载完数据后,再操作数据,类似如下代码:

    var dataSource:IDataInput = mediaPromise.open();

    if(mediaPromise.isAsync)
    {
        IEventDispatcher(dataSource).addEventListener(Event.COMPLETE, onDataComplete);
    }else{
        readMediaData(dataSource);
    }

    要点三

    将 dataSource 的数据写入到一个 byteArray 二进制可处理的对象中,如:

    dataSource.readBytes(byteArray);

    要点四: 

    利用第三方的 jp.shichiseki.exif.ExifInfo 类(自己到 GitHub 或 Google 上找一下就有了)读取 byteArray 中的 Exif 信息,如:

    var _exif:ExifInfo = new ExifInfo(imageFileBytes);
    if(_exif && _exif.ifds)
    {
        imageOrientation = _exif.ifds.primary.Orientation;
    }

    这里不推荐使用 Adobe 官方 XMP 开发者中心的 XMP File Info 相关的类读取照片的 Exif 信息,因为 Adobe 提供的 as3_xmp_file 类只能读取文件的 Exif 信息(适合像 Android 这样的系统中使用),不能现成读取 byteArray 对象中的 Exif 信息(也可能包含在其它类中,但我没有发现)。

    要点五

    通过读取 Orientation 的值为一个数字(每个数字对应的含义点击这里),下面是一个现成的类用于位图旋转方向:

    package
    {
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.geom.Matrix;

        public class ExifUtils
        {
            private static const PORTRAIT:int = 6;
            private static const PORTRAIT_REVERSE:int = 8;

            private static const LANDSCAPE:int = 1;
            private static const LANDSCAPE_REVERSE:int = 3;

            static public function getEyeOrientedBitmap( bitmap:Bitmap, _orientation:int ):Bitmap
            {
                var m:Matrix = new Matrix();
                var bitmapData:BitmapData;

                if( _orientation == LANDSCAPE || _orientation == LANDSCAPE_REVERSE )
                {
                    bitmapData = new BitmapData( bitmap.width, bitmap.height, true );
                }
                else
                {
                    bitmapData = new BitmapData( bitmap.height, bitmap.width, true );
                }

                m.rotate( getEyeOrientedAngle( _orientation ) * ( Math.PI / 180 ) );

                if( _orientation == PORTRAIT_REVERSE )
                {
                    m.translate( 0, bitmap.width )
                }else
                {                
                    if( _orientation == PORTRAIT )
                    {
                        m.translate( bitmap.height, 0 );
                    }else
                    {
                        if( _orientation == LANDSCAPE_REVERSE )
                        {
                            m.translate( bitmap.width, bitmap.height );
                        }
                    }
                }
                bitmapData.draw( bitmap.bitmapData, m);
                return new Bitmap( bitmapData );
            }


            static public function getEyeOrientedAngle(_orientation:int):int
            {
                var angle:int = 0;
                switch(_orientation)
                {
                    case LANDSCAPE: 
                        angle = 0
                        break;
                    case LANDSCAPE_REVERSE: 
                        angle = 180
                        break;
                    case PORTRAIT: 
                        angle = 90
                        break;
                    case PORTRAIT_REVERSE: 
                        angle = -90
                        break;
                }
                return angle;
            }
        }
    }

    其它与本文相关的资料链接(外部链接不保证长期有效):

    http://recycledinformation.blogspot.jp/2011/08/reading-exif-data-on-ios.html

    http://www.digifie.jp/blog/archives/1092

    http://snipplr.com/view/59204/exif-image-reorientation-in-android/ 

    http://stackoverflow.com/questions/5286566/using-xmpcore-to-get-metadata-of-a-file-through-actionscript