sketchbookライブラリを使わせてもらう

通勤電車ではNintendoDSで英語やるようにしてたけど、昨日のプロフェッショナルを見たからにはそうもいかない!いきなりコーディングで表現模索とか「絵具を使うようにプログラミング」すぎてびびりました。

でもコードによる表現で試行錯誤するには AS3 は絶対的にコード記述量が多すぎるというのは達人の方々が以前から仰っていましたね。
ということで、前から興味のあった fladdict さんsketchbook ライブラリを本当に少しずつさわってみる。

ライブラリはここに置いてあるのがたぶん最新。
http://sketchbook.libspark.org/svn/as3/trunk/src/

ソースを書いては消しを繰り返す感じで勉強予定なので、消す前にペーストして備忘録代わりにするエントリ。恥ずかしいぐらい初歩段階から始める。

コードのコピペだけで申し訳ないですが、すべてのコードは、sketchbook ライブラリを svn で取得してクラスパスを通し、SketchbookTest.as というファイルを作って以下のコードのいずれかをコピペしてもらって、ドキュメントクラスとして設定すれば動きます。同階層にsample.pngという画像も置くようにしてください。

SpriteHelper クラス

Sprite 操作を簡潔にしてくれるヘルパークラス。graphics, colorTransform, matrix 等へのショートカットができるのでコード記述量が減らせる。そのおまけに星型とか任意の点を結ぶ三角形や四角形が描画できる。AS2ライクに onRollOver = function(){} みたいに書ける。
localToLocal といった座標変換系ユーティリティーもある。今回は使ってない。

SketchbookTest.as: ドキュメントクラスにしてパブリッシュするとステージ上に星型30角形。クリックとかマウスオーバーとか実装。

package  {
import flash.display.Sprite;
import sketchbook.SketchBook;
import sketchbook.display.SpriteHelper;

public class SketchbookTest extends Sprite{

public function SketchbookTest() {
//初期化。SpriteHelper使う場合必須。引数にstageを渡す必要あり。
SketchBook.init(stage);
//対象となるスプライト
var mySprite:Sprite = new Sprite();
//ヘルパー作成。引数にヘルパーしたいスプライトを渡す。
var helper:SpriteHelper = new SpriteHelper(mySprite);

helper.beginFill(0xFF0000);
//ステージの中心に外径60px、内径50pxの30角形を作る。あらかじめ45度回転しておく。(ただしこの回転はSprite自体の回転ではなく、graphicsにおける回転)
helper.drawStar(stage.stageWidth/2, stage.stageHeight/2, 60, 50, 30, 45);
helper.endFill();
addChild(mySprite);

//イベント処理。こうやってAS2ライクに書ける。
helper.onEnterFrame = function():void {
//helper.rotation += 1;
}
helper.onClick = function():void {
helper.y += 30;
}
helper.onRollOver = function():void {
this.alpha = 0.5;
}
helper.onRollOut = function():void {
this.alpha = 1;
}
}
}
}

Mosaic クラス(sketchbook.imageprocessing.Mosaic)

2行でモザイク化できる。よくある「モザイク→元画像」みたいな効果は sketchbook.display.BitmapDataHelper の mosaic メソッドの方でやるんかな。帰りの電車で遊ぶ。

package  {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.events.Event;
import sketchbook.imageprocessing.Mosaic;

public class SketchbookTest extends Sprite{
private var loader:Loader = new Loader();
public function SketchbookTest() {
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("sample.png"));
}
private function onComplete(event:Event):void{
var image:Bitmap = Bitmap(loader.content);
var bitmap:BitmapData = image.bitmapData;
addChild(image);
//5px四方のモザイクにする。
var m:Mosaic = new Mosaic(5, 5);
m.apply(bitmap);
}
}
}

BitmapDataHelper クラス(sketchbook.display.BitmapDataHelper)

BitmapData 系の扱いを楽にしてくれるそうです。簡単にフィルタやモザイクかけれますが、中でも事前に capture() しておけば restore() で戻せる仕組みがすごく重宝しそうな予感。dispose() 処理も適宜裏側で実行してくれているので、メモリ負荷とかに詳しくないユーザーさんこそ使ってみてはいかがでしょうか。

