スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | | スポンサー広告

Flex2でレンズ

以前Flashで作ったレンズで部分拡大をFlex2(というかActionScript3.0)でも作ってみました。




基本的にやってることはFlash版と同じデス。

ActionScriptはこんなカンジです。

package {
import flash.display.*;
import flash.events.*;
import flash.ui.Mouse;
// メインクラス
public class LensSample extends Sprite {
// 画像リソース
[Embed(source='image.png')]
private var ImageBitmap:Class;
// サイズ入力欄
private var sizeInput:LabelInput;
// 曲率半径入力欄
private var rInput:LabelInput;
// 焦点距離入力欄
private var fInput:LabelInput;
// 設定ボタン
private var settingBtn:LabelButton;
// 画像
private var imageBitmap:Bitmap;
// レンズ
private var lens:BitmapSprite;
// サイズ
private var size:Number;
// コンストラクタ
public function LensSample() {
// サイズ入力欄
sizeInput = new LabelInput("サイズ", "100");
addChild(sizeInput);
// 曲率半径入力欄
rInput = new LabelInput("曲率半径", "70");
rInput.x = 90;
addChild(rInput);
// 焦点距離入力欄
fInput = new LabelInput("焦点距離", "100");
fInput.x = 200;
addChild(fInput);
// 設定ボタン
settingBtn = new LabelButton(" 設定 ");
settingBtn.x = 300;
settingBtn.addEventListener(MouseEvent.CLICK,
onSettingBtnClick);
addChild(settingBtn);
// 画像
imageBitmap = new ImageBitmap();
imageBitmap.x = 100;
imageBitmap.y = 50;
addChild(imageBitmap);
// レンズ
lens = new BitmapSprite();
lens.visible = false;
addChild(lens);
// セットアップ
onSettingBtnClick(null);
// イベントリスナ
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
// 設定ボタンをクリックしたときの処理
private function onSettingBtnClick(evt:Event):void {
size = Number(sizeInput.inputText);
// レンズにフィルタをセット
lens.filters = [LensFilterFactory.create(size,
Number(rInput.inputText),
Number(fInput.inputText))];
}
// フレーム毎の処理
private function onEnterFrame(evt:Event):void {
// 画像上にマウスカーソルが存在したらレンズ処理
if (mouseX >= imageBitmap.x
&& mouseX <= imageBitmap.x + imageBitmap.width
&& mouseY >= imageBitmap.y
&& mouseY <= imageBitmap.y + imageBitmap.height) {
var bitmap:BitmapData
= BitmapDataUtils.clip(imageBitmap,
imageBitmap.mouseX - size / 2,
imageBitmap.mouseY - size / 2,
size,
size);
lens.x = mouseX - size / 2;
lens.y = mouseY - size / 2;
lens.bitmapData = bitmap;
Mouse.hide();
lens.visible = true;
} else {
Mouse.show();
lens.visible = false;
}
}
}
}
import flash.display.*;
import flash.text.*;
import flash.filters.DisplacementMapFilter;
import flash.geom.*;
// BitmapDataユーティリティ
class BitmapDataUtils {
// 指定したオブジェクトからクリッピングしたビットマップデータを
// 戻します。
public static function clip(src:IBitmapDrawable,
x:Number,
y:Number,
w:Number,
h:Number):BitmapData {
var dest:BitmapData = new BitmapData(w, h);
var matrix:Matrix = new Matrix();
matrix.tx = -x;
matrix.ty = -y;
dest.draw(src,
matrix,
new ColorTransform(),
"normal",
new Rectangle(0, 0, w, h),
false);
return dest;
}
}
// 内部にビットマップを持つスプライト
class BitmapSprite extends Sprite {
// 内部画像
private var src:Bitmap;
// コンストラクタ
public function BitmapSprite() {
// 画像
src = new Bitmap();
addChild(src);
}
// ビットマップデータをセット
public function set bitmapData(bitmapData:BitmapData):void {
if (src.bitmapData) {
src.bitmapData.dispose();
}
src.bitmapData = bitmapData;
}
}
// レンズフィルタファクトリ
class LensFilterFactory {
// DisplacementMapFilterを作成し、戻します。
public static function create(size:Number,
r:Number,
f:Number):DisplacementMapFilter {
var mapData:BitmapData = new BitmapData(size,
size,
false,
0xFF008080);
var o:Number = size / 2;
var o2:Number = o * o;
var r2:Number = r * r;
var y:Number;
var dY:Number;
var dY2:Number;
var x:Number;
var dX:Number;
var dR2:Number;
var l:Number;
var d:Number
// 調整値を割り出す
var maxY:Number = 0;
var maxX:Number = 0;
for (y = 0; y < size; y++) {
dY = y - o;
dY2 = dY * dY;
for (x = 0; x < size; x++) {
dX = x - o;
dR2 = dX * dX + dY2;
// ピクセルが、レンズムービークリップの内接円に
// 入っている場合のみ処理
if (dR2 < o2) {
// ずれ
l = Math.sqrt(r2 - dR2) - Math.sqrt(r2 - o2);
d = l / (f + l);
// 最大値設定
maxY = Math.max(maxY, Math.abs(dY * d));
maxX = Math.max(maxX, Math.abs(dX * d));
}
}
}
var yAdj:Number = 128 / (maxY + 1);
var xAdj:Number = 128 / (maxX + 1);
// ビットマップ生成
for (y = 0; y < size; y++) {
dY = y - o;
dY2 = dY * dY;
for (x = 0; x < size; x++) {
dX = x - o;
dR2 = dX * dX + dY2;
// ピクセルが、レンズムービークリップの内接円に
// 入っている場合のみ処理
if (dR2 < o2) {
// ずれ
l = Math.sqrt(r2 - dR2) - Math.sqrt(r2 - o2);
d = l / (f + l);
// ピクセルの色
var yC:Number = -Math.floor(dY * d * yAdj);
var xC:Number = -Math.floor(dX * d * xAdj);
var c:Number = 0xFF000000
+ (0x80 + yC) * 0x100
+ (0x80 + xC);
// ピクセルを描画する
mapData.setPixel(x, y, c);
}
}
}
// フィルタ作成
var filter:DisplacementMapFilter
= new DisplacementMapFilter(mapData,
new Point(),
4,
2,
Math.ceil(256 / xAdj),
Math.ceil(256 / yAdj));
return filter;
}
}
// ラベル付き入力フィールド
class LabelInput extends Sprite {
// ラベル
private var label:TextField;
// 入力フィールド
private var input:TextField;
// コンストラクタ
public function LabelInput(labelText:String,
inputDefault:String) {
// フォーマット
var format:TextFormat=new TextFormat();
format.font = "_等幅";
format.size = 10;
format.color = 0x000000;
// ラベル生成
label = new TextField();
label.setTextFormat(format);
label.autoSize = TextFieldAutoSize.LEFT;
label.text = labelText;
addChild(label);
// 入力欄生成
input = new TextField();
input.border = true;
input.type = TextFieldType.INPUT;
input.setTextFormat(format);
input.x = label.x + label.width;
input.width = 50;
input.height = label.height;
input.text = inputDefault;
addChild(input);
}
// 入力文字列を戻します。
public function get inputText():String {
return input.text;
}
// 入力文字列を設定します。
public function set inputText(value:String):void {
input.text = value;
}
}
// ラベル付きボタン
class LabelButton extends Sprite {
// コンストラクタ
public function LabelButton(labelText:String) {
// フォーマット
var format:TextFormat=new TextFormat();
format.font = "_等幅";
format.size = 10;
format.color = 0x000000;
// ラベル生成
var label:TextField = new TextField();
label.setTextFormat(format);
label.text = labelText;
label.autoSize = TextFieldAutoSize.CENTER;
label.border = true;
label.background = true;
label.backgroundColor = 0xdddddd;
label.selectable = false;
label.mouseEnabled = false;
addChild(label);

buttonMode = true;
}
}
で、swfの作成はFlex2SDKを使って
mxmlc -default-size 400 300 -default-frame-rate=12 -default-background-color=0xFFFFFF LensSample.as
としました。

こうして貼ってみると長いですね。
いくつかクラスを定義してますが、ソレゾレ何のクラスかというと、

LensSampleはメインのクラスで、3つの入力欄と設定ボタンと画像とレンズが配置してあります。画像はFlashではシンボルでしたが、こちらはpng画像を読み込んでいます。設定ボタンがクリックされたらレンズにDisplacementMapFilterを再設定します。onEnterFrameでは、マウスカーソルが画面上にあったらその周辺の画像をレンズに設定しています。

BitmapDataUtilsはBitmapDataを操作するためのメソッドを定義しています。clipメソッドは指定したオブジェクトから、指定した座標/幅/高さでビットマップデータを切り出すメソッドです。

BitmapSpriteは内部にBitmapを一つ持つスプライトで、レンズに使っています。

LensFilterFactoryは、レンズの動作をするDisplacementMapFilterのファクトリです。createメソッドで、指定したサイズ/曲率半径/焦点距離を持つレンズのDisplacementMapFilterオブジェクトを生成します。やってることはFlash版と同じデス。

LabelInputは、ラベルと入力フィールドを持つスプライトです。サイズ/曲率半径/焦点距離の入力欄に使用しています。

LabelButtonは、ラベルのあるボタンです。ボタンといってもSpriteのbuttonModeをtrueにしてるだけなので、見栄えはショボイです。

といったカンジで、あまりActionScript3.0の利点をいかしたというカンジではないですね。というか利点はあまりわかってないのですケド。
スポンサーサイト

テーマ:プログラミング - ジャンル:コンピュータ

2007.03.25 | | Comments(0) | Trackback(0) | Flex2

コメント

コメントの投稿


秘密にする

«  | HOME |  »

プロフィール

HundredthMonkey

Author:HundredthMonkey
プログラマ。

ブロとも申請フォーム

この人とブロともになる

メールフォーム

名前:
メール:
件名:
本文:

ブログ内検索


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。