// -*- 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; } } }