朝の続きで、「モザイク→元画像」をやってみました。BitmapDataHelper.as には mosaic() メソッドがあり、仕組みとしてはマトリックスで画像を縮小し(line:127)、即座にマトリックスで拡大して戻す(line:130)してモザイク化するアプローチ。試してみたところ、少なくとも130行目の draw のスムージングの true を false にしないと僕のコードでモザイクにならない様子。
あと、モザイクサイズによっては画像の下と右がマトリックス漏れ(なんと言ったらいいのかな?引数と画像サイズが割り切れない時、処理対象から外れる部分があるってことです)するので、ビットマップのふちに柄がない画像の時だけ使うか、むらけんさんのモザイクみたいに一旦縮めてから width, height で強制リサイズするアプローチにするかだけど、まだsketchbookの全容が分かってないのでとりあえずここまで。display パッケージの中にもあと2個ビットマップ系のクラスがありますしね。

下のコードをドキュメントルートにしてパブリッシュすると、外部画像 sample.png をステージ上に表示、画面をクリックすると「モザイク→元画像」になる。元画像になったら再度クリックで繰り返せます。

package  {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.events.Event;
import flash.utils.Timer;
import sketchbook.display.SpriteHelper;
import sketchbook.display.BitmapDataHelper;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;

public class SketchbookTest extends Sprite{
private var loader:Loader = new Loader();
private var bmpdHelper:BitmapDataHelper;
private var initialMosaicSize:Number = 40;
private var mosaicSize:Number = 0;
private var smallMultiplier:Number = 0.9; //係数
//原画をキャプチャ保存しておくためのビットマップ
private var captureBmpd:BitmapData;
private var timer:Timer;
public function SketchbookTest() {
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("sample.png"));
}
private function onComplete(event:Event):void{
var image:Bitmap = Bitmap(loader.content);
var bitmap:BitmapData = image.bitmapData;
addChild(image);
//BitmapDataHelper
bmpdHelper = new BitmapDataHelper(bitmap);
//キャプチャ用ビットマップに原画を入れておく
captureBmpd = image.bitmapData;
//ステージをクリックでモザイク開始
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHundler);
}

private function onMouseDownHundler(event:MouseEvent):void {
if(mosaicSize==0){
//キャプチャしておく。タイマーイベントの度にrestoreしてこの元画像を参照するため。
captureBmpd = bmpdHelper.capture();
//モザイクの大きさの初期値を設定。
mosaicSize = initialMosaicSize;
//はじめに初期値でモザイクかけておく。
bmpdHelper.mosaic(mosaicSize);
//50ミリ秒ごとにイベントを発生させる
timer = new Timer(50);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
}
}

private function onTimer(event:TimerEvent):void {
if (mosaicSize > 1) {
mosaicSize *= smallMultiplier;
//キャプチャしておいた元画像に一旦戻す。これしないと直前のモザイク画像にモザイクをかけることになる。
bmpdHelper.restore();
//モザイクを小さくしていく。サイズによっては周辺(画像下と右)をモザイク化できないケースがある。
bmpdHelper.mosaic(mosaicSize);
}else {
mosaicSize = 0;
//キャプチャしておいた元画像に完全に戻す。
bmpdHelper.restore();
//タイマーを停止
timer.removeEventListener(TimerEvent.TIMER, onTimer);
}
}
}
}

上のコードをちょっとだけいじって、ステージクリックで「ブラー→元画像」になるコード。フィルタ値は2の乗数にすると高速なので、Math.pow(2, 乗数) で初期値を設定し、2で割り続けています。フィルタ値をトゥイーンさせたりして調整するとよりよくなる予定。

package  {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.events.Event;
import flash.utils.Timer;
import sketchbook.display.SpriteHelper;
import sketchbook.display.BitmapDataHelper;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;

public class SketchbookTest extends Sprite{
private var loader:Loader = new Loader();
private var bmpdHelper:BitmapDataHelper;
//フィルタは2のべき乗にすると高速なので、2の10乗に設定してみる
private var initialBlurSize:Number = Math.pow(2,10);
private var blurSize:Number = 0;
//原画をキャプチャ保存しておくためのビットマップ
private var captureBmpd:BitmapData;
private var timer:Timer;
public function SketchbookTest() {
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("sample.png"));
}
private function onComplete(event:Event):void{
var image:Bitmap = Bitmap(loader.content);
var bitmap:BitmapData = image.bitmapData;
addChild(image);
//BitmapDataHelper
bmpdHelper = new BitmapDataHelper(bitmap);
//キャプチャ用ビットマップに原画を入れておく
captureBmpd = image.bitmapData;
//ステージをクリックでブラー開始
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHundler);
}

