たまにはAIRのサンプルも置いてみる

みなさんお久しぶりです。

こないだ仕事中に作っちゃったAIRアプリがサンプルとして結構逝けてるのでアップしてみました。
AIRファイルもそのうち置きますが、FC2へのアップの仕方を忘れてしまったので(ダメPG…)。

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
	paddingLeft="0" paddingRight="0" paddingBottom="0" paddingTop="0" 
	nativeDragEnter="dragEnterHandler(event)" nativeDragDrop="dragDropHandler(event)"
	horizontalScrollPolicy="off" verticalScrollPolicy="off"
	title=" PNGファイルの半透明を消しちゃうぞ1号"
	>
	<mx:Script>
		<![CDATA[
			import mx.graphics.ImageSnapshot;
			import mx.graphics.codec.PNGEncoder;
			import mx.controls.Image;
			import mx.containers.Canvas;

			private function dragEnterHandler(e:NativeDragEvent):void{
				if(e.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)){
					NativeDragManager.acceptDragDrop(this);
				}
			}
			private function dragDropHandler(e:NativeDragEvent):void{
				frontLabel.visible = false;
				hList.removeAllChildren();
				var fileName:String;
				try{
					var files:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
					for each(var file:File in files){
						if((file.exists) && (file.extension == "png")){
							fileName = file.nativePath;
							var fs:FileStream = new FileStream();
							var bytes:ByteArray = new ByteArray();
							fs.open(file,FileMode.READ);
							fs.readBytes(bytes);
							fs.close();
							log.text += "読み込み開始:" + fileName+"\n";
							var loader:Loader = new Loader();
							loader.contentLoaderInfo.addEventListener(Event.COMPLETE, getFunction(file));
							loader.loadBytes(bytes);
						}
					}
				}catch(err:Error){
					trace("error:"+err.message);
					log.text+= "読み込みに失敗しました:" + fileName +"\n";
				}
			}
			private function getFunction(file:File):Function{
				return function(e:Event):void{
					var ld:Loader = LoaderInfo(e.currentTarget).loader;
					return addCanvas(file,ld);
				}
			}
			private function addCanvas(file:File,ld:Loader):void{
				if(file){
					var canvas:Canvas = new Canvas();
					canvas.setStyle("backgroundColor",cPicker.selectedColor);
					var img:Image = new Image();
					img.source = ld;
					canvas.addChild(img);
					canvas.setActualSize(img.width,img.height);
					canvas.data = file;
					hList.addChild(canvas);
				}
			}
			private function onUpdate(e:Event):void{
				if(hList.numChildren > 0){
					var canvas:Canvas = hList.getChildAt(0) as Canvas;
					if(canvas){
						save(canvas);
					}
					hList.removeChild(canvas);
				}
			}
			private function save(canvas:Canvas):void{
				var file:File = canvas.data as File;
				var pngEncoder:PNGEncoder = new PNGEncoder();
				var bmpData:BitmapData = ImageSnapshot.captureBitmapData(canvas);
				var pngBytes:ByteArray = pngEncoder.encode(bmpData);
				var fileName:String = file.nativePath;
				// FileStreamクラスのインスタンス作成
				try{
					var stream:FileStream = new FileStream( );
					stream.open(file, FileMode.WRITE);
					stream.writeBytes(pngBytes, 0, pngBytes.length);
					stream.close( );
					log.text+= "成功:" + fileName +"\n";
				}catch(err:Error){
					trace("error:"+err.message);
					log.text+= "書き込みに失敗しました:" + fileName +"\n";
				}
			}
		]]>
	</mx:Script>
	<mx:ApplicationControlBar width="100%" minWidth="0">
		<mx:Label text="背景色"/>
		<mx:ColorPicker id="cPicker" selectedColor="#ffffff"/>
	</mx:ApplicationControlBar>
	<mx:Panel width="100%" height="100%" horizontalScrollPolicy="off" verticalScrollPolicy="off" layout="absolute"
		
		headerHeight="0">
		<mx:TextArea id="log" editable="false" width="100%" height="100%" x="0" y="0" alpha="0.6" />
		<mx:ViewStack id="hList" x="0" y="0" resizeToContent="true" updateComplete="onUpdate(event)"/>
		<mx:Text id="frontLabel"
			width="100%" textAlign="center"
			verticalCenter="0" fontSize="14" fontWeight="bold"
			text="{'この辺めがけてドロップしてね\nいきなり書き換えるからバックアップを忘れずに'}">
			<mx:filters>
				<mx:DropShadowFilter color="0xcccccc"/>
			</mx:filters>
		</mx:Text>
	</mx:Panel>
</mx:WindowedApplication>

何をするプログラムかというと、ソースにも書いてますが「PNGファイルの半透明を他の色で置換する」というソフトです。
ドロップしたPNGファイルの中身をいきなり上書きします。
バックアップファイルも作らないしドロップ以外の読み込み方法もありません。人としてサイテーです。

こんなソフトを作成したのには理由があります。
最近、社内でヘルプを書いているのですが、大量にスクリーンショットを取る必要が生じ、そこでアプリケーション第1弾「MonkeyBinder」を作成しました。
MonkeyBinderは、Flexアプリケーションのコードにタグを一行入れるだけで、狙ったコンポーネントスクリーンショットをキー一発で作成してくれる優れものです。どうやってるか想像がついた?黙っててください。
これはまたそのうちどこかにアップするつもりですが、いろいろと一般人には受け入れがたい(?)問題点があるので、直してからにしようと思っています。

で、Adobe様謹製のヘルプ作成ソフト「RoboHelp7」でゴニョゴニョ書いたヘルプに、スクリーンショットを入れて…とやってるうちに、気がついてしまいました。IE6では、PNG画像の半透明部分の表示にバグがあり(というか未対応らしい)、おかしな色になってしまうのです。
せめてJPEGやGIFで書き出しておけば良かったのですが、100枚ものスクリーンショットを取り直すのは問題外。
GIFに変換するのも検討しましたが、ヘルプファイルのHTML内のファイル名を全部.GIFにするのも面倒くさい。
PNGのままで使う画像もあるし…。

というわけで、仕事が終わってから翌日までの間に布団の中で作成したのがこの「PNGファイルの半透明を消しちゃうぞ1号」です。
ヘタをすりゃこのエントリ書いてる時間の方が長いかも…。

では、ソースの解説。
ドラッグ&ドロップした画像ファイルを開き、書き戻すところなんかは参考になるかもしれません。
もっとも、書き込み禁止のファイルとかフェイルセーフについてはガン無視です。
ビットマップからAlphaを消すのは面倒だったので、単色のCanvasの上に書いて、まるごとスナップショットを取り直しています。
こんな方法をとってしまったが故に、画像を書く前に保存しようとしてbitmapDataのエラーを吐かれてしまいました。
なので、画面の更新が終わってから、そのイベントで保存させるという、何とも情けない方法をとっています。ショートプログラムだから許されるようなもんですね。

まぁ、実際のところ、自分の用さえ済んでしまえばあんまり手直しする気も起こらないわけで…。
ただ、こんな感じで画像加工プログラムをAIRで作っておくと、いろいろ便利かもしれません。
画像じゃなくても、コード整形なんかにも有効ですね。
HTMLの画像ファイル名を書き換えてくれるプログラムとか…あれ?