Flashから画像ファイルを保存する

喜び勇んで英語版Flash CS3 Trialをインストールした皆様、そろそろ試用期限が切れてしまった頃でしょうか?

FICC安藤です。
FICCサイトのバックエンドの設計、構築、FLASH開発など担当しました、裏方の人です。
MT+Flashの記事から始める予定でしたがCS3日本語版の発売間近という事もあり先にCS3(AS3)関連のエントリーから。

今回はFlashから画像ファイルを保存する方法です。
画像ファイルを保存するという事だけであればAS2時代から「一応」可能でしたが今回はせっかくAS3ですのでよりスマートな方法で実現したいと思います。

(Player9.0.45.0以降が必要です)

ちなみにAS2ではgetPixel()を使い左上から右下までのピクセルの色情報が入った配列をPHPなどにポストし、サーバで同じように1ピクセルずつ描いて復元するという方法で可能です。
実際に現在のFICCサイトもその方法でエントリー投稿時にローカルの管理ツールから文字のPNGをアップロードし、その内容を自動でMTにポストする形をとっていますがサーバ負荷を考えるとあまりお勧めできません。

それでは必要な下準備からしていきましょう。
今回のサンプルではAdobe Labsのas3corelibのJPGEncoderクラスを利用します。

SVNリポジトリはこちら
http://as3corelib.googlecode.com/svn/

package {
	import flash.display.Sprite;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import fl.controls.Button;
	import flash.events.MouseEvent;
	import flash.utils.ByteArray;
	import flash.text.TextField;
	import flash.net.*;
	import com.adobe.images.JPGEncoder;
	public class CaseStudy extends Sprite {
		private var bmdPerlin:BitmapData;
		private var bmp:Bitmap;
		private var urlRequest:URLRequest
		private var urlLoader:URLLoader;
		private var imgDir:String = "http://yourdomain/img/";
		private var phpPath:String = "http://yourdomain/encoder.php";
		private var fileName:String;
		private var btnRedraw:Button;
		private var btnUpload:Button;
		private var btnImage:Button;
		private var txtFld:TextField;
		public function CaseStudy() {
			stage.quality   = "MEDIUM";
			stage.scaleMode = "noScale";
			bmdPerlin = new BitmapData(100, 100, false, 0x00CCCCCC);
			bmp = new Bitmap(bmdPerlin);
			bmp.x = 180;
			bmp.y = 30;
			drawPerlinNoise(null);
			addChild(bmp);
			txtFld = new TextField();
			txtFld.text = "アップロード中";
			txtFld.x = 190;
			txtFld.y = 135;
			addChild(txtFld);
			txtFld.visible = false;
			setRedrawBtn();
			setUploadBtn();
			setImageBtn();
		}
		//-----------------------------------------------------------------//
		//	redraw button
		//-----------------------------------------------------------------//
		private function setRedrawBtn():void {
			btnRedraw = new Button();
			btnRedraw.label = "redraw";
			btnRedraw.move(140, 160);
			btnRedraw.setSize(80,30);
			addChild(btnRedraw);
			btnRedraw.addEventListener(MouseEvent.CLICK, drawPerlinNoise);
		}
		private function drawPerlinNoise(event:Event):void {
			bmdPerlin.perlinNoise(Math.floor(Math.random()*100),Math.floor(Math.random()*100),6,Math.floor(Math.random()*10),false,true);
		}
		//-----------------------------------------------------------------//
		//	upload button
		//-----------------------------------------------------------------//
		private function setUploadBtn():void {
			btnUpload = new Button();
			btnUpload.label = "upload";
			btnUpload.move(240, 160);
			btnUpload.setSize(80,30);
			addChild(btnUpload);
			btnUpload.addEventListener(MouseEvent.CLICK, upload);
		}
		private function upload(event:Event):void{
			btnRedraw.enabled = false;
			btnUpload.enabled = false;
			txtFld.visible = true;
			var jpgEncoder:JPGEncoder = new JPGEncoder(80);
			var byteArr:ByteArray = jpgEncoder.encode(bmdPerlin);
			urlRequest = new URLRequest(phpPath);
			urlLoader = new URLLoader();
			urlRequest.contentType = "application/octet-stream";
			urlRequest.method = URLRequestMethod.POST;
			urlRequest.data = byteArr;
			urlLoader.load(urlRequest);
			urlLoader.addEventListener(Event.COMPLETE,onUpload);
		}
		private function onUpload(event:Event):void{
			txtFld.visible = false;
			bmp.visible = false;
			btnImage.visible = true;
			fileName = urlLoader.data;
		}
		//-----------------------------------------------------------------//
		//	画像を表示 button
		//-----------------------------------------------------------------//
		private function setImageBtn():void{
			btnImage = new Button();
			btnImage.label = "画像を表示";
			btnImage.move(180,30);
			btnImage.setSize(100,100);
			addChild(btnImage);
			btnImage.visible = false;
			btnImage.addEventListener(MouseEvent.CLICK, openURL);
		}
		private function openURL(event:Event):void{
			navigateToURL(new URLRequest(imgDir+fileName),"_blank");
			btnRedraw.enabled = true;
			btnUpload.enabled = true;
			btnImage.visible = false;
			bmp.visible = true;
		}
	}
}

画像の保存と関係のないコードで少し長くなりましたが、必要な部分はシンプルです。

var jpgEncoder:JPGEncoder = new JPGEncoder(JPGの画質);
var byteArr:ByteArray = jpgEncoder.encode(BitmapData);


あとはbyteArrに入ったJPGバイナリをPHPに送るだけです。
以下、データを保存してファイル名をprintするだけのシンプルなPHPです。
必要に応じて書き加えてください。

<?php
$fileName = time()."-".round(rand(1,10000)).".jpg";
$fp = fopen("img/".$fileName, 'wb');
fwrite($fp, $GLOBALS['HTTP_RAW_POST_DATA']);
fclose($fp);
print $fileName;
?>

ちなみにJPGEncoderと同様にPNGEncoderもありますが、こちらはstaticなので使い方が異なります。

import com.adobe.image.PNGEncoder;
var byteArr:ByteArray = PNGEncoder.encode(BitmapData);

これでFlashでレタッチソフトとか作れますね。

トラックバック(1)

このブログ記事を参照しているブログ一覧: Flashから画像ファイルを保存する

このブログ記事に対するトラックバックURL: http://www.ficc.jp/cgi-bin/mt4/mt-tb.cgi/8

メタセコイアファイル(.mqo)のビューワを新しく作ってみた。今回はFABridgeを使用して、読み込むモデルをサイト側が決定できる方法にしてみた。テス... 続きを読む

コメント(3)

はじめまして。いつもFICC様のお仕事を楽しみにさせていただいてます。
ちょっと前に、同様のことをやりたかったのですが、AS3&PHPがよく分からず、結局AS2でやってしまいました。
こちらの記事を参考に、AS3版にトライしてみます。
ありがとうございました。

僕もCS3の体験版期限が切れたのですが、そのままアプリ自体を終了させないでおくと、ずっと使えるようです。Adobeさんに怒られるかもしれませんが。

はじめまして、というより以前個人ブログでOSXのホイールの件でゴニョゴニョ。

CS3日本語版発売まであと9日・・遠いですね。

あ、Back...ブログの中の方なのですね!
その節はお世話になりました。
今後の記事も楽しみにさせていただきます。ありがとうございました。

コメントする