Png images with a custom data

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

There are many applications, images and data are used together! The common practice is to add the XML file, such as tables to describe!

In fact, can directly write the data in the picture!

Approach is very simple! I wrote the code, we can refer to the next!

https://hub004.xindong.com/yangyiqiang/AvatarTool/blob/master/src/utils/As3PngEncoder.as

The principle is that the PNG data type in IEND to replace the data you need!

The library is put PNG and XML together! To be clear, if use tools compression word pictures, data may be lost! To put the pictures well pressure, their data put in.!

The above is writing method!

Read as follows:

package utils {
	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;


	/**
	 * @author yangyiqiang
	 */


	/*******************************
	PNGDecoder
	Author: Jerion
	
	A class that decodes png byte arrays and generates a bitmapdata.
	This is my first attempt at decoding images, so there are a lot of
	things that are not implemented.
	
	So far, it can only decode truecolour with alpha png images with
	no interlacing, no filter, and bit depth of 8.
	 ********************************/
	public class PNGDecoder {
		private const IHDR : uint = 0x49484452;
		private const PLTE : uint = 0x504c5445;
		private const IDAT : uint = 0x49444154;
		private const IEND : uint = 0x49454e44;
		private var imgWidth : uint = 0;
		private var imgHeight : uint = 0;
		// file info, but not used yet.
		private var bitDepth : uint = 0;
		private var colourType : uint = 0;
		private var compressionMethod : uint = 0;
		private var filterMethod : uint = 0;
		private var interlaceMethod : uint = 0;
		private var chunks : Array;
		private var input : ByteArray;
		private var output : ByteArray;


		public function PNGDecoder(ba : ByteArray = null) {
			chunks = new Array();
			input = new ByteArray();
			output = new ByteArray();


			input = ba;
			if(input)
			{
				input.position = 0;
				if (!readSignature()) throw new Error("wrong signature");
			}
		}


		public function getIendMessage(ba : ByteArray) :Object {
			chunks = new Array();
			input = new ByteArray();
			output = new ByteArray();


			input = ba;


			input.position = 0;


			if (!readSignature()) throw new Error("wrong signature");


			getIENDChunks();
			if (_IENDChunks) {
				input.position = _IENDChunks.position;
				var len : uint = _IENDChunks.length;
				var bytes:ByteArray=new ByteArray();
				bytes.writeBytes(input,input.position,len);
				bytes.position=0;
				return bytes.readObject();
			}
			return null;
		}


		// recieves the bytearray and returns a bitmapdata
		public function decode(ba : ByteArray) : BitmapData {
			chunks = new Array();
			input = new ByteArray();
			output = new ByteArray();


			input = ba;


			input.position = 0;


			if (!readSignature()) throw new Error("wrong signature");


			getChunks();


			for (var i : int = 0; i <chunks.length; ++i) {
				switch(chunks[i].type) {
					case IHDR:
						processIHDR(i);
						break;
					// case PLTE: processPLTE(i); break;
					case IDAT:
						processIDAT(i);
						break;
					// case IEND: processIEND(i); break;
				}
			}


			// Since the image is inverted in x and y, I have to flip it using a Matrix object. There should be a better solution for this..
			var bd0 : BitmapData = new BitmapData(imgWidth, imgHeight);
			var bd1 : BitmapData = new BitmapData(imgWidth, imgHeight, true, 0xffffff);


			if (output.length > 0 && (imgWidth * imgHeight * 4) == output.length) {
				output.position = 0;
				bd0.setPixels(new Rectangle(0, 0, imgWidth, imgHeight), output);


				var mat : Matrix = new Matrix();
				mat.scale(-1, -1);
				mat.translate(imgWidth, imgHeight);


				bd1.draw(bd0, mat);
			}


			return bd1;
		}


		// read the header of the image
		private function processIHDR(index : uint) : void {
			input.position = chunks[index].position;


			imgWidth = input.readUnsignedInt();
			imgHeight = input.readUnsignedInt();


			// file info, but is not used yet
			bitDepth = input.readUnsignedByte();
			colourType = input.readUnsignedByte();
			compressionMethod = input.readUnsignedByte();
			filterMethod = input.readUnsignedByte();
			interlaceMethod = input.readUnsignedByte();
		}


		// This can't handle multiple IDATs yet, and it can only decode filter 0 scanlines.
		private function processIDAT(index : uint) : void {
			var tmp : ByteArray = new ByteArray();


			var pixw : uint = imgWidth * 4;


			tmp.writeBytes(input, chunks[index].position, chunks[index].length);
			tmp.uncompress();


			for (var i : int = tmp.length - 1; i > 0; --i) {
				if (i % (pixw + 1) != 0) {
					var a : uint = tmp[i];
					var b : uint = tmp[i - 1];
					var g : uint = tmp[i - 2];
					var r : uint = tmp[i - 3];


					output.writeByte(a);
					output.writeByte(r);
					output.writeByte(g);
					output.writeByte(b);


					i -= 3;
				}
			}
		}


		private function getChunks() : void {
			var pos : uint = 0;
			var len : uint = 0;
			var type : uint = 0;


			var loopEnd : int = input.length;


			while (input.position <loopEnd) {
				len = input.readUnsignedInt();
				type = input.readUnsignedInt();
				pos = input.position;


				input.position += len;
				input.position += 4;
				// crc block. It is ignored right now, but if you want to retrieve it, replace this line with "input.readUnsignedInt()"
				chunks.push({position:pos, length:len, type:type});
			}
		}


		private var _IENDChunks : Object;
		private var _pos : uint = 0;
		private var _len : uint = 0;
		private var _type : uint = 0;


		public function getIENDChunks() : Object {
			_pos = 0;
			_len = 0;
			_type = 0;


			var loopEnd : int = input.length;


			while (input.position <loopEnd) {
				_len = input.readUnsignedInt();
				_type = input.readUnsignedInt();
				if (_type == IEND) {
					_pos = input.position;
					_IENDChunks = {position:_pos, length:_len, type:_type};
					return _IENDChunks;
				} else {
					input.position += _len;
					input.position += 4;
				}
			}
			return _IENDChunks;
		}


		private function readSignature() : Boolean {
			return (input.readUnsignedInt() == 0x89504e47 && input.readUnsignedInt() == 0x0D0A1A0A);
		}


		// transform the chunk type to a string representation
		private function fixType(num : uint) : String {
			var ret : String = "";
			var str : String = num.toString(16);


			while (str.length <8) str = "0" + str;


			ret += String.fromCharCode(parseInt(str.substr(0, 2), 16));
			ret += String.fromCharCode(parseInt(str.substr(2, 2), 16));
			ret += String.fromCharCode(parseInt(str.substr(4, 2), 16));
			ret += String.fromCharCode(parseInt(str.substr(6, 2), 16));


			return ret;
		}
	}
}

Because I am here is that the data of direct writeObject! It provides only a
public function getIendMessage(ba : ByteArray) :Object
Own use, can change you want! Personally think that is a good use of writeObject! The analytical data efficiency will be high

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Dean at December 12, 2013 - 5:42 AM