import {BitmapImage2D} from "../image/BitmapImage2D"; import {ImageCube} from "../image/ImageCube"; import {BlendMode} from "../image/BlendMode"; import {ColorTransform} from "../geom/ColorTransform"; import {Matrix} from "../geom/Matrix"; import {Rectangle} from "../geom/Rectangle"; import {Point} from "../geom/Point"; import {ByteArray} from "../utils/ByteArray"; import {ColorUtils} from "../utils/ColorUtils"; import {BitmapImageUtils} from "../utils/BitmapImageUtils"; /** * The BitmapImage2D export class lets you work with the data(pixels) of a Bitmap * object. You can use the methods of the BitmapImage2D export class to create * arbitrarily sized transparent or opaque bitmap images and manipulate them * in various ways at runtime. You can also access the BitmapImage2D for a bitmap * image that you load with the flash.Assets or * flash.display.Loader classes. * *

This export class lets you separate bitmap rendering operations from the * internal display updating routines of flash. By manipulating a * BitmapImage2D object directly, you can create complex images without incurring * the per-frame overhead of constantly redrawing the content from vector * data.

* *

The methods of the BitmapImage2D export class support effects that are not * available through the filters available to non-bitmap display objects.

* *

A BitmapImage2D object contains an array of pixel data. This data can * represent either a fully opaque bitmap or a transparent bitmap that * contains alpha channel data. Either type of BitmapImage2D object is stored as * a buffer of 32-bit integers. Each 32-bit integer determines the properties * of a single pixel in the bitmap.

* *

Each 32-bit integer is a combination of four 8-bit channel values(from * 0 to 255) that describe the alpha transparency and the red, green, and blue * (ARGB) values of the pixel.(For ARGB values, the most significant byte * represents the alpha channel value, followed by red, green, and blue.)

* *

The four channels(alpha, red, green, and blue) are represented as * numbers when you use them with the BitmapImage2D.copyChannel() * method or the DisplacementMapFilter.componentX and * DisplacementMapFilter.componentY properties, and these numbers * are represented by the following constants in the BitmapImage2DChannel * class:

* * * *

You can attach BitmapImage2D objects to a Bitmap object by using the * bitmapData property of the Bitmap object.

* *

You can use a BitmapImage2D object to fill a Graphics object by using the * Graphics.beginBitmapFill() method.

* *

You can also use a BitmapImage2D object to perform batch tile rendering * using the flash.display.Tilesheet class.

* *

In Flash Player 10, the maximum size for a BitmapImage2D object * is 8,191 pixels in width or height, and the total number of pixels cannot * exceed 16,777,215 pixels.(So, if a BitmapImage2D object is 8,191 pixels wide, * it can only be 2,048 pixels high.) In Flash Player 9 and earlier, the limitation * is 2,880 pixels in height and 2,880 in width.

*/ export class BitmapImageCube extends ImageCube { public static assetType:string = "[image BitmapImageCube]"; public static posX:number = 0; public static negX:number = 1; public static posY:number = 2; public static negY:number = 3; public static posZ:number = 4; public static negZ:number = 5; private _imageCanvas:Array = new Array(6); private _context:Array = new Array(6); private _imageData:Array = new Array(6); private _transparent:boolean; private _locked:boolean = false; /** * * @returns {string} */ public get assetType():string { return BitmapImageCube.assetType; } /** * Defines whether the bitmap image supports per-pixel transparency. You can * set this value only when you construct a BitmapImage2D object by passing in * true for the transparent parameter of the * constructor. Then, after you create a BitmapImage2D object, you can check * whether it supports per-pixel transparency by determining if the value of * the transparent property is true. */ public get transparent():boolean { return this._transparent; } public set transparent(value:boolean) { this._transparent = value; } /** * Creates a BitmapImage2D object with a specified width and height. If you * specify a value for the fillColor parameter, every pixel in * the bitmap is set to that color. * *

By default, the bitmap is created as transparent, unless you pass * the value false for the transparent parameter. After you * create an opaque bitmap, you cannot change it to a transparent bitmap. * Every pixel in an opaque bitmap uses only 24 bits of color channel * information. If you define the bitmap as transparent, every pixel uses 32 * bits of color channel information, including an alpha transparency * channel.

* * @param width The width of the bitmap image in pixels. * @param height The height of the bitmap image in pixels. * @param transparent Specifies whether the bitmap image supports per-pixel * transparency. The default value is true * (transparent). To create a fully transparent bitmap, * set the value of the transparent * parameter to true and the value of the * fillColor parameter to 0x00000000(or to * 0). Setting the transparent property to * false can result in minor improvements * in rendering performance. * @param fillColor A 32-bit ARGB color value that you use to fill the * bitmap image area. The default value is * 0xFFFFFFFF(solid white). */ constructor(size:number, transparent:boolean = true, fillColor:number = null) { super(size); this._transparent = transparent; for (var i:number = 0; i < 6; i++) { this._imageCanvas[i] = document.createElement("canvas"); this._imageCanvas[i].width = size; this._imageCanvas[i].height = size; this._context[i] = this._imageCanvas[i].getContext("2d"); if (fillColor != null) this.fillRect(i, new Rectangle(0, 0, size, size), fillColor); } } /** * Returns a new BitmapImage2D object that is a clone of the original instance * with an exact copy of the contained bitmap. * * @return A new BitmapImage2D object that is identical to the original. */ public clone():BitmapImageCube { var t:BitmapImageCube = new BitmapImageCube(this._size, this.transparent); for (var i:number = 0; i < 6; i++) { t.draw(i, this.getCanvas(i)); } return t; } /** * Adjusts the color values in a specified area of a bitmap image by using a * ColorTransform object. If the rectangle matches the * boundaries of the bitmap image, this method transforms the color values of * the entire image. * * @param rect A Rectangle object that defines the area of the * image in which the ColorTransform object is applied. * @param colorTransform A ColorTransform object that describes the color * transformation values to apply. */ public colorTransform(side:number, rect:Rectangle, colorTransform:ColorTransform):void { if (!this._locked) this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); var data:Uint8ClampedArray = this._imageData[side].data; var i:number, j:number, index:number; for (i = 0; i < rect.width; ++i) { for (j = 0; j < rect.height; ++j) { index = (i + rect.x + (j + rect.y)*this._size)*4; data[index] = data[index]*colorTransform.redMultiplier + colorTransform.redOffset; data[index + 1] = data[index + 1]*colorTransform.greenMultiplier + colorTransform.greenOffset; data[index + 2] = data[index + 2]*colorTransform.blueMultiplier + colorTransform.blueOffset; data[index + 3] = data[index + 3]*colorTransform.alphaMultiplier + colorTransform.alphaOffset; } } if (!this._locked) { this._context[side].putImageData(this._imageData[side], 0, 0); this._imageData[side] = null; } this.invalidate(); } /** * Transfers data from one channel of another BitmapImage2D object or the * current BitmapImage2D object into a channel of the current BitmapImage2D object. * All of the data in the other channels in the destination BitmapImage2D object * are preserved. * *

The source channel value and destination channel value can be one of * following values:

* *
    *
  • BitmapImage2DChannel.RED
  • *
  • BitmapImage2DChannel.GREEN
  • *
  • BitmapImage2DChannel.BLUE
  • *
  • BitmapImage2DChannel.ALPHA
  • *
* * @param sourceBitmapImage2D The input bitmap image to use. The source image * can be a different BitmapImage2D object or it can * refer to the current BitmapImage2D object. * @param sourceRect The source Rectangle object. To copy only channel * data from a smaller area within the bitmap, * specify a source rectangle that is smaller than * the overall size of the BitmapImage2D object. * @param destPoint The destination Point object that represents the * upper-left corner of the rectangular area where * the new channel data is placed. To copy only * channel data from one area to a different area in * the destination image, specify a point other than * (0,0). * @param sourceChannel The source channel. Use a value from the * BitmapImage2DChannel class * (BitmapImage2DChannel.RED, * BitmapImage2DChannel.BLUE, * BitmapImage2DChannel.GREEN, * BitmapImage2DChannel.ALPHA). * @param destChannel The destination channel. Use a value from the * BitmapImage2DChannel class * (BitmapImage2DChannel.RED, * BitmapImage2DChannel.BLUE, * BitmapImage2DChannel.GREEN, * BitmapImage2DChannel.ALPHA). * @throws TypeError The sourceBitmapImage2D, sourceRect or destPoint are null. */ public copyChannel(side:number, sourceBitmap:BitmapImage2D, sourceRect:Rectangle, destPoint:Point, sourceChannel:number, destChannel:number):void { var imageData:ImageData = sourceBitmap.getImageData(); if (!this._locked) this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); var sourceData:Uint8ClampedArray = sourceBitmap.getImageData().data; var destData:Uint8ClampedArray = this._imageData[side].data; var sourceOffset:number = Math.round(Math.log(sourceChannel)/Math.log(2)); var destOffset:number = Math.round(Math.log(destChannel)/Math.log(2)); var i:number, j:number, sourceIndex:number, destIndex:number; for (i = 0; i < sourceRect.width; ++i) { for (j = 0; j < sourceRect.height; ++j) { sourceIndex = (i + sourceRect.x + (j + sourceRect.y)*sourceBitmap.width)*4; destIndex = (i + destPoint.x + (j + destPoint.y)*this._size)*4; destData[destIndex + destOffset] = sourceData[sourceIndex + sourceOffset]; } } if (!this._locked) { this._context[side].putImageData(this._imageData[side], 0, 0); this._imageData[side] = null; } this.invalidate(); } /** * Provides a fast routine to perform pixel manipulation between images with * no stretching, rotation, or color effects. This method copies a * rectangular area of a source image to a rectangular area of the same size * at the destination point of the destination BitmapImage2D object. * *

If you include the alphaBitmap and alphaPoint * parameters, you can use a secondary image as an alpha source for the * source image. If the source image has alpha data, both sets of alpha data * are used to composite pixels from the source image to the destination * image. The alphaPoint parameter is the point in the alpha * image that corresponds to the upper-left corner of the source rectangle. * Any pixels outside the intersection of the source image and alpha image * are not copied to the destination image.

* *

The mergeAlpha property controls whether or not the alpha * channel is used when a transparent image is copied onto another * transparent image. To copy pixels with the alpha channel data, set the * mergeAlpha property to true. By default, the * mergeAlpha property is false.

* * @param sourceBitmapImage2D The input bitmap image from which to copy pixels. * The source image can be a different BitmapImage2D * instance, or it can refer to the current * BitmapImage2D instance. * @param sourceRect A rectangle that defines the area of the source * image to use as input. * @param destPoint The destination point that represents the * upper-left corner of the rectangular area where * the new pixels are placed. * @param alphaBitmapImage2D A secondary, alpha BitmapImage2D object source. * @param alphaPoint The point in the alpha BitmapImage2D object source * that corresponds to the upper-left corner of the * sourceRect parameter. * @param mergeAlpha To use the alpha channel, set the value to * true. To copy pixels with no alpha * channel, set the value to false. * @throws TypeError The sourceBitmapImage2D, sourceRect, destPoint are null. */ public copyPixels(side:number, source:BitmapImage2D, sourceRect:Rectangle, destRect:Rectangle); public copyPixels(side:number, source:HTMLImageElement, sourceRect:Rectangle, destRect:Rectangle); public copyPixels(side:number, source:any, sourceRect:Rectangle, destRect:Rectangle):void { if (source instanceof BitmapImage2D) source = source.getCanvas(); if (this._locked) { // If canvas is locked: // // 1) copy image data back to canvas // 2) draw object // 3) read _imageData back out this._context[side].putImageData(this._imageData[side], 0, 0); // at coords 0,0 BitmapImageUtils._copyPixels(this._context[side], source, sourceRect, destRect); this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); } else { BitmapImageUtils._copyPixels(this._context[side], source, sourceRect, destRect); } this.invalidate(); } /** * Frees memory that is used to store the BitmapImage2D object. * *

When the dispose() method is called on an image, the width * and height of the image are set to 0. All subsequent calls to methods or * properties of this BitmapImage2D instance fail, and an exception is thrown. *

* *

BitmapImage2D.dispose() releases the memory occupied by the * actual bitmap data, immediately(a bitmap can consume up to 64 MB of * memory). After using BitmapImage2D.dispose(), the BitmapImage2D * object is no longer usable and an exception may be thrown if * you call functions on the BitmapImage2D object. However, * BitmapImage2D.dispose() does not garbage collect the BitmapImage2D * object(approximately 128 bytes); the memory occupied by the actual * BitmapImage2D object is released at the time the BitmapImage2D object is * collected by the garbage collector.

* */ public dispose():void { super.dispose(); for (var i:number = 0; i < 6; i++) { this._context[i] = null; this._imageCanvas[i] = null; this._imageData[i] = null; } this._transparent = null; this._locked = null; } /** * Draws the source display object onto the bitmap image, using * the NME software renderer. You can specify matrix, * colorTransform, blendMode, and a destination * clipRect parameter to control how the rendering performs. * Optionally, you can specify whether the bitmap should be smoothed when * scaled(this works only if the source object is a BitmapImage2D object). * *

The source display object does not use any of its applied * transformations for this call. It is treated as it exists in the library * or file, with no matrix transform, no color transform, and no blend mode. * To draw a display object(such as a movie clip) by using its own transform * properties, you can copy its transform property object to the * transform property of the Bitmap object that uses the * BitmapImage2D object.

* * @param source The display object or BitmapImage2D object to draw to * the BitmapImage2D object.(The DisplayObject and * BitmapImage2D classes implement the IBitmapDrawable * interface.) * @param matrix A Matrix object used to scale, rotate, or translate * the coordinates of the bitmap. If you do not want to * apply a matrix transformation to the image, set this * parameter to an identity matrix, created with the * default new Matrix() constructor, or * pass a null value. * @param colorTransform A ColorTransform object that you use to adjust the * color values of the bitmap. If no object is * supplied, the bitmap image's colors are not * transformed. If you must pass this parameter but you * do not want to transform the image, set this * parameter to a ColorTransform object created with * the default new ColorTransform() * constructor. * @param blendMode A string value, from the flash.display.BlendMode * class, specifying the blend mode to be applied to * the resulting bitmap. * @param clipRect A Rectangle object that defines the area of the * source object to draw. If you do not supply this * value, no clipping occurs and the entire source * object is drawn. * @param smoothing A Boolean value that determines whether a BitmapImage2D * object is smoothed when scaled or rotated, due to a * scaling or rotation in the matrix * parameter. The smoothing parameter only * applies if the source parameter is a * BitmapImage2D object. With smoothing set * to false, the rotated or scaled * BitmapImage2D image can appear pixelated or jagged. For * example, the following two images use the same * BitmapImage2D object for the source * parameter, but the smoothing parameter * is set to true on the left and * false on the right: * *

Drawing a bitmap with smoothing set * to true takes longer than doing so with * smoothing set to * false.

* @throws ArgumentError The source parameter is not a * BitmapImage2D or DisplayObject object. * @throws ArgumentError The source is null or not a valid IBitmapDrawable * object. * @throws SecurityError The source object and(in the case of a * Sprite or MovieClip object) all of its child objects * do not come from the same domain as the caller, or * are not in a content that is accessible to the * caller by having called the * Security.allowDomain() method. This * restriction does not apply to AIR content in the * application security sandbox. */ public draw(side:number, source:BitmapImage2D, matrix?:Matrix, colorTransform?:ColorTransform, blendMode?:BlendMode, clipRect?:Rectangle, smoothing?:boolean); public draw(side:number, source:HTMLElement, matrix?:Matrix, colorTransform?:ColorTransform, blendMode?:BlendMode, clipRect?:Rectangle, smoothing?:boolean); public draw(side:number, source:any, matrix?:Matrix, colorTransform?:ColorTransform, blendMode?:BlendMode, clipRect?:Rectangle, smoothing?:boolean):void { if (source instanceof BitmapImage2D) source = source.getCanvas(); if (this._locked) { // If canvas is locked: // // 1) copy image data back to canvas // 2) draw object // 3) read _imageData back out this._context[side].putImageData(this._imageData[side], 0, 0); // at coords 0,0 BitmapImageUtils._draw(this._context[side], source, matrix, colorTransform, blendMode, clipRect, smoothing); this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); } else { BitmapImageUtils._draw(this._context[side], source, matrix, colorTransform, blendMode, clipRect, smoothing); } this.invalidate(); } /** * Fills a rectangular area of pixels with a specified ARGB color. * * @param rect The rectangular area to fill. * @param color The ARGB color value that fills the area. ARGB colors are * often specified in hexadecimal format; for example, * 0xFF336699. * @throws TypeError The rect is null. */ public fillRect(side:number, rect:Rectangle, color:number):void { if (this._locked) { // If canvas is locked: // // 1) copy image data back to canvas // 2) apply fill // 3) read _imageData back out if (this._imageData[side]) this._context[side].putImageData(this._imageData[side], 0, 0); // at coords 0,0 BitmapImageUtils._fillRect(this._context[side], rect, color, this._transparent); if (this._imageData[side]) this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); } else { BitmapImageUtils._fillRect(this._context[side], rect, color, this._transparent); } this.invalidate(); } /** * Returns an integer that represents an RGB pixel value from a BitmapImage2D * object at a specific point(x, y). The * getPixel() method returns an unmultiplied pixel value. No * alpha information is returned. * *

All pixels in a BitmapImage2D object are stored as premultiplied color * values. A premultiplied image pixel has the red, green, and blue color * channel values already multiplied by the alpha data. For example, if the * alpha value is 0, the values for the RGB channels are also 0, independent * of their unmultiplied values. This loss of data can cause some problems * when you perform operations. All BitmapImage2D methods take and return * unmultiplied values. The internal pixel representation is converted from * premultiplied to unmultiplied before it is returned as a value. During a * set operation, the pixel value is premultiplied before the raw image pixel * is set.

* * @param x The x position of the pixel. * @param y The y position of the pixel. * @return A number that represents an RGB pixel value. If the(x, * y) coordinates are outside the bounds of the image, the * method returns 0. */ public getPixel(side:number, x:number, y:number):number { var r:number; var g:number; var b:number; var a:number; if (!this._locked) { var pixelData:ImageData = this._context[side].getImageData(x, y, 1, 1); r = pixelData.data[0]; g = pixelData.data[1]; b = pixelData.data[2]; a = pixelData.data[3]; } else { var index:number = (x + y*this._size)*4; r = this._imageData[side].data[index + 0]; g = this._imageData[side].data[index + 1]; b = this._imageData[side].data[index + 2]; a = this._imageData[side].data[index + 3]; } //returns black if fully transparent if (!a) return 0x0; return (r << 16) | (g << 8) | b; } /** * Returns an ARGB color value that contains alpha channel data and RGB data. * This method is similar to the getPixel() method, which * returns an RGB color without alpha channel data. * *

All pixels in a BitmapImage2D object are stored as premultiplied color * values. A premultiplied image pixel has the red, green, and blue color * channel values already multiplied by the alpha data. For example, if the * alpha value is 0, the values for the RGB channels are also 0, independent * of their unmultiplied values. This loss of data can cause some problems * when you perform operations. All BitmapImage2D methods take and return * unmultiplied values. The internal pixel representation is converted from * premultiplied to unmultiplied before it is returned as a value. During a * set operation, the pixel value is premultiplied before the raw image pixel * is set.

* * @param x The x position of the pixel. * @param y The y position of the pixel. * @return A number representing an ARGB pixel value. If the(x, * y) coordinates are outside the bounds of the image, 0 is * returned. */ public getPixel32(side:number, x, y):number { var r:number; var g:number; var b:number; var a:number; if (!this._locked) { var pixelData:ImageData = this._context[side].getImageData(x, y, 1, 1); r = pixelData.data[0]; g = pixelData.data[1]; b = pixelData.data[2]; a = pixelData.data[3]; } else { var index:number = (x + y*this._size)*4; r = this._imageData[side].data[index + 0]; g = this._imageData[side].data[index + 1]; b = this._imageData[side].data[index + 2]; a = this._imageData[side].data[index + 3]; } return (a << 24) | (r << 16) | (g << 8) | b; } /** * Locks an image so that any objects that reference the BitmapImage2D object, * such as Bitmap objects, are not updated when this BitmapImage2D object * changes. To improve performance, use this method along with the * unlock() method before and after numerous calls to the * setPixel() or setPixel32() method. * */ public lock():void { if (this._locked) return; this._locked = true; for (var i:number = 0; i < 6; i++) this._imageData[i] = this._context[i].getImageData(0, 0, this._size, this._size); } /** * Converts an Array into a rectangular region of pixel data. For each pixel, * an Array element is read and written into the BitmapImage2D pixel. The data * in the Array is expected to be 32-bit ARGB pixel values. * * @param rect Specifies the rectangular region of the BitmapImage2D * object. * @param inputArray An Array that consists of 32-bit unmultiplied pixel * values to be used in the rectangular region. * @throws RangeError The vector array is not large enough to read all the * pixel data. */ public setArray(side:number, rect:Rectangle, inputArray:Array):void { if (!this._locked) this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); var i:number, j:number, index:number, argb:number[]; for (i = 0; i < rect.width; ++i) { for (j = 0; j < rect.height; ++j) { argb = ColorUtils.float32ColorToARGB(inputArray[i + j*rect.width]); index = (i + rect.x + (j + rect.y)*this._size)*4; this._imageData[side].data[index + 0] = argb[1]; this._imageData[side].data[index + 1] = argb[2]; this._imageData[side].data[index + 2] = argb[3]; this._imageData[side].data[index + 3] = argb[0]; } } if (!this._locked) { this._context[side].putImageData(this._imageData[side], 0, 0); this._imageData[side] = null; } this.invalidate(); } /** * Sets a single pixel of a BitmapImage2D object. The current alpha channel * value of the image pixel is preserved during this operation. The value of * the RGB color parameter is treated as an unmultiplied color value. * *

Note: To increase performance, when you use the * setPixel() or setPixel32() method repeatedly, * call the lock() method before you call the * setPixel() or setPixel32() method, and then call * the unlock() method when you have made all pixel changes. * This process prevents objects that reference this BitmapImage2D instance from * updating until you finish making the pixel changes.

* * @param x The x position of the pixel whose value changes. * @param y The y position of the pixel whose value changes. * @param color The resulting RGB color for the pixel. */ public setPixel(side:number, x:number, y:number, color:number):void { var argb:number[] = ColorUtils.float32ColorToARGB(color); if (!this._locked) this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); var index:number = (x + y*this._size)*4; this._imageData[side].data[index + 0] = argb[1]; this._imageData[side].data[index + 1] = argb[2]; this._imageData[side].data[index + 2] = argb[3]; this._imageData[side].data[index + 3] = 255; if (!this._locked) { this._context[side].putImageData(this._imageData[side], 0, 0); this._imageData = null; } this.invalidate(); } /** * Sets the color and alpha transparency values of a single pixel of a * BitmapImage2D object. This method is similar to the setPixel() * method; the main difference is that the setPixel32() method * takes an ARGB color value that contains alpha channel information. * *

All pixels in a BitmapImage2D object are stored as premultiplied color * values. A premultiplied image pixel has the red, green, and blue color * channel values already multiplied by the alpha data. For example, if the * alpha value is 0, the values for the RGB channels are also 0, independent * of their unmultiplied values. This loss of data can cause some problems * when you perform operations. All BitmapImage2D methods take and return * unmultiplied values. The internal pixel representation is converted from * premultiplied to unmultiplied before it is returned as a value. During a * set operation, the pixel value is premultiplied before the raw image pixel * is set.

* *

Note: To increase performance, when you use the * setPixel() or setPixel32() method repeatedly, * call the lock() method before you call the * setPixel() or setPixel32() method, and then call * the unlock() method when you have made all pixel changes. * This process prevents objects that reference this BitmapImage2D instance from * updating until you finish making the pixel changes.

* * @param x The x position of the pixel whose value changes. * @param y The y position of the pixel whose value changes. * @param color The resulting ARGB color for the pixel. If the bitmap is * opaque(not transparent), the alpha transparency portion of * this color value is ignored. */ public setPixel32(side:number, x, y, color:number):void { var argb:number[] = ColorUtils.float32ColorToARGB(color); if (!this._locked) this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); var index:number = (x + y*this._size)*4; this._imageData[side].data[index + 0] = argb[1]; this._imageData[side].data[index + 1] = argb[2]; this._imageData[side].data[index + 2] = argb[3]; this._imageData[side].data[index + 3] = argb[0]; if (!this._locked) { this._context[side].putImageData(this._imageData[side], 0, 0); this._imageData[side] = null; } this.invalidate(); } /** * Converts a byte array into a rectangular region of pixel data. For each * pixel, the ByteArray.readUnsignedInt() method is called and * the return value is written into the pixel. If the byte array ends before * the full rectangle is written, the function returns. The data in the byte * array is expected to be 32-bit ARGB pixel values. No seeking is performed * on the byte array before or after the pixels are read. * * @param rect Specifies the rectangular region of the BitmapImage2D * object. * @param inputByteArray A ByteArray object that consists of 32-bit * unmultiplied pixel values to be used in the * rectangular region. * @throws EOFError The inputByteArray object does not include * enough data to fill the area of the rect * rectangle. The method fills as many pixels as possible * before throwing the exception. * @throws TypeError The rect or inputByteArray are null. */ public setPixels(side:number, rect:Rectangle, inputByteArray:ByteArray):void { if (!this._locked) this._imageData[side] = this._context[side].getImageData(0, 0, this._size, this._size); inputByteArray.position = 0; var i:number, j:number, index:number; for (i = 0; i < rect.width; ++i) { for (j = 0; j < rect.height; ++j) { index = (i + rect.x + (j + rect.y)*this._size)*4; this._imageData[side].data[index + 0] = inputByteArray.readUnsignedInt(); this._imageData[side].data[index + 1] = inputByteArray.readUnsignedInt(); this._imageData[side].data[index + 2] = inputByteArray.readUnsignedInt(); this._imageData[side].data[index + 3] = inputByteArray.readUnsignedInt(); } } if (!this._locked) { this._context[side].putImageData(this._imageData[side], 0, 0); this._imageData[side] = null; } this.invalidate(); } /** * Unlocks an image so that any objects that reference the BitmapImage2D object, * such as Bitmap objects, are updated when this BitmapImage2D object changes. * To improve performance, use this method along with the lock() * method before and after numerous calls to the setPixel() or * setPixel32() method. * * @param changeRect The area of the BitmapImage2D object that has changed. If * you do not specify a value for this parameter, the * entire area of the BitmapImage2D object is considered * changed. */ public unlock():void { if (!this._locked) return; this._locked = false; for (var i:number = 0; i < 6; i++) { this._context[i].putImageData(this._imageData[i], 0, 0); // at coords 0,0 this._imageData[i] = null; } } /** * * @returns {ImageData} */ public getImageData(side:number):ImageData { if (!this._locked) return this._context[side].getImageData(0, 0, this._size, this._size); return this._imageData[side]; } /** * * @returns {HTMLCanvasElement} */ public getCanvas(side:number):HTMLCanvasElement { return this._imageCanvas[side]; } /** * * @param width * @param height * @private */ public _setSize(size:number):void { super._setSize(size); for (var i:number = 0; i < 6; i++) { if (this._locked) this._context[i].putImageData(this._imageData[i], 0, 0); this._imageCanvas[i].width = size; this._imageCanvas[i].height = size; if (this._locked) this._imageData[i] = this._context[i].getImageData(0, 0, this._size, this._size); } } }