zoukankan      html  css  js  c++  java
  • Flex 学习笔记------读取Jpeg图片的width,height和colorSpace

    最近开始学习Flex开发,遇到一个需求:上传图片之前需要在本地先预览图片。但是有两个问题:

      1.flex4里面还不支持对*.tif 和 *.tiff格式的预览,一方面可能是因为tif图的体积比较大,非常耗内存,另一方也有可能是因为tif图片的格式比较复杂。

      2.Jpeg格式的图片中颜色通道主要分为三种:rgb,cmyk,grey。而cmyk的图片在浏览器中显示时颜色会失真。

    问题1没有想到好的解决的办法,虽然也在github上找到一个开源的读取tif图片的类库,但是体积过大,预览的时间很慢。关键的是tif格式的图片中颜色通道为cmyk的还是不能正确的显示。

    下面是部分代码,及测试效果:

            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, 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的文件头格式

    不看不知道,没想到文件头格式这么复杂。不过还好,colorspace字段的存储位置还是相对固定的:

    由上图我们可以看到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/

    -----------------------------一花开五叶 结果自然成-------------------------------------------------
  • 相关阅读:
    数组的完全随机排列算法
    css超出2行部分省略号...
    前端面试题精华总结
    在地址栏输入网址后页面是如何呈现的?
    document.write和innerHTML的区别
    js运算符单竖杠“|”与“||”的用法和作用介绍
    border:none与border:0的区别
    如何实现浏览器内多个标签页之间的通信?
    js 关键字 in 的使用方法
    msyql: navicat 连接时msyql遇到的问题
  • 原文地址:https://www.cnblogs.com/zyc-undefined/p/3199327.html
Copyright © 2011-2022 走看看