private function onMouseDownHundler(event:MouseEvent):void {
if(blurSize==0){
//キャプチャしておく。タイマーイベントの度にrestoreしてこの元画像を参照するため。
captureBmpd = bmpdHelper.capture();
//ブラー量の初期値を設定。
blurSize = initialBlurSize;
//はじめに初期値でブラーかけておく。
bmpdHelper.blur(blurSize, 0);
//40ミリ秒ごとにイベントを発生させる(25fpsのイメージ)
timer = new Timer(40);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
}
}

private function onTimer(event:TimerEvent):void {
//最後1になるまで2で割り続ける
if (blurSize != 1) {
//2のべき乗にし続けたいので、2で割り続ける
blurSize = blurSize / 2;
//キャプチャしておいた元画像に一旦戻す。これしないと直前のブラー画像にブラーをかけることになる。
bmpdHelper.restore();
//ブラーを小さくしていく。
bmpdHelper.blur(blurSize, 0);
}else {
blurSize = 0;
//キャプチャしておいた元画像に完全に戻す。
bmpdHelper.restore();
//タイマーを停止
timer.removeEventListener(TimerEvent.TIMER, onTimer);
}
}
}
}

GraphicsHelper クラス(sketchbook.graphics.GraphicsHelper)

一旦ビットマップから離れて、AS で図形を描画するのにめちゃくちゃ便利な GraphicsHelper クラスです。AS3でもとから描画できる図形はもちろん、他にも下のような図形が直観的な指定で描画できます。こうやって図形が簡単に直観的に描画できることで、その先のステップに注力できます。便利すぎ!!!!!

sketchbook_GraphicsHelper.jpg

図形は左上から上段が1,2,3, 下段が4,5,6です。使い方は SpriteHelper クラスと同じ感じで、GraphicsHelper の引数に Sprite の graphics を渡します。

package  {
import flash.display.Sprite;
import flash.geom.Point;
import sketchbook.graphics.GraphicsHelper;

public class SketchbookTest extends Sprite {
public function SketchbookTest() {
var sp1:Sprite = new Sprite();
var sp2:Sprite = new Sprite();
var sp3:Sprite = new Sprite();
var sp4:Sprite = new Sprite();
var sp5:Sprite = new Sprite();
var sp6:Sprite = new Sprite();
addChild(sp1);
addChild(sp2);
addChild(sp3);
addChild(sp4);
addChild(sp5);
addChild(sp6);
var gHelper1:GraphicsHelper = new GraphicsHelper(sp1.graphics);
var gHelper2:GraphicsHelper = new GraphicsHelper(sp2.graphics);
var gHelper3:GraphicsHelper = new GraphicsHelper(sp3.graphics);
var gHelper4:GraphicsHelper = new GraphicsHelper(sp4.graphics);
var gHelper5:GraphicsHelper = new GraphicsHelper(sp5.graphics);
var gHelper6:GraphicsHelper = new GraphicsHelper(sp6.graphics);
//星型(歯車)を作る(以降、円形っぽい図形はx,y指定した箇所が中心点となる仕様なので便利)
gHelper1.beginFill(0xFF0000);
gHelper1.drawStar(50, 100, 40, 30, 20, 0);
//弧というか、弧と弧の両端を結んだ図形になる。この図形なんて言うの?
gHelper2.beginFill(0x00FF00);
gHelper2.drawArc(150, 100, 40, 270, 0, 36);
//扇型を描画
gHelper3.beginFill(0x0000FF);
gHelper3.drawPie(250, 100, 40, 270, 0, 36);
//リングを描画。開いたリングも描ける
gHelper4.beginFill(0xFFFF00);
gHelper4.drawRing(50, 200, 40, 30, 270, 90);
//四隅がそれぞれ異なるRの矩形を描画。
gHelper5.beginFill(0xFF00FF);
gHelper5.drawRoundRectComplex(150, 200, 60, 40, 5, 10, 15, 20);
//線を簡単に描ける。lineStyle設定することと、引数はpointの配列を与えること。
gHelper6.lineStyle(5, 0x00FFFF);
gHelper6.drawLines([new Point(250, 200),new Point(300, 200),new Point(280,240)], false);
}

}
}

Comments:5

fladdict 08-04-03 (木) 18:48

わーい、ご使用ありがとうございますですよ。

>2行でモザイク化できる。よくある「モザイク→元画像」みたいな効果は sketchbook.display.BitmapDataHelper の mosaic メソッドの方でやるんかな。

