处理位图数据,一直是flash很重要的一块。在我们的应用中,处理保存图片到本地或上传多服务器上会经常遇到。比如用摄像头拍照上传或保存到本地。或AIR导入图片,处理后保存到磁盘。
在flash player 11.3和air3.3之前,我们可以借助第三方类(JPEGEncoder)这些,很容易处理。现在,有了encode和JPEGEncoderOptions这些,处理位图数据就更简单快捷了。
网上很多人测试过各个方法处理的性能以及占用文件大小情况,encode 都是不错的。
官方给的解释:
flash.display.BitmapData.encode() 方法允许您将位图数据本机压缩为以下图像压缩格式之一:
-
PNG – 使用 PNG 压缩,可以选择使用快速压缩,它强调的是压缩速度而不是文件大小。若要使用 PNG 压缩,请将新的 flash.display.PNGEncoderOptions 对象作为 BitmapData.encode() 方法的第二个参数传递。
-
JPEG – 使用 JPEG 压缩,可以选择指定图像品质。若要使用 JPEG 压缩,请将新的 flash.display.JPEGEncoderOptions 对象作为 BitmapData.encode() 方法的第二个参数传递。
-
JPEGXR – 使用 JPEG 扩展范围 (XR) 压缩,可以选择指定颜色通道、损耗和熵 (entropy) 编码设置。若要使用 JPEGXR 压缩,请将新的 flash.display.JPEGXREncoderOptions 对象作为BitmapData.encode() 方法的第二个参数传递。
您可以将图像处理的此功能用作服务器上传或下载工作流程的一部分。
下面的示例代码片段使用 JPEGEncoderOptions 压缩 BitmapData 对象:
var bitmapData:BitmapData = new BitmapData(640,480,false,0x00FF00); var byteArray:ByteArray = new ByteArray(); bitmapData.encode(new Rectangle(0,0,640,480), new flash.display.JPEGEncoderOptions(), byteArray);
http://help.adobe.com/zh_CN/as3/dev/WS4768145595f94108-17913eb4136eaab51c7-8000.html
对于JPEGEncoderOptions的参数,其值介于1和100之间。值为1的时候,品质最低,100品质最高。默认值是80,这个时候,处理出来的位图质量已经很好了。
今天周末,无聊。在家做一个AIR本地处理保存处理图片,才找到了这个。久违期待已久的好东西。无论是用air还是flash player。处理的方式都一样。这里贴出完整的代码以方便以后使用查阅。
面对web,IE:
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; public class IeJpegEncoderDemo extends Sprite { public function IeJpegEncoderDemo() { load(); } private function load():void { var loader:Loader = new Loader(); var request:URLRequest = new URLRequest(); request.url = "../embed/01.jpg"; loader.load(request); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler); } private function completeHandler(e:Event):void { var bitmap:Bitmap = e.target.content as Bitmap; var bitmapData:BitmapData = new BitmapData(bitmap.width,bitmap.height,true,0); bitmapData.draw(bitmap); (e.target as LoaderInfo).loader.unloadAndStop(); var ba:ByteArray = new ByteArray(); var jpegEncoder:JPEGEncoderOptions = new JPEGEncoderOptions(80); bitmapData.encode(bitmapData.rect,jpegEncoder,ba); var file:FileReference = new FileReference(); file.save(ba,"00.jpg"); } } }
AIR 的,其实,AIR的本来只想做一个处理的过程,做着做着就做多了。揉在一起了。
文档类:JpegEncodeDemo.as
package { import com.vini123.tool.Button; import com.vini123.tool.ScrollBar; import com.vini123.utils.Box; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.JPEGEncoderOptions; import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.PixelSnapping; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.FileListEvent; import flash.events.MouseEvent; import flash.filesystem.File; import flash.filesystem.FileMode; import flash.filesystem.FileStream; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.FileFilter; import flash.net.URLRequest; import flash.utils.ByteArray; [SWF(width = "790", height = "612",frameRate = "30")] public class JpegEncodeDemo extends Sprite { private var addBtn:Button; private var creatBtn:Button; private var maskSp:Sprite; private var resultSp:Sprite; private var scrollBar:ScrollBar; private var bg:Bg; private var resultPos:Point; private var _file:File; private var _fs:FileStream private var index:int = 0; private var urlList:Vector.<String> = new Vector.<String>(); private var boxList:Vector.<Box> = new Vector.<Box>(); public function JpegEncodeDemo() { bg = new Bg(); addChild(bg); stage.nativeWindow.maxSize = stage.nativeWindow.minSize = new Point(stage.stageWidth,stage.stageHeight); stage.nativeWindow.title = "用我三生烟火,换你一世迷离:图片生成器"; stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; addBtn = new Button("添加图片"); addChild(addBtn); creatBtn = new Button("生成图片"); addChild(creatBtn); addBtn.x = 5; addBtn.y = 5; creatBtn.x = addBtn.x + addBtn.width + 5; creatBtn.y = 5; addBtn.buttonMode = true; addBtn.name = "addBtn"; addBtn.addEventListener(MouseEvent.CLICK,clickHandler); creatBtn.buttonMode = true; creatBtn.name = "creatBtn"; creatBtn.addEventListener(MouseEvent.CLICK,clickHandler); resultSp = new Sprite(); resultSp.x = 5; resultSp.y = 35 addChild(resultSp); resultSp.alpha = 1; resultPos = new Point(5,35); scrollBar = new ScrollBar(); addChild(scrollBar); scrollBar.setSize(stage.stageHeight - 35 - 5,15,0x65A5FA,0xADD0FC,0x2D72B5,0,true); scrollBar.scrollTarget = resultSp; maskSp = new Sprite(); maskSp.graphics.beginFill(0x00ffff,0.2); maskSp.graphics.drawRect(0,0,stage.stageWidth - scrollBar.width -5,scrollBar.height); maskSp.graphics.endFill(); addChild(maskSp); maskSp.x = 5, maskSp.y = 35; resultSp.mask = maskSp; resizeHandler(); stage.addEventListener(Event.RESIZE,resizeHandler); } private function clickHandler(e:MouseEvent):void { var tarName:String = e.currentTarget.name; switch(tarName) { case "addBtn": addImage(); break; case "creatBtn": creatImage(); break; } } private function addImage():void { _file = File.desktopDirectory; // _file.browseForDirectory("Please import a Directory that contains image"); // _file.addEventListener(Event.SELECT,addSelectHandler); var fileFilter:FileFilter = new FileFilter("Images(*.jpg;*.gif;*.png;*.jpeg)","*.jpg;*.gif;*.png;*.jpeg"); _file.browseForOpenMultiple("Please import image files",[fileFilter]); _file.addEventListener(FileListEvent.SELECT_MULTIPLE,selectEnd); } private function selectEnd(e:FileListEvent):void { e.target.removeEventListener(FileListEvent.SELECT_MULTIPLE,selectEnd); var len:int = e.files.length; index = urlList.length; for(var i:int =0 ; i < len ; i++) { trace(File(e.files[i]).size/(1024*1024) + "M"); urlList.push(File(e.files[i]).nativePath); } load(); } private function creatImage():void { _file = File.desktopDirectory; _file.browseForDirectory("Please select a Directory that place this image"); _file.addEventListener(Event.SELECT,creatSelectHandler); } private function creatSelectHandler(e:Event):void { e.target.removeEventListener(Event.SELECT,creatSelectHandler); var path:String = (e.target as File).nativePath; var len:int = boxList.length; var jpegEncoder:JPEGEncoderOptions ; var ba:ByteArray; for(var i:int = 0 ; i< len; i++) { jpegEncoder = new JPEGEncoderOptions(80); var rec:Rectangle = boxList[i].bitmap.bitmapData.rect; ba = boxList[i].bitmap.bitmapData.encode(rec,jpegEncoder); _file = _file.resolvePath(path + "/" + i + ".jpg"); _fs = new FileStream(); _fs.open(_file,FileMode.WRITE); _fs.writeBytes(ba); _fs.addEventListener(Event.COMPLETE,creatFull); _fs.close(); ba.clear(); } } private function creatFull(e:Event):void { } private function addSelectHandler(e:Event):void { e.target.removeEventListener(Event.SELECT,creatSelectHandler); if(e.target.isDirectory) { index = urlList.length; var tempArr:Array = e.target.getDirectoryListing(); for(var i:int = 0 ; i< tempArr.length; i++) { var str:String = (tempArr[i] as File).nativePath; var type:String = (str.slice(str.lastIndexOf(".")+1)).toLowerCase(); if(type == "jpg" || type == "png" || type == "gif" || type == "jpeg") { urlList.push(str); } } } load(); } private function load():void { if(index >= urlList.length) { return; } var loader:Loader = new Loader(); var request:URLRequest = new URLRequest(); request.url = urlList[index]; loader.load(request); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler); } private function completeHandler(e:Event):void { e.target.removeEventListener(Event.COMPLETE,completeHandler); var box:Box = new Box(); var bm:Bitmap = e.target.content as Bitmap; bm.smoothing = true; bm.pixelSnapping = PixelSnapping.AUTO; var poinSize:Point = setWh(bm,1280,720) var bd:BitmapData = new BitmapData(poinSize.x,poinSize.y,false); bd.draw(bm,new Matrix(poinSize.x/bm.width,0,0,poinSize.y/bm.height,0,0)); bm = new Bitmap(bd,PixelSnapping.AUTO,true); box.bitmap = bm; resultSp.addChild(box); boxList.push(box); box.x = (index % 3) * box.width; box.y = Math.floor((index / 3)) * box.height; box.index = index; box.deleBtn.addEventListener(MouseEvent.CLICK,boxClickHandler) //(e.target as LoaderInfo).loader.unloadAndStop(); index ++; scrollBar.scrollTarget = resultSp; load(); } private function setWh(bm:Bitmap,_w,_h):Point { var po:Point = new Point(); if(_w/_h > bm.width/bm.height) { po.x = _w; po.y = bm.height * _w/bm.width; } else { po.x = bm.width * _h/bm.height; po.y = _h; } return po; } private function boxClickHandler(e:MouseEvent):void { if(e.currentTarget.name == "deleBtn") { var tempIndex:int = e.currentTarget.parent.index; for(var i:int = 0 ; i< boxList.length ;i++) { if(boxList[i].index == tempIndex) { urlList.splice(i,1); boxList.splice(i,1); (e.currentTarget.parent as Box).dispose(); e.currentTarget.removeEventListener(MouseEvent.CLICK,boxClickHandler); index = urlList.length; } } } resultSp.removeChildren(); for(i = 0 ; i< boxList.length ;i++) { var box:Box = boxList[i]; resultSp.addChild(box); box.x = (i % 3) * box.width; box.y = Math.floor((i / 3)) * box.height; scrollBar.scrollTarget = resultSp; } trace(resultSp.x,resultSp.y) trace(boxList.length); } private function resizeHandler(e:Event = null):void { scrollBar.x = stage.stageWidth - scrollBar.width - 5; scrollBar.y = resultPos.y; trace(stage.stageWidth ,stage.stageHeight); } } }
Button.as
package com.vini123.tool { import flash.display.Sprite; import flash.events.MouseEvent; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; public class Button extends Sprite { private var _txtFormat:TextFormat; private var _txt:TextField private var _bottom:Sprite; private var _gap:int =7; public function Button(label:String):void { _txtFormat = new TextFormat(); _txtFormat.size = 13; _txtFormat.color = 0xADD0FC; _txt = new TextField(); _txt.text = label; _txt.autoSize = TextFieldAutoSize.LEFT; _txt.setTextFormat(_txtFormat); _txt.mouseEnabled = false; addChild(_txt); _bottom = new Sprite(); _bottom.graphics.lineStyle(1.0,0x2D72B5); _bottom.graphics.beginFill(0x0099ff,1); _bottom.graphics.drawRoundRect(0,0,_txt.textWidth + _gap *2,_txt.textHeight + _gap,5,5); _bottom.graphics.endFill(); addChildAt(_bottom,0); _txt.x = _gap; _txt.y = _gap * 0.5 -1; this.addEventListener(MouseEvent.ROLL_OVER,overHandler); this.addEventListener(MouseEvent.ROLL_OUT,outHandler); } private function overHandler(e:MouseEvent):void { _txt.alpha = 0.65; } private function outHandler(e:MouseEvent):void { _txt.alpha = 1; } public function dispose():void { _bottom.graphics.clear(); this.removeEventListener(MouseEvent.ROLL_OVER,overHandler); this.removeEventListener(MouseEvent.ROLL_OUT,outHandler); if(this.parent) { this.parent.removeChild(this); } } } }
ScrollBar.as
package com.vini123.tool { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Rectangle; public class ScrollBar extends Sprite { private var _upBtn:UpBtn; private var _downBtn:DownBtn; private var _lineBar:LineBar; private var _dragBar:DragBar; private var _gap:int = 2; private var _rec:Rectangle; private var _dirction:int; private var _scrollTarget:*; private var _barWidth:Number; private var _lineColor:int; private var _visible:Boolean = false; public function ScrollBar():void { addEventListener(Event.ADDED_TO_STAGE,addToStageHandler); } private function addToStageHandler(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE,addToStageHandler); _upBtn = new UpBtn(); _downBtn = new DownBtn(); _lineBar = new LineBar(); _dragBar = new DragBar(); addChild(_upBtn); addChild(_downBtn); addChild(_lineBar); addChild(_dragBar); _dragBar.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler); _dragBar.addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler); stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); stage.addEventListener(MouseEvent.MOUSE_WHEEL,mouseWheelHandler); _downBtn.addEventListener(MouseEvent.CLICK,clickHandler); _upBtn.addEventListener(MouseEvent.CLICK,clickHandler); } private function mouseWheelHandler(e:MouseEvent):void { var _distance:Number = e.delta * 3; _dragBar.y += _distance; updateDragBarPosition(); } private function clickHandler(e:MouseEvent):void { var _distance:Number; _distance = _lineBar.height * 0.2; switch (e.target) { case _downBtn : _dragBar.y -= _distance; break; case _upBtn : _dragBar.y += _distance; break; } updateDragBarPosition(); } private function updateDragBarPosition():void { if (_dragBar.y <= _lineBar.y) { _dragBar.y = _lineBar.y; } else if (_dragBar.y >= (_lineBar.y + _lineBar.height - _dragBar.height)) { _dragBar.y = (_lineBar.y + _lineBar.height - _dragBar.height); } enterHandler(); } private function mouseDownHandler(e:MouseEvent):void { _dragBar.startDrag(false,_rec); useHandler(); } private function mouseUpHandler(e:MouseEvent):void { _dragBar.stopDrag(); noHandler(); } private function updateBar():void { _upBtn.y = 0; _lineBar.y = _upBtn.y + _upBtn.height + _gap; _downBtn.y = _lineBar.y + _lineBar.height + _gap; _dragBar.x = 1; _dragBar.y = _lineBar.y; _rec = new Rectangle(_dragBar.x,_lineBar.y,0,(_lineBar.height - _dragBar.height)); } /** * 设置拖动条的属性 * @param _length 拖动条的总长度(竖向就是总高度,横向的就是总宽度) * @param _width 拖动条的宽度 (指的是上下两个按钮的宽度和高度) * @param _lineColor 拖动条的线条颜色 * @param _fillColor 拖动条的填充颜色 * @param _triangleColor 上下两个按钮里边三角形的填充颜色 * @param _dirction 表示拖动条的方向,值为0的时候是竖向,为1的时候是横向 * @param _visible 表示当被拖动对象小于或等于拖动条的长度时,是否显示拖动条。 * */ public function setSize(_length:Number,_width:Number,_lineColor:int,_fillColor:int,_triangleColor:int,_dirction:int,_visible:Boolean = false):void { this._dirction = _dirction; _upBtn.beginDraw(_width,_lineColor,_fillColor,_triangleColor); _downBtn.beginDraw(_width,_lineColor,_fillColor,_triangleColor); _dragBar.beginDraw(_width,(_length - _upBtn.height - _downBtn.height -_gap *2)*0.5,_lineColor); _lineBar.beginDraw(_width,(_length - _upBtn.height - _downBtn.height -_gap *2),_lineColor,_fillColor); this._barWidth = _width; this._lineColor = _lineColor; this._visible = _visible; updateBar(); } /** *设置被拖动的对象 * @param value * */ public function set scrollTarget(value:*):void { _scrollTarget = value; var _h1:Number = this.height > _scrollTarget.height ? _lineBar.height :(this.height / _scrollTarget.height) *_lineBar.height; _h1 = _h1 < 30 ? 30:_h1; _dragBar.beginDraw(_barWidth,_h1,_lineColor); _rec = new Rectangle(_dragBar.x,_lineBar.y,0,(_lineBar.height - _dragBar.height)); enterHandler(); } private function enterHandler(e:Event = null):void { if (_lineBar.height == _dragBar.height) { if (! _visible) { this.visible = false; } _scrollTarget.y = this.y; } else { this.visible = true; _scrollTarget.y = this.y + (_dragBar.y - _lineBar.y) * (this.height - _scrollTarget.height)/(_lineBar.height - _dragBar.height); } } private function useHandler():void { addEventListener(Event.ENTER_FRAME,enterHandler); } private function noHandler():void { removeEventListener(Event.ENTER_FRAME,enterHandler); } } } import flash.display.Shape; import flash.display.Sprite; class UpBtn extends Sprite { private var _rect:Shape; private var _triangle:Shape; public function UpBtn():void { _rect = new Shape(); _triangle = new Shape(); addChild(_rect); addChild(_triangle); } public function beginDraw(_h:Number,_lineColor:int,_fillColor:int,_triangleColor:int):void { _rect.graphics.clear(); _rect.graphics.lineStyle(1,_lineColor); _rect.graphics.beginFill(_fillColor,1); _rect.graphics.drawRect(0,0,_h,_h); _rect.graphics.endFill(); _triangle.graphics.clear(); _triangle.graphics.lineStyle(1,_triangleColor); _triangle.graphics.beginFill(_triangleColor,1); _triangle.graphics.moveTo(_h/3,0); _triangle.graphics.lineTo(2*_h/3,_h/2.5); _triangle.graphics.lineTo(0,_h/2.5); _triangle.graphics.lineTo(_h/3,0); _triangle.x = _rect.width * 0.5 - _triangle.width * 0.5; _triangle.y = _rect.height * 0.5 - _triangle.height * 0.5; } } class DownBtn extends Sprite { private var _rect:Shape; private var _triangle:Shape; public function DownBtn():void { _rect = new Shape(); _triangle = new Shape(); addChild(_rect); addChild(_triangle); } public function beginDraw(_h:int,_lineColor:int,_fillColor:int,_triangleColor:int):void { _rect.graphics.clear(); _rect.graphics.lineStyle(1,_lineColor); _rect.graphics.beginFill(_fillColor,1); _rect.graphics.drawRect(0,0,_h,_h); _rect.graphics.endFill(); _triangle.graphics.clear(); _triangle.graphics.lineStyle(1,_triangleColor); _triangle.graphics.beginFill(_triangleColor,1); _triangle.graphics.moveTo(0,0); _triangle.graphics.lineTo(2*_h/3,0); _triangle.graphics.lineTo(_h/3,_h/2.5); _triangle.graphics.lineTo(0,0); _triangle.x = _rect.width * 0.5 - _triangle.width * 0.5; _triangle.y = _rect.height * 0.5 - _triangle.height * 0.5; } } class LineBar extends Sprite { private var _rect:Shape; public function LineBar():void { _rect = new Shape(); addChild(_rect); } public function beginDraw(_w:int,_h:int,_lineColor:int,_fillColor:int):void { _rect.graphics.clear(); _rect.graphics.lineStyle(1,_lineColor); _rect.graphics.beginFill(_fillColor,1); _rect.graphics.drawRect(0,0,_w,_h); _rect.graphics.endFill(); } } class DragBar extends Sprite { private var _rect:Shape; public function DragBar():void { _rect = new Shape(); addChild(_rect); beginDraw(15,100,0xFFF8E9); } public function beginDraw(_w:int,_h:int,_fillColor:int):void { _rect.graphics.clear(); _rect.graphics.beginFill(_fillColor,1); _rect.graphics.drawRect(0,0,(_w-1),_h); _rect.graphics.endFill(); } }
Box.as:
package com.vini123.utils { import com.vini123.tool.Button; import flash.display.Bitmap; import flash.display.Sprite; import flash.events.MouseEvent; public class Box extends Sprite { private var _w:Number; private var _h:Number; private var _deleBtn:Button; private var _index:int; private var bottom:Sprite; private var box:Sprite; private var gap1:int = 4; private var gap2:int = 1; private var _bitmap:Bitmap; public function Box(w:Number = 250,h:Number = 180) { _w = w; _h = h; bottom = new Sprite(); addChild(bottom); box = new Sprite(); addChild(box); draw(); _deleBtn = new Button("删除图片"); addChild(_deleBtn); _deleBtn.x = _w - 2 * gap1 - _deleBtn.width -10; _deleBtn.y = _h - 2 * gap1 - _deleBtn.height -10; _deleBtn.buttonMode = true; _deleBtn.name = "deleBtn"; _deleBtn.visible = false; this.addEventListener(MouseEvent.ROLL_OVER,overHandler); this.addEventListener(MouseEvent.ROLL_OUT,outHandler); } public function dispose():void { this.removeEventListener(MouseEvent.ROLL_OVER,overHandler); this.removeEventListener(MouseEvent.ROLL_OUT,outHandler); bottom.graphics.clear(); box.graphics.clear(); _deleBtn.dispose(); _bitmap.bitmapData.dispose(); if(this.parent) { this.parent.removeChild(this); } } public function get deleBtn():Button { return _deleBtn; } public function get index():int { return _index; } public function set index(value:int):void { _index = value; } private function overHandler(e:MouseEvent):void { _deleBtn.visible = true; } private function outHandler(e:MouseEvent):void { _deleBtn.visible = false; } public function get bitmap():Bitmap { return _bitmap; } public function set bitmap(value:Bitmap):void { if(_bitmap) { return; } _bitmap = value; var _tempW:Number = _bitmap.width; var _tempH:Number = _bitmap.height; if((_tempW/_tempH) > (_w - gap1*2 - gap2 *2)/(_h - gap1 *2 - gap2*2)) { _bitmap.width =(_w - gap1*2 - gap2 *2); _bitmap.height = _tempH * (_w - gap1*2 - gap2 *2)/_tempW; } else { _bitmap.width = _tempW * (_h - gap1*2 - gap2 *2)/_tempH; _bitmap.height = _h - gap1*2 - gap2 *2; } _bitmap.x = bottom.width * 0.5 - _bitmap.width * 0.5; _bitmap.y = bottom.height * 0.5 - _bitmap.height * 0.5; addChildAt(_bitmap,this.numChildren -1); } private function draw():void { bottom.graphics.beginFill(0x00ff00,0.0); bottom.graphics.drawRect(0,0,_w,_h); bottom.graphics.endFill(); box.graphics.lineStyle(1.2,0xADD0FC); box.graphics.beginFill(0xADD0FC,1); box.graphics.drawRoundRect(0,0,_w - gap1 *2,_h - gap1 *2,5,5); box.graphics.endFill(); box.x= bottom.width * 0.5 - box.width * 0.5 ; box.y = bottom.height * 0.5 - box.height * 0.5; } } }