BitmapData 单个引用

通过尽量重复使用实例来优化 BitmapData 类的使用,这一点非常重要。Flash Player 10.1 和 AIR 2.5 引入了一个适用于所有平台的新功能,称为 BitmapData 单个引用。从嵌入图像创建 BitmapData 实例时,将对所有 BitmapData 实例使用位图的同一版本。如果稍后修改位图,则在内存中为该位图提供其自身的唯一位图。嵌入的图像可来自库或 [Embed] 标签。

注: 此新功能同样适用于当前内容,因为 Flash Player 10.1 和 AIR 2.5 会自动重复使用位图。

当实例化嵌入的图像时,将在内存中创建相关联的位图。在 Flash Player 10.1 和 AIR 2.5 之前的版本中,内存中为每个实例都提供了一个单独的位图,如下图所示:

运行 Flash Player 10.1 和 AIR 2.5 之前,内存中的位图

在 Flash Player 10.1 和 AIR 2.5 中,当创建同一图像的多个实例时,单个版本的位图将用于所有 BitmapData 实例。下图演示了此概念:

Flash Player 10.1 内存中的位图 和 AIR 2.5

此方法大大降低了具有许多位图的应用程序的内存使用量。以下代码创建了 Star 符号的多个实例:

const MAX_NUM:int = 18; 
 
var star:BitmapData; 
var bitmap:Bitmap; 
 
for (var i:int = 0; i<MAX_NUM; i++) 
{ 
    for (var j:int = 0; j<MAX_NUM; j++) 
    { 
        star = new Star(0,0); 
        bitmap = new Bitmap(star); 
        bitmap.x = j * star.width; 
        bitmap.y = i * star.height; 
        addChild(bitmap) 
    } 
}

下图显示该代码的效果:

查看完全大小图形
用于创建多个符号实例的代码的效果

例如,使用 Flash Player 10 时,上面的动画使用大约 1008 KB 内存。使用 Flash Player 10.1 时,在台式机和移动设备上该动画只使用 4 KB。

以下代码修改一个 BitmapData 实例:

const MAX_NUM:int = 18; 
 
var star:BitmapData; 
var bitmap:Bitmap; 
 
for (var i:int = 0; i<MAX_NUM; i++) 
{ 
    for (var j:int = 0; j<MAX_NUM; j++) 
    { 
        star = new Star(0,0); 
        bitmap = new Bitmap(star); 
        bitmap.x = j * star.width; 
        bitmap.y = i * star.height; 
        addChild(bitmap) 
    } 
} 
 
var ref:Bitmap = getChildAt(0) as Bitmap; 
 
ref.bitmapData.pixelDissolve(ref.bitmapData, ref.bitmapData.rect, new Point(0,0),Math.random()*200,Math.random()*200, 0x990000);

下图显示修改一个 Star 实例的效果:

查看完全大小图形
修改一个实例的效果

在内部,运行时会在内存中自动分配和创建位图以处理像素修改。当调用的 BitmapData 类的方法导致像素修改时,将在内存中创建一个新实例,而不更新其他实例。下图演示了此概念:

修改一个位图后,内存中的效果

如果修改一个星星,则在内存中创建一个新的副本。在 Flash Player 10.1 和 AIR 2.5 上,生成的动画使用大约 8 KB 内存。

在上一示例中,各个位图可单独用于转换。要仅创建平铺效果,则 beginBitmapFill() 方法是最合适的方法:

var container:Sprite = new Sprite(); 
 
var source:BitmapData = new Star(0,0); 
 
// Fill the surface with the source BitmapData 
container.graphics.beginBitmapFill(source); 
container.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight); 
 
addChild(container);

此方法与仅创建一个 BitmapData 实例的效果相同。要连续旋转星形,请使用绕各个帧旋转的 Matrix 对象,而不是访问各个 Star 实例。将此 Matrix 对象传递给 beginBitmapFill() 方法:

var container:Sprite = new Sprite(); 
 
container.addEventListener(Event.ENTER_FRAME, rotate); 
 
var source:BitmapData = new Star(0,0); 
var matrix:Matrix = new Matrix(); 
 
addChild(container); 
 
var angle:Number = .01; 
 
function rotate(e:Event):void 
{ 
    // Rotate the stars 
    matrix.rotate(angle); 
 
    // Clear the content 
    container.graphics.clear(); 
  
    // Fill the surface with the source BitmapData 
    container.graphics.beginBitmapFill(source,matrix,true,true); 
    container.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight); 
}

借助此技术,无需 ActionScript 循环即可创建这种效果。运行时在内部执行所有操作。下图显示转换星形的效果:

查看完全大小图形
旋转星形的效果

借助此方法,更新原始的源 BitmapData 对象时将自动更新其在舞台上的所有使用,这可能是一项功能强大的技术。然而,此方法不允许单独缩放各个星形,如前面的示例中所示。

注: 当使用同一图像的多个实例时,将根据某个类是否与内存中的原始位图相关联进行绘图。如果不存在与位图相关联的类,则图像将作为 Shape 对象使用位图填充进行绘制。