Created
June 8, 2011 18:04
-
-
Save claus/1014957 to your computer and use it in GitHub Desktop.
Create SWF with PNGs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package | |
{ | |
// Dependencies: | |
// as3swf.swc | |
// as3commons-bytecode-1.0-RC1.swc | |
// as3commons-lang-0.3.2.swc | |
// as3commons-logging-2.0.swc | |
// as3commons-reflect-1.3.4.swc | |
// MinimalComps_0_9_9.swc | |
import com.bit101.components.List; | |
import com.bit101.components.PushButton; | |
import com.codeazur.as3swf.SWF; | |
import com.codeazur.as3swf.SWFData; | |
import com.codeazur.as3swf.data.SWFSymbol; | |
import com.codeazur.as3swf.data.consts.BitmapType; | |
import com.codeazur.as3swf.tags.TagDefineBitsJPEG2; | |
import com.codeazur.as3swf.tags.TagDoABC; | |
import com.codeazur.as3swf.tags.TagEnd; | |
import com.codeazur.as3swf.tags.TagFileAttributes; | |
import com.codeazur.as3swf.tags.TagShowFrame; | |
import com.codeazur.as3swf.tags.TagSymbolClass; | |
import org.as3commons.bytecode.abc.AbcFile; | |
import org.as3commons.bytecode.abc.enum.Opcode; | |
import org.as3commons.bytecode.emit.IAbcBuilder; | |
import org.as3commons.bytecode.emit.IClassBuilder; | |
import org.as3commons.bytecode.emit.ICtorBuilder; | |
import org.as3commons.bytecode.emit.IPackageBuilder; | |
import org.as3commons.bytecode.emit.impl.AbcBuilder; | |
import org.as3commons.bytecode.io.AbcSerializer; | |
import flash.display.Sprite; | |
import flash.display.StageAlign; | |
import flash.display.StageScaleMode; | |
import flash.events.Event; | |
import flash.net.FileFilter; | |
import flash.net.FileReference; | |
import flash.utils.ByteArray; | |
public class PNGPacker extends Sprite | |
{ | |
private var swf:SWF; | |
private var imgWidth:Number; | |
private var imgHeight:Number; | |
private var abcBuilder:IAbcBuilder; | |
private var packageBuilder:IPackageBuilder; | |
private var symbolClass:TagSymbolClass; | |
private var currentCharacterId:uint; | |
private var list:List; | |
private static const PACKAGENAME:String = "png"; | |
private static const CLASSNAME:String = "BitmapDataClass"; | |
public function PNGPacker() | |
{ | |
stage.align = StageAlign.TOP_LEFT; | |
stage.scaleMode = StageScaleMode.NO_SCALE | |
addChild(new PushButton(this, 10, 10, "Add PNG", function():void { | |
var ref:FileReference = new FileReference(); | |
ref.addEventListener(Event.SELECT, function(e:Event):void { ref.load(); }); | |
ref.addEventListener(Event.COMPLETE, function(e:Event):void { addPNG(ref.data, ref.name); }); | |
ref.browse([new FileFilter("PNG (*.png)", "*.png")]); | |
})); | |
addChild(new PushButton(this, 120, 10, "Save SWF", function():void { | |
var ba:ByteArray = publish(); | |
var ref:FileReference = new FileReference(); | |
ref.save(ba, 'Untitled.swf'); | |
init(); | |
})); | |
addChild(new PushButton(this, 230, 10, "Clear SWF", function():void { | |
init(); | |
})); | |
list = new List(this, 10, 50); | |
list.enabled = false; | |
list.width = 400; | |
list.height = 300; | |
addChild(list); | |
init(); | |
} | |
private function addPNG(data:ByteArray, filename:String):void | |
{ | |
if(determinePNGSize(data)) | |
{ | |
var className:String = CLASSNAME + "_" + currentCharacterId; | |
var classBuilder:IClassBuilder = packageBuilder.defineClass(className, "flash.display.BitmapData"); | |
classBuilder.isDynamic = true; | |
// BitmapData subclasses need a custom constructor, for example: | |
// public function BitmapDataSubclass(width:int = 550, height:int = 400) { | |
// super(width, height) | |
// } | |
var ctorBuilder:ICtorBuilder = classBuilder.defineConstructor(); | |
ctorBuilder.defineArgument("int", true, imgWidth); | |
ctorBuilder.defineArgument("int", true, imgHeight); | |
ctorBuilder.addOpcode(Opcode.getlocal_0) | |
.addOpcode(Opcode.pushscope) | |
.addOpcode(Opcode.getlocal_0) | |
.addOpcode(Opcode.getlocal_1) | |
.addOpcode(Opcode.getlocal_2) | |
.addOpcode(Opcode.constructsuper, [2]) | |
.addOpcode(Opcode.returnvoid); | |
symbolClass.symbols.push(SWFSymbol.create(currentCharacterId, PACKAGENAME + "." + className)); | |
var defineBitsJPEG2:TagDefineBitsJPEG2 = new TagDefineBitsJPEG2(); | |
defineBitsJPEG2.characterId = currentCharacterId; | |
defineBitsJPEG2.bitmapType = BitmapType.PNG; | |
defineBitsJPEG2.bitmapData.writeBytes(data); | |
swf.tags.push(defineBitsJPEG2); | |
list.addItem(filename + " (id: " + currentCharacterId + ")"); | |
currentCharacterId++; | |
} | |
} | |
private function init():void | |
{ | |
swf = new SWF(); | |
swf.tags.push(new TagFileAttributes()); | |
abcBuilder = new AbcBuilder(); | |
packageBuilder = abcBuilder.definePackage(PACKAGENAME); | |
symbolClass = new TagSymbolClass(); | |
list.removeAll(); | |
currentCharacterId = 1; | |
} | |
private function publish():ByteArray | |
{ | |
var abcFile:AbcFile = abcBuilder.build(); | |
var abcSerializer:AbcSerializer = new AbcSerializer(); | |
var abcBytes:ByteArray = abcSerializer.serializeAbcFile(abcFile); | |
swf.tags.push(TagDoABC.create(abcBytes)); | |
swf.tags.push(symbolClass); | |
swf.tags.push(new TagShowFrame()); | |
swf.tags.push(new TagEnd()); | |
var swfData:SWFData = new SWFData(); | |
swf.publish(swfData); | |
return swfData; | |
} | |
// Source: http://www.wischik.com/lu/programmer/get-image-size.html | |
private function determinePNGSize(data:ByteArray):Boolean { | |
// PNG: the first frame is by definition an IHDR frame, which gives dimensions | |
if (data[0] == 0x89 | |
&& data[1] == 0x50 && data[2] == 0x4e && data[3] == 0x47 // "PNG" | |
&& data[4] == 0x0D && data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A | |
&& data[12] == 0x49 && data[13] == 0x48 && data[14] == 0x44 && data[15] == 0x52) { // "IHDR" | |
imgWidth = (data[16] << 24) | (data[17] << 16) | (data[18] << 8) | data[19]; | |
imgHeight = (data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23]; | |
return true; | |
} | |
trace("WARNING: determinePNGSize(): No size found"); | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment