全面提升你的程序效率 之细说 bit地图data(一)

全面提升你的程序效率 之细说 bitmapdata(一)
如果你是刚接触as编程或者现在只接触flex开发,或许你会对BitmapData不太了解,也或许你会对它不屑一顾。

但作为一个资深的as开发者,无论是游戏开发还是web应用。 

BitmapData是你不可不了解的一个基础核心。为什么说它是核心,因为在as开发中BitmapData是我们处理图像的基类。 

BitmapData可以为我们做什么?很多哦开发者或者老开发人员也可能不太了解

。BitmapData的存在可以大大的优化你的图像处理能力。小至一个简单的效果,大至一个3d引擎。BitmapData可以说任何地方都能发挥其优越性。只要你能深入了解它,它将带给你对as的一个高层次提升。



下边我结合一些例子给大家详细的解说下,BitmapData对于我们究竟用处有多大。 

一。可能你用过flex的image组件或者你要写一个简单的图片自适应问题而苦恼,又或者你现在对于处理你的相册应用开销而烦恼,诸如此类的图片大小适应问题将在这节为你详细说说。

对于刚接触as编程的人,对于一个图片自适应问题可能很是苦恼,要么花费大量的判断去对一个加载进来的loader的大小进行判断处理,但你有没有考虑过用BitmapData来解决你的问题呢?

如果你认为自己是一个老程序员应该要第一时间考虑到BitmapData的解决这类问题。而不是花费大量时间去处理如sprite,movieclip等可是对象的大小。因为那样的处理大大的提高了你的开销,并不可取。

这类问题的一般难点在于,我们要处理的图像大小不一致, 怎么可以使得一个位置大小的图像去适应一个已知大小的容器呢?

处理这类问题我们主要用到BitmapData的draw的方法。

接下来的问题是首先我们需要然原图像能够整个的现实在我们要显示的容器上,其次,我们还需要等比例拉伸我们的图像使得他不会变形。

draw虽然可以帮我们解决这里问题,但怎么个思路呢?

这里您需要先了解BitmapData的一个特性,如果你有BitmapData的使用经验,你可能也会发觉知道BitmapData.draw()这个方法对于位于为负数坐标的像素是无法绘制的。

知道了问题所在之后我们再看看 BitmapData.draw()这个方法的一些参数说明 
public function draw(source:IBitmapDrawable, matrix:Matrix = null, colorTransform:ColorTransform = null, blendMode:String = null, clipRect:Rectangle = null, smoothing:Boolean = false):void

参数

source:IBitmapDrawable — 要绘制到 BitmapData 对象的显示对象或 BitmapData 对象。 (DisplayObject 和 BitmapData 类实现 IBitmapDrawable 接口。)

matrix:Matrix (default = null) — 一个 Matrix 对象,用于缩放、旋转位图或转换位图的坐标。 如果不想将矩阵转换应用于图像,请将此参数设置为恒等矩阵(使用默认 new Matrix() 构造函数创建),或传递 null 值。

colorTransform:ColorTransform (default = null) — 一个 ColorTransform 对象,用于调整位图的颜色值。 如果没有提供任何对象,则不会转换位图图像的颜色。 如果必须传递此参数但又不想转换图像,请将此参数设置为使用默认 new ColorTransform() 构造函数创建的 ColorTransform 对象。

blendMode:String (default = null) — 来自 flash.display.BlendMode 类的一个字符串值,指定要应用于所生成位图的混合模式。 clipRect:Rectangle (default = null) — 一个 Rectangle 对象,定义要绘制的源对象的区域

。 如果不提供此值,则不会进行剪裁,并且将绘制整个源对象。

smoothing:Boolean (default = false) — 一个布尔值,用于确定因在 matrix 参数中指定缩放或旋转而对 BitmapData 对象进行缩放或旋转以后,是否对该对象进行平滑处理。 smoothing 参数只有在 source 参数是 BitmapData 对象时才适用。 在将 smoothing 设置为 false 的情况下,经过旋转或缩放的 BitmapData 图像可能会显得像素化或带有锯齿。 例如,下面两个图像的 source 参数使用同一个 BitmapData 对象,但对左侧的图像,smoothing 参数设置为 true,对右侧的图像,该参数设置为 false: 在将 smoothing 设置为 true 的情况下绘制位图要比在将 smoothing 设置为 false 的情况下执行相同操作更为缓慢。 



