- 积分
- 4259
- 注册时间
- 2015-1-11
- 最后登录
- 2016-8-19
- 在线时间
- 1 小时
- 威望
- 0
- 贡献
- 16
- 金币
- 117
- 钢镚
- 10
- 交易凭证
- 0
- 分享
- 0
- 精华
- 0
- 帖子
- 4
- 主题
- 1
TA的每日心情 | 慵懒 2016-8-19 16:03 |
|---|
签到天数: 3 天 [LV.2]偶尔看看I
中尉
  
- 威望
- 0
- 贡献
- 16
- 金币
- 117
- 钢镚
- 10
|
- package cn.window.image.png
- {
- import flash.display.BitmapData;
- import flash.utils.ByteArray;
- public class PNGEncoder
- {
- /**CRC验证器*/
- private var crcTable:Array;
- /**
- *PNG文件格式分为PNG-24和PNG-8,
- * 其最大的区别是PNG-24是用24位来保存一个像素值,是真彩色,
- * 而PNG-8是用8位索引值来在调色盘 中索引一个颜色,
- * 因为一个索引值的最大上限为2的8次方既128,故调色盘中颜色数最多为128种,
- * 所以该文件格式又被叫做PNG-8 128仿色。PNG-24因为其图片容量过大,
- * 而且在Nokia和Moto等某些机型上创建图片失败和显示不正确等异常时有发生,
- * 有时还会严重拖慢显示速度,故并不常 用,
- * CoCoMo认为这些异常和平台底层的图像解压不无关系。
- * 不过该格式最大的优点是可以保存Alpha通道,
- * 同事也曾有过利用该图片格式实现Alpha 混合的先例,
- * 想来随着技术的发展,手机硬件平台的提升,Alpha混合一定会被广泛的应用,
- * 到那时该格式的最大优势才会真正发挥。
- *
- */
- public function PNGEncoder()
- {
- initializeCRCTable();
- }
- /**
- *将 BitmapData 对象的像素转换为 PNG 编码的 ByteArray 对象。
- * @param bitmapData BitmapData 输入对象。
- * @return 返回包含以 PNG 格式编码的图像数据的 ByteArray 对象。
- */
- public function encode(bitmapData:BitmapData):ByteArray
- {
- return internalEncode(bitmapData, bitmapData.width, bitmapData.height,
- bitmapData.transparent);
- }
- /**
- *将包含 32 位 ARGB(Alpha、红、绿、蓝)格式原始像素的 ByteArray 对象
- * 转换为新的 PNG 编码的 ByteArray 对象。
- * 原始的 ByteArray 将保持不变。
- * @param byteArray 包含原始像素的 ByteArray 输入对象。<br>
- * 此 ByteArray 应包含 4 width height 字节。<br>
- * 每个像素都由 4 个字节表示,顺序依次为 ARGB。<br>
- * 前四个字节表示图像左上角的像素。<br>
- * 接下来的四个字节表示其右侧的像素,依此类推。每一行与前一行之间没有任何填充。
- * @param width 输入图像的宽度(以像素为单位)。
- * @param height 输入图像的高度(以像素为单位)。
- * @param transparent 如果为 false,则将忽略 Alpha 通道信息,但是您仍必须使用 ARGB 格式以四个字节表示每个像素。
- * @return 返回包含以 PNG 格式编码的图像数据的 ByteArray 对象。
- *
- */
- public function encodeByteArray(byteArray:ByteArray, width:int, height:int,
- transparent:Boolean = true):ByteArray
- {
- return internalEncode(byteArray, width, height, transparent);
- }
- /**
- *初始化CRC验证器
- * <p>
- * CRC(cyclic redundancy check)域中的值是对Chunk Type Code域和Chunk Data域中的数据进行计算得到的。<br>
- * CRC具体算法定义在ISO 3309和ITU-T V.42中,其值按下面的CRC码生成多项式进行计算:<br>
- * x<sup>32</sup>+x<sup>26</sup>+x<sup>23</sup>+x<sup>22</sup>+x<sup>16</sup>+x<sup>12</sup>+x
- *<sup>11</sup>+x<sup>10</sup>+x<sup>8</sup>+x<sup>7</sup>+x<sup>5</sup>+x<sup>4</sup>+x<sup>2</sup>+x+1
- * <p>
- */
- private function initializeCRCTable():void
- {
- 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;
- }
- }
- /**
- * 进行编码, source可以为BitmapData 或 a ByteArray.<br>
- *
- * <b>PNG签名</b><br>
- * 89 50 4e 47 0d 0a 1a 0a<br>
- * 其中第一个字节0x89超出了ASCII字符的范围,这是为了避免某些软件将PNG文件当做文本文件来处理<br>
- * 0x50 0x4e 0x47 为 PNG 的Unicode编码<br>
- * 0d 0a 1a 0a 这4个就不知道了<br>
- *
- * <b>PNG数据块(Chunk):</b><br>
- *<table align="center" bgcolor="#eeeeee" border="0">
- *<tr><td colspan="5"><div align="center"><strong>PNG文件格式中的数据块</strong></div></td></tr>
- *<tr><td><div align="center"><b>数据块符号</b></div></td><td><div align="center"><b>数据块名称</b></div></td>
- *<td><div align="center"><b>多数据块</b></div></td><td><div align="center"><b>可选否</b></div></td>
- *<td><div align="center"><b>位置限制</b></div></td></tr>
- *<tr><td>IHDR</td><td>文件头数据块</td><td>否</td><td>否</td><td>第一块</td></tr>
- *<tr><td>cHRM</td><td>基色和白色点数据块</td><td>否</td><td>是</td><td>在PLTE和IDAT之前</td></tr>
- *<tr><td>gAMA</td><td>图像γ数据块</td><td>否</td><td>是</td><td>在PLTE和IDAT之前</td></tr>
- *<tr><td>sBIT</td><td>样本有效位数据块</td><td>否</td><td>是</td><td>在PLTE和IDAT之前</td></tr>
- *<tr><td>PLTE</td><td>调色板数据块</td><td>否</td><td>是</td><td>在IDAT之前</td></tr>
- *<tr><td>bKGD</td><td>背景颜色数据块</td><td>否</td><td>是</td><td>在PLTE之后IDAT之前</td></tr>
- *<tr><td>hIST</td><td>图像直方图数据块</td><td>否</td><td>是</td><td>在PLTE之后IDAT之前</td></tr>
- *<tr><td>tRNS</td><td>图像透明数据块</td><td>否</td><td>是</td><td>在PLTE之后IDAT之前</td></tr>
- *<tr><td>oFFs</td><td>(专用公共数据块)</td><td>否</td><td>是</td><td>在IDAT之前</td></tr>
- *<tr><td>pHYs</td><td>物理像素尺寸数据块</td><td>否</td><td>是</td><td>在IDAT之前</td></tr>
- *<tr><td>sCAL</td><td>(专用公共数据块)</td><td>否</td><td>是</td><td>在IDAT之前</td></tr>
- *<tr><td>IDAT</td><td>图像数据块</td><td>是</td><td>否</td><td>与其他IDAT连续</td></tr>
- *<tr><td>tIME</td><td>图像最后修改时间数据块</td><td>否</td><td>是</td><td>无限制</td></tr>
- *<tr><td>tEXt</td><td>文本信息数据块</td><td>是</td><td>是</td><td>无限制</td></tr>
- *<tr><td>zTXt</td><td>压缩文本数据块</td><td>是</td><td>是</td><td>无限制</td></tr>
- *<tr><td>fRAc</td><td>(专用公共数据块)</td><td>是</td><td>是</td><td>无限制</td></tr>
- *<tr><td>gIFg</td><td>(专用公共数据块)</td><td>是</td><td>是</td><td>无限制</td></tr>
- *<tr><td>gIFt</td><td>(专用公共数据块)</td><td>是</td><td>是</td><td class="text">无限制</td></tr>
- *<tr><td>gIFx</td><td>(专用公共数据块)</td><td>是</td><td>是</td><td>无限制</td></tr>
- *<tr><td>IEND</td><td>图像结束数据</td><td>否</td><td>否</td><td>最后一个数据块</td></tr>
- *</table><br>
- *
- * <b>数据块结构</b><br>
- *<table align="center" bgcolor="#eeeeee" border="0">
- *<tr><td><b>名称</b></td><td><b>字节数</b></td><td><b>说明</b></td></tr>
- *<tr><td>Length (长度)</td><td>4字节</td><td>指定数据块中数据域的长度,其长度不超过(2<sup>31</sup>-1)字节</td></tr>
- *<tr><td>Chunk Type Code (数据块类型码)</td><td>4字节</td><td>数据块类型码由ASCII字母(A-Z和a-z)组成</td></tr>
- *<tr><td>Chunk Data (数据块数据)</td><td>可变长度</td><td>存储按照Chunk Type Code指定的数据</td></tr>
- *<tr><td>CRC (循环冗余检测)</td><td>4字节</td><td>存储用来检测是否有错误的循环冗余码</td></tr>
- *</table><br>
- *
- * <b>IHDR 数据结构:</b><br>
- * <table align="center" bgcolor="#eeeeee" border="0">
- *<tr> <td><div align="center"><b>域的名称</b></div></td> <td><div align="center"><b>字节数</b></div></td>
- *<td><div align="center"><b>说明</b></div></td> </tr>
- *<tr><td>Width</td> <td>4 bytes</td> <td>图像宽度,以像素为单位</td> </tr>
- *<tr> <td>Height</td> <td>4 bytes</td> <td>图像高度,以像素为单位</td> </tr>
- *<tr> <td>Bit depth</td> <td>1 byte</td> <td>图像深度: <br />索引彩色图像:1,2,4或8 <br/>
- *灰度图像:1,2,4,8或16 <br/>真彩色图像:8或16</td> </tr>
- *<tr> <td>ColorType</td> <td>1 byte</td> <td>颜色类型:<br/>0:灰度图像, 1,2,4,8或16 <br/>
- *2:真彩色图像,8或16 <br/>3:索引彩色图像,1,2,4或8 <br/>
- *4:带α通道数据的灰度图像,8或16 <br/>6:带α通道数据的真彩色图像,8或16</td> </tr>
- *<tr> <td>Compression method</td> <td>1 byte</td> <td>压缩方法(LZ77派生算法)</td> </tr>
- *<tr> <td>Filter method</td> <td>1 byte</td> <td>滤波器方法</td> </tr>
- *<tr> <td>Interlace method</td> <td>1 byte</td> <td>隔行扫描方法:<br/>0:非隔行扫描 <br/>
- *1: Adam7(由Adam M. Costello开发的7遍隔行扫描方法)</td> </tr>
- *</table><br>
- */
- 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;
- // 创建二进制输出流
- var png:ByteArray = new ByteArray();
- // 写入PNG签名(PNG文件的标志)89 50 4e 47 0d 0a 1a 0a
- png.writeUnsignedInt(0x89504E47);
- png.writeUnsignedInt(0x0D0A1A0A);
- // 创建 IHDR(文件头数据块) 它包含有PNG文件中存储的图像数据的基本信息,
- //并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。
- //文件头数据块由13字节组成,结构见注释
- var IHDR:ByteArray = new ByteArray();
- IHDR.writeInt(width); // 宽度
- IHDR.writeInt(height);//高度
- IHDR.writeByte(8); // bit depth per channel(图像深度)
- IHDR.writeByte(6); // color type: RGBA(颜色类型)
- IHDR.writeByte(0); // compression method(压缩方法 --- LZ77派生算法)
- IHDR.writeByte(0); // filter method(滤波器方法)
- IHDR.writeByte(0); // interlace method (隔行扫描方法)
- writeChunk(png, 0x49484452, IHDR);
- // 构建 IDAT chunk(图像数据块)
- var IDAT:ByteArray = new ByteArray();
- for (var y:int = 0; y < height; y++)
- {
- IDAT.writeByte(0); // no filter
- var x:int;
- var pixel:uint;
- if (!transparent)
- {
- for (x = 0; x < width; x++)
- {
- if (sourceBitmapData)
- pixel = sourceBitmapData.getPixel(x, y);
- else
- pixel = sourceByteArray.readUnsignedInt();
- IDAT.writeUnsignedInt(uint(((pixel & 0xFFFFFF) << 8) | 0xFF));
- }
- }
- else
- {
- for (x = 0; x < width; x++)
- {
- if (sourceBitmapData)
- pixel = sourceBitmapData.getPixel32(x, y);
- else
- pixel = sourceByteArray.readUnsignedInt();
- IDAT.writeUnsignedInt(uint(((pixel & 0xFFFFFF) << 8) |
- (pixel >>> 24)));
- }
- }
- }
- IDAT.compress();
- writeChunk(png, 0x49444154, IDAT);
- // 构建 IEND (图像结束数据)
- writeChunk(png, 0x49454E44, null);
- // return PNG
- png.position = 0;
- return png;
- }
- /**
- * @private
- */
- private function writeChunk(png:ByteArray, type:uint, data:ByteArray):void
- {
- // Write length of data.
- var len:uint = 0;
- if (data)
- len = data.length;
- png.writeUnsignedInt(len);
- // Write chunk type.
- var typePos:uint = png.position;
- png.writeUnsignedInt(type);
- // Write data.
- if (data)
- png.writeBytes(data);
- // Write CRC of chunk type and data.
- var crcPos:uint = png.position;
- png.position = typePos;
- var crc:uint = 0xFFFFFFFF;
- for (var i:uint = typePos; i < crcPos; i++)
- {
- crc = uint(crcTable[(crc ^ png.readUnsignedByte()) & uint(0xFF)] ^
- uint(crc >>> 8));
- }
- crc = uint(crc ^ uint(0xFFFFFFFF));
- png.position = crcPos;
- png.writeUnsignedInt(crc);
- }
- }
- }
复制代码
|
评分
-
查看全部评分
|