`

[转] BitmapData 基础部分2

阅读更多
http://bbs.9ria.com/thread-73321-1-1.html

BitmapData 基础部分2

这篇文章是我对flash.display.BitmapData对象的第二篇总结.第一篇地址.

首先让我们来了解一下颜色

操作颜色

所有的显示对象都有一个transform 属性,这个属性允许我们对该显示对象应用各种各样的变换-例如变形和颜色转换等.下面有个转换公式:
var ct:ColorTransform = new ColorTransform(rM, gM, bM, aM, rO, gO, bO, aO);
myDisplayObject.transform.colorTransform = ct;


每个颜色的通道都被转换了:
new red = (rM * old red) + rO
new green = (gM * old green) + gO
new blue = (bM * old blue) + bO
new alpha = (aM * old alpha) + aO


你可能注意到了一旦ColorTransform被设置就不能通过设置null来移除它(你会得到的一个运行时错误);如果要移除它,只需要将一个新的默认值的ColorTransform设置上就可以了.
myDisplayObject.transform.colorTransform = new ColorTransform();


还有,为表现出我们想要的效果我们不得不为其设置一个全新的ColorTransform 对象---设置显示对象ColorTransform 的个别的属性不会产生任何效果.
//won't work:

myDisplayObject.transform.colorTransform.redOffset = 25;

//will work:

//get existing transform

var ct:ColorTransform = myDisplayObject.transform.colorTransform;

//amend transform

ct.redOffset = 25;

//apply transform

myDisplayObject.transform.colorTransform = ct;


这个colour transforming 可以用于任何显示对象(包括Bitmap),所以它是一个非常有用的工具.但是本篇的内容主要为BitmaData;它不是一个显示对象并且对BitmapData对象使用colour transform 时操作会有一点点不同.我认为显示对象的transform 就如同在该对象上覆盖一个图层然后对该图层染色,BitmapData 对象则是直接在该对象上面操作.
myBitmapDataObject.colorTransform(new Rectangle(...), new ColorTransform(...));


Rectangle 对象定义了图像要transform 的区域.
package

{

    import flash.display.Bitmap;

    import flash.display.BitmapData;

    import flash.display.Sprite;

    import flash.display.StageAlign;

    import flash.display.StageScaleMode;

    import flash.events.Event;

    import flash.events.MouseEvent;

    import flash.geom.ColorTransform;

    import flash.geom.Rectangle;



    [SWF(backgroundColor="#CCCCCC", frameRate="30", width="200", height="200")]

    public class BitmapDataExample3 extends Sprite

    {

        private var bm:Bitmap;

        private var count:Number = 0;



        public function BitmapDataExample3()

        {

            //do some general housekeeping

            stage.align = StageAlign.TOP_LEFT;

            stage.scaleMode = StageScaleMode.NO_SCALE;



            //create a new BitmapData object filled with random noise

            var bmd:BitmapData = new BitmapData(100, 100, false, 0x000000);

            bmd.noise(Math.random()*int.MAX_VALUE);

            //create bitmap and pass in BitmapData object

            bm = new Bitmap(bmd);

            //add bitmap to stage

            bm.x = 50;

            bm.y = 50;

            addChild(bm);

            //add loop

            addEventListener(Event.ENTER_FRAME, loop);

            //add listener

            stage.addEventListener(MouseEvent.CLICK, reset);

        }



        //run every frame

        private function loop(event:Event):void

        {

            //define rect to be right half of image

            var rect:Rectangle = new Rectangle(50, 0, 50, 100);

            //define transform

            var ct:ColorTransform = new ColorTransform(1, 1, 1, 1, count);

            //apply transform to image

            bm.bitmapData.colorTransform(rect, ct);

            //update counter

            count += 0.1;

        }



        //called when user clicks anywhere

        private function reset(event:MouseEvent):void

        {

            //remove old bitmapData object

            bm.bitmapData.dispose();

            //insert new bitmapData object

            bm.bitmapData = new BitmapData(100, 100, false, 0x000000);

            //fill with noise

            bm.bitmapData.noise(Math.random()*int.MAX_VALUE);

            //reset counter

            count = 0;

        }



    }

}
复制代码
{BitmapDataExample3}


拷贝颜色

Threshold(...)的作用和part1中的copyPixels很相似,除此之外,根据指定的阈值测试图像中的每个像素值,并将通过测试的像素设置为新的颜色值,如下所示:
var src:BitmapData = otherBitmapData;

var srcRect:Rectangle = otherBitmapData.rect;

var destPoint:Point = new Point(0, 0);

var operation:String = ">=";

var threshold:uint = 0x00800000;

var newColour:uint = 0xFFFFFF00;

var mask:uint = 0x00FF0000;

var copy:Boolean = false;

myBitmapData.threshold(src, srcRect, destPoint, operation, threshold, newColour, mask, copy);


Scr,srcRect和destPoint的作用等同于copyPixels对应参数的作用.另一个参数需要在这里介绍一下;operation和mask 用来判断每个被检测像素点是否符合条件.如果检测通过,则目标像素点被设置为新颜色.如果没有通过检测,则目标像素直接拷贝原始像素.

检测过程其实是一个返回boolean 值(true为通过检测)的操作,它工作原理如下(它的操作符是:“<”, “<=”, “>”, “>=”, “==” 或“!=”):

(pixelValue & mask) operation (threshold & mask)

(译者注peration 为操作符)

在本例中 operation 是“>=”,threshold 是0×00800000,newColour 是0xFFFFFF00 ,mask 是0x00FF0000 所以检测公式就是:

(pixelValue & 0x00FF0000) >= (0×00800000 & 0x00FF0000)

我们可以将其简化为:

(pixelValue & 0xFF0000) >= 0×800000

所以如果pixelValue 与(译者注:逻辑与操作)0xFF0000(ie:红色通道)大于或等于0×800000则使用new的颜色值(0xFFFFFF00 – 黄色) 替代原来的颜色.反之则不做任何操作.如果你觉这一部分就像是在听Klingon 的歌剧(译者注:Klingon 是一种外星人.意指 听天书),你应该去补习一下位操作的相关知识.

{BitmapDataExample4}


Histogram(...)方法用检索图像的颜色通道信息.它需要输入4个分别代表(R, G, B 和A) Vector对象并且返回一个Vector对象.每个Vector都包含了一个介于0-256的数字.

例如:item 47的 红色向量值是100,这就意味着图像中有100个红色通道值为47的像素点.

我们可以通过使用一个矩形参数来定义图像中的的特殊采样区,或者是设置其为null来采样整个图像.

Here’s a stock example that draws a graph of the data returned from histogram(…):

下面是一个通过绘制histogram(…)返回数据的例子:

{BitmapDataExample5}


noise(…)方法的作用在于随机填充,所以图像应该(理想地)会完全的一样(译者注:杂点函数是一个映射函数,不是真正的随机数生成函数,所以它每次都会根据相同的随机种子创建相同的结果),但是我猜测它可能有一个特定值---鼠标点击(产生新的噪点)并没有产生相同的噪点.如果你知道为什么请告诉我---我可能以后会在研究一下.

merge(…) 是另一个和copyPixels很类似的方法---不同之处在于它会融合源图像和目标图像,而不是完全的覆盖源图像.如下所示:
var src:BitmapData = otherBitmapData;

var srcRect:Rectangle = otherBitmapData.rect;

var destPoint:Point = new Point(0, 0);

var r:uint = 128;

var g:uint = 128;

var b:uint = 128;

var a:uint = 128;

myBitmapData.merge(src, srcRect, destPoint, r, g, b, a);


前三个参数和copyPixels 中的参数意义相同,后四个参数决定目标图像和源图像的4个通道值的改变量.每个参数的有效值介于 0(100%提取目标图像)-255 (100%提取源图像).在这里我们将参数全部设置为128,这就意味着从源图像和目标图像的融合度对等.

另一个复制功能的变种方法paletteMap(...):
var src:BitmapData = otherBitmapData;

var srcRect:Rectangle = otherBitmapData.rect;

var destPoint:Point = new Point(0, 0);

var reds:Array = [...];

var greens:Array = [...];

var blues:Array = [...];

var alphas:Array = [...];

myBitmapData.paletteMap(src, srcRect, destPoint, reds, greens, blues, alphas);


相信你已经对前三个参数很熟悉了.剩下的数组应该是分别包含ARGB 的信息(或者他们可以是null).本质上来说,这个方法会根据参数传入的数组将图像的每个像素重新映射成新的颜色.

对于每个像素点,每个新的颜色是这样计算的: a) 源颜色被分成4个通道值介于0-255的整数. B)这四个整数会被当做刚刚的4个数组的索引.c)这四个数组的值被加在一起然后将目标像素的值设置为该值.--如果某个数组为null,则用源图像(这个通道的)的数字代替.我将通过设置特殊值来阐述这一过程:

我们假定源像素的颜色为0xFFFF8000.将其分解成ARGB四通道值:0xFF, 0xFF, 0×80 和 0×00.--或者是10进制:255, 255, 128 和 0.目标像素值和四个数组中值的和相关的:alphas[255] + reds[255] + greens[128] + blues[0].

想着就头疼---我在flash.display.BitmapData的官方文档中找到一个只使用了个2数组和几种颜色的例子.



Filters(滤镜)

应用一个滤镜是非常简单的事儿:
myBitmapData.applyFilter(src, srcRect, destPoint, filter);


对于现在的你,参数名已经可以起到自我解释说明了.

和colorTransform一样,对BitmapData 使用滤镜都会产生持久的效果.此外滤镜的效果范围可能会超出我们定义的区域(虽然没有超出完整的图像)- e.g: 将一个blur x,y为2的滤镜应用于50×50的区域,由于2像素的边缘效果,该滤镜将会在所有方向上延长2像素,即产生54x54的效果区域.这是滤镜自身的一种行为.

应用滤镜的乐趣在于重复嵌套应用滤镜.这里应用了一个滤镜然后绘制一个色块.伴随着时间的不停推移每个色块慢慢变模糊.

{BitmapDataExample6}

package

{

    import flash.display.Bitmap;

    import flash.display.BitmapData;

    import flash.display.Sprite;

    import flash.display.StageAlign;

    import flash.display.StageScaleMode;

    import flash.events.Event;

    import flash.filters.BitmapFilter;

    import flash.filters.BlurFilter;

    import flash.geom.Point;

    import flash.geom.Rectangle;



    [SWF(backgroundColor="#CCCCCC", frameRate="30", width="200", height="200")]

    public class BitmapDataExample6 extends Sprite

    {

        private var bm:Bitmap;

        private var filter:BitmapFilter;



        public function BitmapDataExample6()

        {

            //do some general housekeeping

            stage.align = StageAlign.TOP_LEFT;

            stage.scaleMode = StageScaleMode.NO_SCALE;



            //create filter

            filter = new BlurFilter(2, 2, 1);



            //create a new BitmapData object

            var bmd:BitmapData = new BitmapData(100, 100, false, 0x000000);

            //create bitmap and pass in BitmapData object

            bm = new Bitmap(bmd);

            //add bitmap to stage

            bm.x = 50;

            bm.y = 50;

            addChild(bm);

            //add loop

            addEventListener(Event.ENTER_FRAME, loop);

        }



        //called every frame

        private function loop(event:Event):void

        {

            //apply a blur

            bm.bitmapData.applyFilter(bm.bitmapData, bm.bitmapData.rect, new Point(0, 0), filter);

            //draw new block randomly

            var rect:Rectangle = new Rectangle(Math.random()*90, Math.random()*90, 10, 10);

            bm.bitmapData.fillRect(rect, Math.random()*0xFFFFFF);

        }

    }

}


任何派生自BitmapFilter的类都可以被使用:BevelFilter, BlurFilter, ColorMatrixFilter, ConvolutionFilter, DisplacementMapFilter, DropShadowFilter, GlowFilter, GradientBevelFilter, GradientGlowFilter 和 ShaderFilter.

很多时候,重复的将一个滤镜应用于同一个BitmapData 最终将会产生一个单色的色块--在上面的例子中,如果我们没有新的方块绘制你会发现BlurFilter会将所有东西都变成黑色(0x0000000).其他的如ConvolutionFilter 滤镜会导致褪变成白色.可以通过同时应用一个colorTransform 对象来避免这一现象---这样就可以平衡滤镜的黑白效果了.

这个例子除了调用applyFilter 时不太一样,其他地方和前面的例子一样:
bm.bitmapData.colorTransform(bm.bitmapData.rect, new ColorTransform(1.012, 1.012, 1.012, 1.012, 0, 0, 0, 0));


这里增加了1.2%的亮度刚刚好可以避免方块的消失.(译者注:参数为作者手动暴力测试出来的)

{BitmapDataExample7}

我强烈建议对其他滤镜进行测试---效果的范围可能是无限制的.使用cpu趋向于密集型的是nvolutionFilter, GradientBevelFilter 和 GradientGlowFilter---其他的都是瞬时的.ShaderFilter 使用PixelBender来编码,所以其快慢取决于其工作量.

源代码
分享到:
评论

相关推荐

    flash游戏开发第一张 高级碰撞检测

    通过对比《Advanced ActionScript 3.0 Animation》一书的部分内容,我们将深入了解BitmapData.hitTest在实际应用中的工作原理和技术细节。 #### 二、基础知识回顾 在讨论高级碰撞检测方法之前,我们需要回顾一些...

    spark下_3D立方体翻转

    1. **DisplayObject3D**: 这是Flex 4.5中用于表示3D对象的基础类,你可以创建一个DisplayObject3D实例作为3D场景中的基本元素,例如我们的立方体。 2. **Transform3D**: 这个类提供了对3D对象进行旋转、平移和缩放...

    Flex 图片压缩、上传

    为了上传图片,通常需要将BitmapData转换为Base64编码的字符串,然后作为POST请求的一部分发送到服务器。服务器端则需要解析这个字符串,将其写入文件系统或者存储服务。 博文“Flex 图片压缩、上传”可能会讲解...

    C#图像处理基础.rar

    2. **Bitmap类**:`Bitmap`是`Image`类的一个子类,用于表示位图图像。你可以使用`Bitmap`类创建新的图像,或者从文件、流或资源中加载现有图像。例如: ```csharp Bitmap image = new Bitmap("image.jpg"); ``` ...

    c#图像数据操作例子

    3. **BitmapData的LockBits和UnlockBits**:要访问像素数据,你需要锁定Bitmap的部分或全部区域,获取BitmapData实例,然后解锁。这通常在处理大量像素时提高性能。 ```csharp Rectangle rect = new Rectangle(0, ...

    AcitonScript 3.0游戏开发基础与范例

    《ActionScript 3.0游戏开发基础与范例》是一本深入探讨ActionScript 3.0在游戏开发领域的专著,特别适合初学者和有一定基础的开发者参考学习。ActionScript 3.0是Adobe Flash Professional CS5中的核心编程语言,...

    数字图像处理 文档

    学习这部分内容将为初学者打开数字图像处理的大门,为进一步深入研究图像识别、图像分析等高级话题打下坚实的基础。通过实际项目和练习,可以更好地理解和掌握这些知识点,提高解决问题的能力。

    用GDI+做簡單的圖像處理

    在IT行业中,图像是我们日常开发中不可或缺的一部分,特别是在多媒体应用、游戏开发和数据分析等领域。GDI+(Graphics Device Interface Plus)是微软提供的一种图形处理库,它为Windows应用程序提供了强大的2D图形...

    图片透明、屏蔽背景色、旋转、伸缩

    ### 2. 图像操作基础 #### 2.1 枚举类型定义 - **枚举类型** 在编程中用于定义一组固定的常量集合,通常用于简化代码并提高可读性。 - 给定文件中定义了多个枚举类型,例如 `tpstyle`、`ImageLockMode`、`...

    高级教程ActionScript_3.0_CN

    1. **高级动画**:本部分详细讲解了如何在ActionScript 3.0中实现复杂的动画效果,包括高级碰撞检测技术,如不规则图形的碰撞检测、BitmapData.hitTest方法的应用,以及大量对象的碰撞检测策略。此外,还介绍了基于...

    flash3d 代码

    在AS2中,可以使用BitmapData类来处理图像,并将其切割成合适的部分。 3. **交互事件处理**:添加鼠标监听器,捕捉用户的拖动行为,根据拖动方向更新当前显示的全景条带。 4. **平滑过渡**:为了提供流畅的视觉...

    Actionscript3.0基础语法

    ActionScript 3.0 的基础语法是理解Flash和Flex开发的关键。 首先,我们要了解ActionScript 3.0中的显示对象(DisplayObject)体系。DisplayObject 类是所有可显示元素的基类,包括交互对象和非交互对象。交互对象...

    Flex实现Camera摄像头在线拍照功能

    在探讨“Flex实现Camera摄像头在线拍照功能”这一主题时,我们深入分析了如何利用Adobe Flex框架结合Camera组件来...这些技术点对于开发者而言,是掌握Flex媒体处理能力的重要组成部分,也是构建丰富多媒体应用的基础。

    flash 拼图游戏

    总结来说,通过这个“Flash拼图游戏”,我们可以深入理解Flash的编程基础,包括ActionScript的基本语法、图形处理、事件处理和程序结构。同时,这也是一个很好的实践项目,可以帮助初学者提升编程和设计技能,理解...

    flash-as图像截取

    FLA文件是开发Flash内容的基础,可以用于创建交互式应用程序,如图像截取工具。在`截图.fla`中,你可能会找到舞台上的一个可拖动的矩形组件,这是用户用来选择截取区域的部分。此外,AS代码可能被嵌入到时间轴上的...

    Flash绘图-AS3 Drawing API.pdf

    `ColorTransform` 包括两个主要部分: - **色彩变换**:调整颜色的偏移量和缩放比例。 - **alpha变换**:调整alpha通道的偏移量和缩放比例。 #### 滤镜 Filters 在AS3中,滤镜是一种非常强大的功能,可以用来在运行...

Global site tag (gtag.js) - Google Analytics