MPO Viewer
/**
* Copyright Saqoosha ( http://wonderfl.net/user/Saqoosha )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jqZez
*/
package {
import com.bit101.components.HBox;
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import com.bit101.components.RadioButton;
import com.bit101.components.VBox;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.net.FileFilter;
import flash.net.FileReference;
[SWF(backgroundColor="0xffffff", frameRate="30", width="465", height="465")]
public class MPOViewer extends Sprite {
public var _parallelMode:RadioButton;
public var _crossMode:RadioButton;
private var _file:FileReference;
private var _parser:MPOParser;
private var _container:Sprite;
private var _width:Number;
public function MPOViewer() {
stage.quality = StageQuality.BEST;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.addEventListener(Event.RESIZE, _onStageResize);
// new MinimalConfigurator(this).parseXML(<comps>
// <VBox x="10" y="10">
// <PushButton label="LOAD MPO" event="click:_onClickLoad"/>
// <HBox>
// <Label text="MODE:" />
// <RadioButton id="_parallelMode" y="4" label="PARALLEL" groupName="mode" selected="true" event="click:_onChangeMode" />
// <RadioButton id="_crossMode" y="4" label="CROSS" groupName="mode" event="click:_onChangeMode" />
// </HBox>
// </VBox>
// </comps>);
var vbox:VBox = new VBox(this, 10, 10);
new PushButton(vbox, 0, 0, 'LOAD MPO', _onClickLoad);
var hbox:HBox = new HBox(vbox);
new Label(hbox, 0, 0, 'MODE:');
_parallelMode = new RadioButton(hbox, 0, 4, 'PARALLEL', true, _onChangeMode);
_crossMode = new RadioButton(hbox, 0, 4, 'CROSS', false, _onChangeMode);
_parallelMode.groupName = _crossMode.groupName = 'mode';
}
public function _onClickLoad(e:Event):void {
_file = new FileReference();
_file.addEventListener(Event.SELECT, _onFileSelect);
_file.browse([new FileFilter('MPO', '*.mpo')]);
}
private function _onFileSelect(event:Event):void {
if (_container) {
removeChild(_container);
}
_file.addEventListener(Event.COMPLETE, _onDataLoaded);
_file.load();
}
private function _onDataLoaded(event:Event):void {
_parser = new MPOParser(_file.data);
_parser.addEventListener(Event.COMPLETE, _onImageLoaded);
}
private function _onImageLoaded(event:Event):void {
_container = addChild(new Sprite()) as Sprite;
for (var i:int = 0; i < 2; i++) {
var b:Bitmap = _container.addChild(new Bitmap(_parser.images[i])) as Bitmap;
b.smoothing = true;
b.x = i * b.width;
}
_width = _container.width;
_onChangeMode(null);
_onStageResize(null);
}
public function _onChangeMode(e:Event):void {
if (!_container) return;
if (_parallelMode.selected) {
_container.getChildAt(0).x = 0;
_container.getChildAt(1).x = _width / 2;
} else {
_container.getChildAt(0).x = _width / 2;
_container.getChildAt(1).x = 0;
}
}
private function _onStageResize(e:Event):void {
if (!_container) return;
_container.scaleX = _container.scaleY = stage.stageWidth / _width;
_container.y = (stage.stageHeight - _container.height) / 2;
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.utils.ByteArray;
import flash.utils.Endian;
class MPOParser extends EventDispatcher {
private var _index:MPIndex;
private var _images:Vector.<BitmapData>;
private var _loaded:int;
public function MPOParser(data:ByteArray) {
var pos:int;
var tag:int, length:int;
while (!_index && data.position < data.length) {
pos = data.position;
tag = data.readUnsignedShort();
if (tag == 0xFFD8 || tag == 0xFFD9) {
length = 0;
} else {
length = data.readUnsignedShort();
}
switch (tag) {
case 0xFFE2:
_index = _parseAPP2(data, length);
break;
}
if (length > 0) data.position += length - 4;
}
var n:int = _index.mpEntry.length;
_images = new Vector.<BitmapData>(n);
_loaded = 0;
for (var i:int = 0; i < n; i++) {
var entry:MPEntry = _index.mpEntry[i];
var jpeg:ByteArray = new ByteArray();
data.position = entry.offset;
data.readBytes(jpeg, 0, entry.size);
_loadImage(jpeg, i);
}
}
private function _loadImage(data:ByteArray, i:int):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (e:Event):void {
_images[i] = Bitmap(loader.content).bitmapData;
if (++_loaded == _images.length) {
dispatchEvent(new Event(Event.COMPLETE));
}
});
loader.loadBytes(data);
}
private function _parseAPP2(data:ByteArray, length:int):MPIndex {
var id:uint = data.readUnsignedInt();
var zero:int = data.position;
var endian:uint = data.readUnsignedInt();
if (endian == 0x49492a00) data.endian = Endian.LITTLE_ENDIAN;
var firstIFDOffset:uint = data.readUnsignedInt();
data.position = zero + firstIFDOffset;
var index:MPIndex = new MPIndex(data);
for each (var entry:MPEntry in index.mpEntry) {
if (entry.offset > 0) entry.offset += zero;
}
data.endian = Endian.BIG_ENDIAN;
return index;
}
public function get images():Vector.<BitmapData> { return _images; }
public function get numImages():int { return _index.numberOfImages; }
}
class MPIndex {
public var count:int;
public var version:String;
public var numberOfImages:uint;
public var offsetToNextIFD:uint;
public var mpEntry:Vector.<MPEntry>;
public function MPIndex(data:ByteArray) {
count = data.readUnsignedShort();
for (var i:int = 0; i < count; i++) {
var tag:int = data.readUnsignedShort();
var type:int = data.readUnsignedShort();
var cnt:int = data.readUnsignedInt();
switch (tag) {
case 0xB000: // MPF Version
version = data.readUTFBytes(4);
break;
case 0xB001: // Number of Images
numberOfImages = data.readUnsignedInt();
break;
case 0xB002: // MP Entry
data.readUnsignedInt();
break;
}
}
offsetToNextIFD = data.readUnsignedInt();
mpEntry = new Vector.<MPEntry>();
for (i = 0; i < numberOfImages; i++) {
mpEntry.push(new MPEntry(data));
}
}
}
class MPEntry {
public var spec:uint;
public var size:uint;
public var offset:uint;
public var slave1EntryNo:uint;
public var slave2EntryNo:uint;
public function MPEntry(data:ByteArray) {
spec = data.readUnsignedInt();
size = data.readUnsignedInt();
offset = data.readUnsignedInt();
slave1EntryNo = data.readUnsignedShort();
slave2EntryNo = data.readUnsignedShort();
}
}