Единая ссылка 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 КБ памяти. Проигрывателю Flash Player 10.1 на настольных системах и мобильных устройствах для этого требуется всего 4 КБ.

Следующий код изменяет один экземпляр 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, выполняющего модификацию пикселов, в памяти создается новый экземпляр, а остальные экземпляры не обновляются. На следующем рисунке показан этот подход.

Память при изменении одного растрового изображения

При изменении одной звезды в памяти создается новая копия. Полученная анимация занимает в памяти около 8 КБ при воспроизведении с помощью Flash Player 10.1 и AIR 2.5.

В предыдущем примере каждое растровое изображение преобразовывается отдельно. Если требуется лишь создать эффект плитки, лучше всего использовать метод 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. Для непрерывного вращения звезд (вместо вращения каждого экземпляра Star по отдельности) используйте объект Matrix, который поворачивается в каждом кадре. Передайте объект 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 с растровыми заливками.