Flex 學習筆記------讀取Jpeg圖片的width,height和colorSpace

最近開始學習Flex開發,遇到一個需求:上傳圖片以前須要在本地先預覽圖片。可是有兩個問題:html

  1.flex4裏面還不支持對*.tif 和 *.tiff格式的預覽,一方面多是由於tif圖的體積比較大,很是耗內存,另外一方也有多是由於tif圖片的格式比較複雜。git

  2.Jpeg格式的圖片中顏色通道主要分爲三種:rgb,cmyk,grey。而cmyk的圖片在瀏覽器中顯示時顏色會失真。github

問題1沒有想到好的解決的辦法,雖然也在github上找到一個開源的讀取tif圖片的類庫,可是體積過大,預覽的時間很慢。關鍵的是tif格式的圖片中顏色通道爲cmyk的仍是不能正確的顯示。windows

下面是部分代碼,及測試效果:瀏覽器

        import mx.controls.Alert;
        import com.utils.Tiff.TIFF6Decoder;

        private var tiffDecoder:TIFF6Decoder;
        private var byteArray:ByteArray;

        private function loadFile():void {
            var request:URLRequest = new URLRequest("images/1.tif");
            var urlLoader:URLLoader = new URLLoader(request);

            urlLoader.addEventListener(Event.COMPLETE, onLoadComplete);
            urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
            urlLoader.load(request);
        }

        private function onLoadComplete(e:Event):void {
            byteArray = e.target.data;

            tiffDecoder = new TIFF6Decoder();
            if (tiffDecoder.decode(byteArray)) {
                 img.source = new Bitmap(tiffDecoder.bitmapData);
            }
            else {
                Alert.show("Failed TIFF decoding");
            }
        }

問題2的解決辦法是先判斷Jpeg圖片的顏色通道,若是是cmyk的,不顯示預覽圖,上傳以後顯示後臺返回的縮略圖。本文的目標就是要解決這個問題。函數

上傳前讀取圖片的width和height,網上已經有不少方法了。這一點bitmapdata本身就能夠作到,甚至不須要別的類庫。學習

示例:測試

      //打開瀏覽文件窗口選擇要上傳的文件
        private function browse(event:MouseEvent):void {
            var imageTypes:FileFilter = new FileFilter("圖片 (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg; *.jpeg; *.gif; *.png");
            var allTypes:Array = new Array(imageTypes);
            fileReferenceList.browse(allTypes);
        }

        // 選擇文件後的處理
        // 若選擇多個文件,每一個文件都須要一個FileReference進行處理
        private function selectHandler(event:Event):void {
            for (var i:int = 0; i < fileReferenceList.fileList.length; i++) {
                var f:FileReference = FileReference(fileReferenceList.fileList[i]);
                //每一個文件對應的fileReference  監聽上傳成功後, 後臺返回參數的事件
                f.addEventListener(Event.COMPLETE, loadCompleteHandler);
                f.load();
            }
            trace("selectHandler Called!");
        }

        // 本地預覽
        private function loadCompleteHandler(event:Event):void {
            var loader:Loader = new Loader();
            var file:FileReference = event.target as FileReference;
            if (file.size > 1024 * 1024 * 100) {
                Alert.show("文件不能超過100M.", "錯誤");
                return;
            }
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function():void {
                var bmp:Bitmap = loader.content as Bitmap;
                var bmd:BitmapData;
                var scale:Number, width:Number, height:Number;
    
                 trace("imgWidth:" + bmp.width + " imgHeight:" + bmp.height );   
     
                file.removeEventListener(Event.COMPLETE,loadCompleteHandler);
            });
            loader.loadBytes(event.target.data);
            trace("loadCompleteHandler Called!");
        }        

  

可是這個方法也只能處理圖片的大小,不能判斷colorspace。通常圖片的文件頭部分存儲了關於這個圖片的全部相關信息,要想判斷Jpeg的colorspace,固然先得了解一下Jpeg的文件頭格式flex

不看不知道,沒想到文件頭格式這麼複雜。不過還好,colorspace字段的存儲位置仍是相對固定的:ui

