A Day in the Life

2007-03-14

ConvolutionFilter Interface

http://lab.rails2u.com/swf/convolution_filter_interface

ConvolutionFilter での matrix の適用値がどれぐらいだとどんな効果になるのか解らなかったので、感覚でつかむために適当なインターフェイス用意してみた。flex2 はこういうとき超便利だなぁ。fcsh 使ってもコンパイルが遅すぎるけど…。

以下ソース

xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" initialize="init()" backgroundColor="#ffffff">
  <mx:Script>
    CDATA[
    private function init():void {
        setImage();
        applyFilter();
    }

    private function setImage():void {
        image.source = imageUrl.text;
    }

    private function applyFilter():void {
        var matrixX:Number = 3;
        var matrixY:Number = 3;
        var divisor:Number = 9;
        var matrix:Array = [
            int(m1.value), int(m2.value), int(m3.value),
            int(m4.value), int(m5.value), int(m6.value),
            int(m7.value), int(m8.value), int(m9.value)
        ];
        var filter:BitmapFilter = new ConvolutionFilter(matrixX, matrixY, matrix, divisor);
        var filters:Array = new Array();
        filters.push(filter);
        image.filters = filters;
    }

    ]]>
  mx:Script>
    <mx:VBox width="60%" horizontalAlign="center">
      <mx:Panel id="mainPanel" title="ConvolutionFilterInterface" styleName="mainPanel" width="100%">
        <mx:Box width="100%" horizontalAlign="center" paddingTop="15">
            <mx:Image id="image"/>
        mx:Box>
        <mx:Form width="100%" defaultButton="{Submit}">
            <mx:Box width="100%" horizontalAlign="center">
              <mx:Label text="ConvolutionFilter 3x3 Matrix"/>
              <mx:HBox>
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m1" width="75" value="5" />
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m2" width="75" value="-1" />
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m3" width="75" value="20" />
              mx:HBox>
              <mx:HBox>
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m4" width="75" value="1" />
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m5" width="75" value="-20" />
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m6" width="75" value="-1" />
              mx:HBox>
              <mx:HBox>
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m7" width="75" value="5" />
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m8" width="75" value="1" />
                <mx:NumericStepper minimum="-1000" change="applyFilter();" maximum="1000" id="m9" width="75" value="5" />
              mx:HBox>
            mx:Box>
          <mx:Box textAlign="center" width="100%" horizontalAlign="center">
            <mx:Button id="Submit" label="apply" click="applyFilter();" />
          mx:Box>
        mx:Form>
        <mx:Form width="100%" defaultButton="{imageSubmit}">
          <mx:TextInput id="imageUrl" text="http://f.hatena.ne.jp/images/fotolife/s/secondlife/20070312/20070312065825.jpg" width="100%"/>
          <mx:Button id="imageSubmit" label="set image" click="setImage();" />
        mx:Form>
      mx:Panel>
    mx:VBox>
mx:Application>

flex2/as3 の Embed/Binding メモ

画像や音をコンパイル時に組み込んでくれるよ。

[Embed(source="example.jpg")]
    [Bindable]
    public var ExampleImage:Class;

とか class の内側に書き、クラスから呼び出す。ファイルパスは書き込んだソースからの相対パス、もしくは絶対パス(試してないけど)で。

で、Bitmap として使いたかったら

var exampleBitmap:Bitmap = Bitmap(new ExampleImage);

とかすれば扱える。mx コンポーネントを import しなくても使えた。これは flex2 の機能なのか mxmlc の機能なのか?[jitensya] な syntax って as3 にあったっけ?flex_devguide.pdf を検索したけどそれっぽい説明がなかったので追ってみる。

まずコンパイラの設定を見る。flex-config.xml にメタデータとして定義されてる。

Bindable
    Managed
    ChangeEvent
    NonCommittingChangeEvent
    Transient

へぇ(よくわかんないけど)。というわけで -keep オプション付きでコンパイルしてみてジェネレートされる *.as ファイルを見てみる。

package
{

import mx.core.BitmapAsset;

[ExcludeClass]
[Embed(exportSymbol="ColorMatrixFilterExample_ExampleImage", _resolvedSource="/path/to/example.jpg", source=
"example.jpg", _file="/path/to/ColorMatrixFilterExample.as", _column="10", _line="13")]

public class ColorMatrixFilterExample_ExampleImage extends mx.core.BitmapAsset
{
    public function ColorMatrixFilterExample_ExampleImage()
    {
            super();
    }

}

}

BitmapAsset の子クラスとして定義されてる。よしなに BitmapAsset/SoundAsset/FlexMovieClip なんかを生成してくれるのかな。

Binding で定義したクラスは BindableProperty なクラスに setter/getter でまとめられている。また mx.utils.ObjectProxy 周り使って、更新があったらイベント起こせるようになってるのかな。そのため Binding オブジェクトの値の変更があったらすぐに mxml での表示を変更できると。へぇ。

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import mx.core.IPropertyChangeNotifier;
import mx.events.PropertyChangeEvent;
import mx.utils.ObjectProxy;
import mx.utils.UIDUtil;

import Class;

class BindableProperty
{
        /**
         * generated bindable wrapper for property ExampleImage (public)
         * - generated setter
         * - generated getter
         * - original public var 'ExampleImage' moved to '_54677041ExampleImage'
         */

    [Bindable(event="propertyChange")]
    public function get ExampleImage():Class
    {
        return this._54677041ExampleImage;
    }

    public function set ExampleImage(value:Class):void
    {
        var oldValue:Object = this._54677041ExampleImage;
        if (oldValue !== value)
        {
                        this._54677041ExampleImage = value;
            dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent(this, "ExampleImage", oldValue, value));
        }
    }
}

flex2[Embed][Bindable]

便利だ…

カンコーヒ

フタを空けた後にカンをふって思いっきりこぼれた。人生二回目。もうだめかもしれんね。

ファン・サーヴィス [bitter]

届いた、そうだamazonさんで予約してたんだ忘れてたタワレコにしておけばよかった><

雲一つ無い青空

最近建物の凹凸があるとあそこのビルはジャンプで上れるよなーとか思ってしまう(riot act の影響)。

サンディーサンディー

http://rails2u.com/misc/swf/070313.swf

むつかしいのぅ

記事の一覧 >