src/jp/shichiseki/exif/IFDEntry.as
package jp.shichiseki.exif {
import flash.utils.ByteArray;
/**
* The IFDEntry class is an entry in an IFD. The IFDEntry class contains type, name, id
* and data of the entry.
*/
public class IFDEntry {
private static const TAG_TYPES:Object = {
1: {name:"BYTE", size:1, reader: readByteHandler},
2: {name:"ASCII", size:1, reader: readStringHandler},
3: {name:"SHORT", size:2, reader: readShortHandler},
4: {name:"LONG", size:4, reader: readLongHandler},
5: {name:"RATIONAL", size:8, reader: readRationalHandler},
7: {name:"UNDEFINED", size:1, reader: readByteHandler},
9: {name:"SLONG", size:4, reader: readSLongHandler},
10: {name:"SRATIONAL", size:8, reader: readSRationalHandler}
};
private var _tagID:uint;
/**
* Indicates the tagID of this entry.
*/
public function get tagID():uint { return _tagID; }
private var _tag:XMLList;
/**
*Indicates the tag of this entry.
*/
public function get tag():XMLList { return _tag; }
private var _tagName:String;
/**
* Indicates the tag name of this entry.
*/
public function get tagName():String { return tag.@field_name.toString() || _tagName }
private var _typeID:uint;
/**
* Indicates the type ID of this entry.
*/
public function get typeID():uint { return _typeID; }
private var _type:Object;
/**
* Indicates the type of this entry.
*/
public function get type():Object { return _type; }
private var _data:Object;
/**
* Indicates the data of this entry.
*/
public function get data():Object { return _data; }
private var _numData:uint;
/**
* Constructor.
*/
public function IFDEntry(stream:ByteArray, tagSet:XML, offset:uint) {
var nextPosition:uint;
_tagID = stream.readUnsignedShort();
_tag = tagSet.tag.(parseInt(@id, 16) == tagID);
_tagName = "0x" + _tagID.toString(16);
if (!tag.@field_name.toString())
_tagName = "UnknownTag_" + _tagName;
_typeID = stream.readUnsignedShort();
_type = TAG_TYPES[_typeID];
_numData = stream.readUnsignedInt();
nextPosition = stream.position + 4;
if (!type) {
trace("unrecognizable tag id=" + tagID + " type=" + typeID);
_data = null;
} else {
if (_numData * type.size > 4)
stream.position = stream.readUnsignedInt() + offset;
readContent(stream);
}
stream.position = nextPosition;
}
private function readContent(stream:ByteArray):void {
if (_typeID == 2) {
_data = readStringHandler(stream, _numData);
} else if (_numData == 1) {
_data = type.reader(stream);
} else {
_data = new Array();
for (var i:uint = 0; i < _numData; i++) {
_data.push(type.reader(stream));
}
}
}
private static function readStringHandler(stream:ByteArray, length:uint):String {
return stream.readUTFBytes(length);
}
private static function readByteHandler(stream:ByteArray):uint {
return stream.readUnsignedByte();
}
private static function readShortHandler(stream:ByteArray):uint {
return stream.readUnsignedShort();
}
private static function readLongHandler(stream:ByteArray):uint {
return stream.readUnsignedInt();
}
private static function readSLongHandler(stream:ByteArray):int {
return stream.readInt();
}
private static function readRationalHandler(stream:ByteArray):Number {
var denominator:uint = stream.readUnsignedInt();
var numerator:uint = stream.readUnsignedInt();
return Number(denominator) / Number(numerator);
}
private static function readSRationalHandler(stream:ByteArray):Number {
var denominator:int = stream.readInt();
var numerator:int = stream.readInt();
return Number(denominator) / Number(numerator);
}
}
}