/* PNGEnc48.as Lee Felarca http://www.zeropointnine.com/blog 2-2009 A modified version of Tinic Uro's PNGEnc class which saves 48-bit PNG's (16 bits per channel). (http://www.kaourantin.net/2005/10/png-encoder-in-as3.html) This class could be used in tandem with com.leelib.ImageCompositor */ package com.leelib { import flash.utils.ByteArray; public class PNGEnc48 { /** * @param $imageData An array of Numbers ranging from 0 to 1, * arranged in the following format: * [nR, nB, nG, nR, nB, nG ...] */ public static function encode($imageData:Array, $width:int, $height:int):ByteArray { // Create output byte array var png:ByteArray = new ByteArray(); // Write PNG signature png.writeUnsignedInt(0x89504e47); png.writeUnsignedInt(0x0D0A1A0A); // Build IHDR chunk var IHDR:ByteArray = new ByteArray(); IHDR.writeInt($width); IHDR.writeInt($height); IHDR.writeUnsignedInt(0x10020000); // 16 bits per channel, TrueColor/no alpha IHDR.writeByte(0); writeChunk(png,0x49484452,IHDR); // Build IDAT chunk var IDAT:ByteArray= new ByteArray(); writeSub($imageData, $width, $height, IDAT); IDAT.compress(); writeChunk(png,0x49444154,IDAT); // Build IEND chunk writeChunk(png,0x49454E44,null); // return PNG return png; } private static function writeSub($imageData:Array, $width:int, $height:int, IDAT:ByteArray):void { var r:uint; var g:uint; var b:uint; var col:uint; var counter:uint; var numR:Number, numG:Number, numB:Number; for(var y:int=0; y < $height; y++) { // no filter IDAT.writeByte(0); for(var x:int=0; x < $width; x++) { numR = $imageData[counter++]; numG = $imageData[counter++]; numB = $imageData[counter++]; r = int(numR * 65536); g = int(numG * 65536); b = int(numB * 65536); IDAT.writeShort(r); IDAT.writeShort(g); IDAT.writeShort(b); } } } private static var crcTable:Array; private static var crcTableComputed:Boolean = false; private static function writeChunk(png:ByteArray, type:uint, data:ByteArray) { if (!crcTableComputed) { crcTableComputed = true; crcTable = []; for (var n:uint = 0; n < 256; n++) { var c:uint = n; for (var k:uint = 0; k < 8; k++) { if (c & 1) { c = uint(uint(0xedb88320) ^ uint(c >>> 1)); } else { c = uint(c >>> 1); } } crcTable[n] = c; } } var len:uint = 0; if (data != null) { len = data.length; } png.writeUnsignedInt(len); var p:uint = png.position; png.writeUnsignedInt(type); if ( data != null ) { png.writeBytes(data); } var e:uint = png.position; png.position = p; var c:uint = 0xffffffff; for (var i:int = 0; i < (e-p); i++) { c = uint(crcTable[ (c ^ png.readUnsignedByte()) & 0xff] ^ (c >>> 8)); } c = uint(c^uint(0xffffffff)); png.position = e; png.writeUnsignedInt(c); } } }