blob: 8aaa1efe3c974f1857f92f321b4bafa50ba21245 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
/**
* writes bitmaps into PNG format.
* original author, Ely
*/
package {
import flash.display.*;
import flash.geom.*;
import flash.utils.*;
import flash.net.*;
public class MustellaPNGEncoder {
private var _png:ByteArray;
// empty constructor
public function MustellaPNGEncoder () {
}
public function encode(img:BitmapData):ByteArray
{
var imgWidth:uint = img.width;
var imgHeight:uint = img.height;
var imgData:ByteArray = img.getPixels(new Rectangle(0,0,imgWidth,imgHeight));
_png = new ByteArray();
_png.writeByte(137);
_png.writeByte(80);
_png.writeByte(78);
_png.writeByte(71);
_png.writeByte(13);
_png.writeByte(10);
_png.writeByte(26);
_png.writeByte(10);
var IHDR:ByteArray = new ByteArray();
IHDR.writeInt(imgWidth);
IHDR.writeInt(imgHeight);
IHDR.writeByte(8); // color depth: 8 bpp
IHDR.writeByte(6); // color type: RGBA
IHDR.writeByte(0); // compression: ZLIB
IHDR.writeByte(0); // filter method
IHDR.writeByte(0); // not interlaced;
writeChunk([0x49,0x48,0x44,0x52],IHDR);
var IDAT:ByteArray= new ByteArray();
for(var i:uint=0;i<imgHeight;i++) {
IDAT.writeByte(0);
for(var j:uint=0;j<imgWidth;j++) {
var p:uint = img.getPixel32(j,i);
IDAT.writeByte((p>>16)&0xFF);
IDAT.writeByte((p>> 8)&0xFF);
IDAT.writeByte((p )&0xFF);
IDAT.writeByte((p>>24)&0xFF);
}
}
IDAT.compress();
writeChunk([0x49,0x44,0x41,0x54],IDAT);
writeChunk([0x49,0x45,0x4E,0x44],null);
return _png;
}
public function dump():String
{
_png.position = 0;
var out:String ="";
for(var i:uint=0;i<_png.length;i++) {
var code:String = "0123456789abcdef";
var v:uint = _png.readUnsignedByte();
out += code.charAt((v & 0xF0) >> 4);
out += code.charAt(v & 0xF);
out += " ";
}
return out;
}
private function writeChunk(type:Array,data:ByteArray):void
{
var len:uint = 0;
if(data != null)
len = data.length; // data length
_png.writeUnsignedInt(len);
var p:uint = _png.position;
_png.writeByte(type[0]);
_png.writeByte(type[1]);
_png.writeByte(type[2]);
_png.writeByte(type[3]);
if(data != null)
_png.writeBytes(data);
var endP:uint = _png.position;
_png.position = p;
var c:uint = crc(_png,endP-p);
_png.position = endP;
_png.writeUnsignedInt(c);
}
/* Table of CRCs of all 8-bit messages. */
private static var crc_table:Array;
/* Flag: has the table been computed? Initially false. */
private static var crc_table_computed:Boolean = false;
/* Make the table for a fast CRC. */
private function make_crc_table():void
{
var c:uint;
var n:int;
var k:int;
crc_table = [];
for (n = 0; n < 256; n++) {
c = n;
for (k = 0; k < 8; k++) {
if (c & 1)
c = uint(uint(0xedb88320) ^ uint(c >>> 1));
else
c = uint(c >>> 1);
}
crc_table[n] = c;
}
crc_table_computed = true;
}
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
should be initialized to all 1's, and the transmitted value
is the 1's complement of the final running CRC (see the
crc() routine below)). */
private function update_crc(crc:uint, buf:ByteArray,
len:uint):uint
{
var c:uint = crc;
var n:int;
var v:uint;
if (!crc_table_computed)
make_crc_table();
for (n = 0; n < len; n++) {
v = buf.readUnsignedByte();
c = uint(crc_table[(c ^ v) & uint(0xff)] ^ uint(c >>> 8));
}
return c;
}
/* Return the CRC of the bytes buf[0..len-1]. */
private function crc(buf:ByteArray, len:uint):uint
{
var cc:uint = update_crc(uint(0xffffffff), buf, len);
return uint(cc ^ uint(0xffffffff));
}
}
}