喜び勇んで英語版Flash CS3 Trialをインストールした皆様、そろそろ試用期限が切れてしまった頃でしょうか?
FICC安藤です。
FICCサイトのバックエンドの設計、構築、FLASH開発など担当しました、裏方の人です。
MT+Flashの記事から始める予定でしたがCS3日本語版の発売間近という事もあり先にCS3(AS3)関連のエントリーから。
今回はFlashから画像ファイルを保存する方法です。
画像ファイルを保存するという事だけであればAS2時代から「一応」可能でしたが今回はせっかくAS3ですのでよりスマートな方法で実現したいと思います。
ちなみに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でレタッチソフトとか作れますね。
はじめまして。いつもFICC様のお仕事を楽しみにさせていただいてます。
ちょっと前に、同様のことをやりたかったのですが、AS3&PHPがよく分からず、結局AS2でやってしまいました。
こちらの記事を参考に、AS3版にトライしてみます。
ありがとうございました。
僕もCS3の体験版期限が切れたのですが、そのままアプリ自体を終了させないでおくと、ずっと使えるようです。Adobeさんに怒られるかもしれませんが。
はじめまして、というより以前個人ブログでOSXのホイールの件でゴニョゴニョ。
CS3日本語版発売まであと9日・・遠いですね。
あ、Back...ブログの中の方なのですね!
その節はお世話になりました。
今後の記事も楽しみにさせていただきます。ありがとうございました。