// -*- mode:actionscript; encoding: utf-8 -*-
//
// Author: Daichi Shinozaki
// Date: 11/Mar/2008
//
package
{
import flash.display.BitmapData;
import flash.utils.ByteArray;
import flash.utils.Endian;
import mx.graphics.codec.IImageEncoder;
public class BMPEncoder implements IImageEncoder
{
//--------------------------------------------------------------------------
//
// Class constants
//
//--------------------------------------------------------------------------
/**
* @private
* The MIME type for a BMP image.
*/
private static const CONTENT_TYPE:String = "image/bmp";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
public function BMPEncoder(){
super();
}
/**
* The MIME type for the BMP encoded image.
* The value is "image/bmp"
.
*/
public function get contentType():String
{
return CONTENT_TYPE;
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* Converts the pixels of a BitmapData object
* to a BMP-encoded ByteArray object.
*
* @param bitmapData The input BitmapData object.
*
* @returns A ByteArray object containing BMP-encoded image data.
*/
public function encode(bitmapData:BitmapData):ByteArray
{
return internalEncode(bitmapData, bitmapData.width, bitmapData.height,
bitmapData.transparent);
}
/**
* Converts a ByteArray object containing raw pixels
* in 32-bit ARGB (Alpha, Red, Green, Blue) format
* to a new BMP-encoded ByteArray object.
* The original ByteArray is left unchanged.
*
* @param byteArray The input ByteArray object containing raw pixels.
* This ByteArray should contain
* 4 * width * height
bytes.
* Each pixel is represented by 4 bytes, in the order ARGB.
* The first four bytes represent the top-left pixel of the image.
* The next four bytes represent the pixel to its right, etc.
* Each row follows the previous one without any padding.
*
* @param width The width of the input image, in pixels.
*
* @param height The height of the input image, in pixels.
*
* @param transparent If false
, alpha channel information
* is ignored but you still must represent each pixel
* as four bytes in ARGB format.
*
* @returns A ByteArray object containing BMP-encoded image data.
*/
public function encodeByteArray(byteArray:ByteArray, width:int, height:int,
transparent:Boolean = true):ByteArray
{
return internalEncode(byteArray, width, height, transparent);
}
/**
* @private
*/
private function internalEncode(source:Object, width:int, height:int,
transparent:Boolean = true):ByteArray
{
// The source is either a BitmapData or a ByteArray.
var sourceBitmapData:BitmapData = source as BitmapData;
var sourceByteArray:ByteArray = source as ByteArray;
if (sourceByteArray)
sourceByteArray.position = 0;
// Create output byte array
var bmp:ByteArray = new ByteArray();
bmp.endian = Endian.LITTLE_ENDIAN;
var size:uint = width * height * 4;
/*
typedef struct tagBITMAPFILEHEADER {
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} BITMAPFILEHEADER
*/
// Write BMP signature
bmp.writeShort(0x4D42);
// Write size
bmp.writeUnsignedInt(size + 54);
bmp.writeUnsignedInt(0); // reserved 1, 2
bmp.writeUnsignedInt(54); // offbits
/*
typedef struct tagBITMAPINFOHEADER{
unsigned long biSize;
long biWidth;
long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;
unsigned long biClrImporant;
} BITMAPINFOHEADER;
*/
bmp.writeUnsignedInt(40);
bmp.writeInt(width);
bmp.writeInt(-height);
bmp.writeShort(1); // planes
bmp.writeShort(32);// bit count
bmp.writeUnsignedInt(0); // compression(0 -> no compression)
bmp.writeUnsignedInt(size); //
bmp.writeInt(0); // x pixels per meter
bmp.writeInt(0); // y pixels per meter
bmp.writeUnsignedInt(0); // color used
bmp.writeUnsignedInt(0); // color important
var pixel:uint
var x:uint, y:uint;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if (sourceBitmapData) {
pixel = sourceBitmapData.getPixel32(x, y);
} else {
pixel = sourceByteArray.readUnsignedInt();
}
bmp.writeUnsignedInt(pixel);
}
}
return bmp;
}
}
}