引发 ArgumentError — source 参数不是 BitmapData 或 DisplayObject 对象。 SecurityError — source 对象及(就 Sprite 或 MovieClip 对象而论)其所有子对象与调用方不在同一个域中,或者不在调用方可通过调用 Security.allowDomain() 方法访问的 SWF 文件中。 ArgumentError — 源为空或不是有效的 IBitmapDrawable 对象。

通过对参数的了解我们其实可以发觉 draw()这个方法其实早就已经考虑到这种问题了,只是一般人不了解参数的使用望而却步而已。。 恩,我们可以使用参数 矩阵(matrix:Matrix) ,及 矩形(clipRect:Rectangle )这两个参数来帮助我们处理 这两个参数主要提供了像素的矩阵乘积及图像的范围限制 来为我们解决上述问题, 知道了解决问题的缺口,那么现在 我们要做的就是, 我们根据上边的分析可以定出我们的方法所需要的必要参数, 
public function draw(container:DisplayObjectContainer,target:DisplayObject,width:Number=150,height:Number=200):BitmapData { } 

我们在定义一个矩阵matrix为调用draw时必须注意一下几点,a.让图像的像素都调整到以(0,0)点开始。 

b .我们还要考虑到可是对象的大小伸缩问题,因为draw是对可是对象的内存缓存的一个渲染。所以如果可是对象发生的大小伸缩,draw出来的图像是不会伸缩的,

c. 怎么让draw出来的图像适应我们的容器等 

这3个问题都在定义矩阵时必须考虑好的。 要让绘制出来的图像适应容器的大小我们必须计算出一个比例,这个比例主要是用于对图像的等比例缩放用的, 要让两个大小不一样的对象适应我们首先得根据一个比例来缩小图像,而这个的依据就是图像的宽度或者高度那个最大,那个大我们就以那个为参照伸缩, 

方法的实现过程大致如下 
private function getScale(width:Number,height:Number):Number { 



var size:Number; var scale:Number; var num:Number=this.width-this.height var num2:Number=width-height num2<0?size=width:size=height; num>0?scale=size/this.width:scale=size/this.height; return scale 



} 

通过这样的处理我们就可以得到一个缩放的比例, 然后下边就是绘制一张完整的图像,像之前说的那样我们在draw时还需要对将像素进行平移, 平移的依据我们可以根据getBounds这个放来来获取我们要绘制的对象的信息矩形, 在得到图像的信息后我们只要让 matrix的tx,ty减去这个像素的开始点就好~因为如果像素开始点是负数,那么我们 减去实际是在x轴跟y轴增加相应像素,这个处理完后我们还要处理掉可是对象原先的缩放问题 于是我们得到下边的过程 
public function draw(container:DisplayObjectContainer,target:DisplayObject,width:Number=150,height:Number=200):BitmapData { var rect:Rectangle=target.getBounds(target) var scale:Number=getScale(width,height); var vw:Number=(width-target.width*scale)/2; var vh:Number=(height-target.height*scale)/2; this.samllMapBMD=new BitmapData(width,height,true,0); var matrix:Matrix=new Matrix; matrix.tx-=rect.topLeft.x; matrix.ty-=rect.topLeft.y; matrix.scale(scale,scale); matrix.scale(target.scaleX,target.scaleY) matrix.tx+=vw; matrix.ty+=vh; var rect2: Rectangle=new Rectangle(0,0,width,height) var bitmapdata:Bitmapdata=new Bitmapdata(rect2.width,rect2.height,true,0) bitmapdata.draw(target,matrix,null,null,rect2) return bitmapdata 



}

通过上边的讲解大家现在应该了解怎么去绘制一个自适应图像了~ 这个应用的方法扩展还可以让你去 实现一些诸如随机图片抢等难度相对应大点的应用,因为现在你的图像可以任意适应任何大小的容器,所以你只要预先根据加载对象的高宽特向随机出几个大小不一的容器就可以很方便的实现那样的效果了~