About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Apr

    15

    纯 AS3 将图片转换为 SWF

    • 0 Comments
    • Flash Platform

    比较简单方便的通过纯 AS3 代码将图片转换为 SWF 格式,可以免去 SWFTools 需要通过命令行将 *.jpg / *.png 之类的文件转换成 *.swf。

    package
    {
        import flash.display.Bitmap;
        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.net.FileReference;
        import flash.net.URLRequest;
        import flash.utils.ByteArray;
        import flash.utils.Endian;

        public class Image2Swf extends Sprite
        {
            private var isCompress:Boolean = true;//是否为压缩格式的SWF

            private var loader:Loader;
            private var bitmapData:BitmapData;

            public function Image2Swf()
            {
                loader = new Loader();
                loader.contentLoaderInfo.addEventListener(Event.INIT, initHandler);
                loader.load(new URLRequest("test.jpg"));
            }

            private function initHandler(e:Event):void
            {
                e.target.removeEventListener(Event.INIT, initHandler);

                var bitmap:Bitmap = e.target.content as Bitmap;

                if(bitmap)
                {
                    bitmapData = bitmap.bitmapData;

                    var byteArray:ByteArray = new ByteArray();

                    bitmapData.encode(bitmapData.rect, new JPEGEncoderOptions(), byteArray)

                    loader = null;
                    loader = new Loader();
                    loader.contentLoaderInfo.addEventListener( Event.COMPLETE, completeHandler );
                    loader.loadBytes(byteArray);        
                }
            }

            private function completeHandler(e:Event):void
            {
                e.target.removeEventListener( Event.COMPLETE, completeHandler );

                if(isCompress)
                {
                    //保存为压缩格式的SWF
                    saveContentToSWF_compress( e );
                }
                else
                {
                    //保存为非压缩格式的SWF
                    saveContentToSWF( e );
                }
                loader.unload();
                loader = null;
                bitmapData.dispose();
                bitmapData = null;
            }

            //压缩格式
            private function saveContentToSWF_compress( e:Event ):void
            {
                var swf_head:ByteArray = new ByteArray();
                    swf_head.endian = Endian.LITTLE_ENDIAN;
                    swf_head.writeBytes((e.target as LoaderInfo).bytes, 08 );
                    swf_head[0] = 0x43; // 'C'; 
                    swf_head.position = 0;

                var swf_body:ByteArray = new ByteArray();
                    swf_body.endian = Endian.LITTLE_ENDIAN;
                    swf_body.writeBytes((e.target as LoaderInfo).bytes, 8 );
                    swf_body.position = 0;
                    swf_body.compress();
                    swf_body.position = 0;

                var swf_ByteArray:ByteArray = new ByteArray();//包含 head 与 body 的二进制

                    swf_ByteArray.writeBytes(swf_head);
                    swf_ByteArray.writeBytes(swf_body);

                var file:FileReference = new FileReference();
                    file.save(swf_ByteArray, "压格式的SWF.swf");//SWF head CWS
            }

            //非压缩格式
            private function saveContentToSWF( e:Event ):void
            {
                var file:FileReference = new FileReference();
                    file.save((e.target as LoaderInfo).bytes, "非压格式的SWF.swf");//SWF head 为FWS
            }
        }
    }

    Oct

    5

    要点一

    侦听 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

    Dec

    13

    没啥好说的,猛戳这里下载导出fla文件中所有图片的jsfl.rar

    Jan

    12

    AIR / FLEX / AS3 裁切图像

    • 0 Comments
    • Flash Platform
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    //inScale为缩放系数
    function cropBitmapData( inDisplayObject:DisplayObject, inWidth:int, inHeight:int, inX:int, inY:int, inScale:Number = 1):BitmapData {
     if (!inDisplayObject) {
      throw new Error('inDisplayObject 显示对象必须在列表上');
      return null;
     }
     var cropArea:Rectangle = new Rectangle( 0, 0, inWidth * inScale, inHeight * inScale);
     var croppedBitmapData:BitmapData = new BitmapData( inWidth * inScale, inHeight * inScale);
     croppedBitmapData.draw(inDisplayObject, new Matrix(inScale, 0, 0, inScale, -inX, -inY), null, null, cropArea, true );
     return croppedBitmapData;
    }