由上圖咱們能夠看到Jpeg中的S0F0字段存儲了colorspace信息,但在S0F0以前可能有一些APPn字段,這些字段須要先跳過去。所以,知道了colorspace的存放位置以後,代碼以下:

package com {
	
	import flash.net.URLStream;
	import flash.net.URLRequest;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.utils.Endian;
	
	public class JpegColorSpaceExtractor extends URLStream {

	public static const PARSE_COMPLETE              : String = "parseComplete";
	public static const PARSE_FAILED	        : String = "parseFailed";


	protected var jumpLength			: uint;
	protected var stopWhenParseComplete		: Boolean;
	protected var address				: int;

        protected var dataLoaded			: uint;
        protected var jpgWidth				: uint;
        protected var jpgHeight				: uint;
        protected  var jpgColorSpace                    : int;

        // 構造函數
	public function JpegColorSpaceExtractor() {
            // 設置字節序
            endian = Endian.BIG_ENDIAN;
	}

	protected function progressHandler( e:ProgressEvent ) : void {
            // bytesAvailable 當前加載進來的數據
	    dataLoaded = bytesAvailable;

            var seg1: uint = 0;
            var seg2: uint = 0;

	    while ( bytesAvailable ) {
		var match : Boolean = false;
		if ( jumpLength == 0 ) {
		    seg1 = readUnsignedByte( );
		    address++;
                     if(seg1 == 0xff){
                        seg2 = readUnsignedByte( );
                        address++;
                        if(seg2 >= 0xE0 && seg2 <= 0xEF){
                            jumpLength = readUnsignedShort( ) - 2;
                            address += 2;
                            match = false;
                        }
                        if(seg2 >= 0xC0 && seg2 <= 0xCF){
                            readUnsignedShort( ); //  0x00 ox11
                            address += 2;
                            jumpLength = 0;
                            trace("find!!!");
                            match = true;
                        }
                    }
		}
		if ( jumpLength > 0 ) {
			if ( bytesAvailable >= jumpLength ) {
				jumpBytes( jumpLength );
				jumpLength = 0;
			}
                        else break;
		}
                if(match){
                    readUnsignedByte();                     // bit depth
                    jpgHeight = readUnsignedShort( );      // height
                    jpgWidth = readUnsignedShort( );       // width
                    jpgColorSpace = readUnsignedByte();   // colorSpace
                    address += 6;

                    removeEventListener( ProgressEvent.PROGRESS, progressHandler );
                    if ( stopWhenParseComplete && connected ){
                        close();
                    }
                    dispatchEvent( new Event( PARSE_COMPLETE ) );
                    break;
                }
	  }
       }

        protected function jumpBytes( count : uint ) : void {
            for ( var i : uint = 0; i < count; i++ ) {
                readByte( );
                address++;
            }
        }

	protected function fileCompleteHandler( e : Event ) : void {
	   if ( !jpgWidth || !jpgHeight || !jpgColorSpace ) dispatchEvent( new Event( PARSE_FAILED ) );
	}

	public function extractJpegColorSpace( fileURL : String, stopWhenParsed : Boolean = true ) : void {
	    addEventListener( ProgressEvent.PROGRESS, progressHandler );
	    addEventListener( Event.COMPLETE, fileCompleteHandler );
            address = 0;
            dataLoaded = 0;
            jumpLength = 0;
            jpgColorSpace = 0;

	    stopWhenParseComplete = stopWhenParsed;
	    super.load( new URLRequest( fileURL ) );
         }

	public function get loaded( ) : uint {
		return dataLoaded;
	}

	public function get width( ) : uint {
		return jpgWidth;
	}

	public function get height( ) : uint {
		return jpgHeight;
	}

        public  function get colorSpace(): uint{
                return jpgColorSpace;
        }
	}
}                    

資料:

Image-MetaData-Jpeg:https://metacpan.org/release/Image-MetaData-JPEG

Getting Jpeg Dimensions: http://www.anttikupila.com/flash/getting-jpg-dimensions-with-as3-without-loading-the-entire-file/

相關文章
相關標籤/搜索