そんな感じです。

imageprocessingは画像の超原始的な加工を同じAPIでする為のクラス群です(数少ないけど)。

var ar:Array = [ myDotPattern, myCopyPixels, myMosaic, myColorTransformProcessing]

みたいに、imageprocessingを配列にいれて

for(var i:int=0; iわーい、ご使用ありがとうございますですよ。

>2行でモザイク化できる。よくある「モザイク→元画像」みたいな効果は sketchbook.display.BitmapDataHelper の mosaic メソッドの方でやるんかな。

そんな感じです。

imageprocessingは画像の超原始的な加工を同じAPIでする為のクラス群です(数少ないけど)。

var ar:Array = [ myDotPattern, myCopyPixels, myMosaic, myColorTransformProcessing]

みたいに、imageprocessingを配列にいれて

for(var i:int=0; i ar[i].apply(myBitmap)
}

みたいにすることで、対象への複雑なビットマップ加工を一括処理しちゃおうみたいなクラスです。

単体で使う場合は、bitmapHelperのほうが使い勝手がいいです。多分。

tera 08-04-03 (木) 22:30

>fladdict さん
お忙しい中、ご本人様降臨コメントありがとうございますー。
なるほど~。僕はご提示いただいたような「一括処理」がスマートにできない人なので、早速勉強させていただきます!

しばらくはコード書いてコピペするだけの自分用メモエントリなので見づらいエントリですが、ある程度理解できたら僕なりにまとめてみようと思ってます~。
ありがとうございます!僕にも便利なライブラリです!

yasuo 08-04-05 (土) 23:28

どうも、はじめまして。
AS3の書き方に抵抗がない派です。

>帰りの電車で遊ぶ。
っていう、一文を見たんですが、電車の中でFlashやってるんですか?ノートパソコン持ちながらコーディングとかっすか?
参考まで、僕も電車の中でコーディングとかしたいんで、どんな風にしてるのか教えていただけたらと思います。DS見たいな感覚でやるならFujituのluxUにCS3インストールしてやるぐらいの勢いじゃないとだめですよね。

tera 08-04-06 (日) 0:46

yasuo様
はじめまして。こんばんは。

通勤はソフトケースにThinkPad X61(B5)だけ持って、割と座れる電車なので、膝に乗せて片道40分ほど FlashDevelop でコーディング&ライブラリ解読して、 Flash CS3 でパブリッシュを繰り返す感じです。
といっても最近このスタイルにしたばかりなので、どれほど効率があるかは分かりませんが、粒度のあるライブラリを軽く勉強するのにはいいかなと思ってたりします。

yasuo 08-04-06 (日) 1:17

teraさん

どうもです。
あーやっぱり、X61か、そうですよね、座れればいんですが、立ってることが多いい僕には、ちとつらいかも。
座れるときがあれば、mackbookで、挑戦してみます。
でなければ、いつもどうりEssential ActionScript 3.0とかを、激読ですね。

ありがとうございます。

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://www.trick7.com/blog/2008/04/02-232733.php/trackback
Listed below are links to weblogs that reference
sketchbookライブラリを使わせてもらう from trick7

Moleskine Plain Notebook Large

アイデア帳として。

AS3習得本
AS3の全容を学習できる本。この中でどれか1冊自分に合ったものを。
Adobe Flash CS3 詳細! ActionScript 3.0 入門ノート (DVD-ROM付) Adobe Flash CS3 詳細! ActionScript3.0入門ノート2 (CD-ROM付) ActionScript3.0 プロフェッショナルガイド 初めてのActionScript 3.0 Flashユーザーのためのステップアップガイド 詳説 ActionScript 3.0 Actionscript 3.0 Cookbook
AS3発展本
ASでアニメーションさせる面白さを知るための本。最後のはPHP連携デビューにオススメの洋書。
Flash Math & Physics Design:ActionScript 3.0による数学・物理学表現[入門編] ActionScript 3.0 アニメーション AdvancED ActionScript 3.0 Animation (Advanced) Flash and PHP Bible (Bible (Wiley))
AS2
"Flash"ではなく"ActionScript2.0"学習のための良著。他にもいろいろ読んだけど、この4冊を読んだ後、自分が成長できた感じがしました。
FLASH ActionScript 2.0入門完全ガイド+実践サンプル集 [CD-ROM付] Essential Actionscript 2.0 Flash 8 Essentials Foundation Actionscript Animation: Making Things Move (Foundation)

Return to page top