/**/

チュートリアル 12:
カラールックアップテーブル

このチュートリアルでは、カラールックアップテーブルを使ってJitterマトリックスの中のデータをリマップ(再配置)する方法について調べます。さらに、マトリックスとしてルックアップテーブルを生成するための違った方法についても見ていきます。

ルックアップテーブルは単なる数値の配列ですが、入力される数値は配列のアドレス(位置)として扱われます。そしてテーブルはそのアドレスに格納された値を出力します。どのような関数でもルックアップテーブルとして使用することができます(実際、グラフは各々のxの値(アドレス)に対応するyの値(出力)を持っています)。通常、funbufftable といった Max オブジェクト、そしてMSPの buffer~ オブジェクトがルックアップテーブルとして使用される対象となります。このチュートリアルでは、これとほとんど同じような方法で Jitter マトリックスを使用します。

・Jitter tutorialフォルダの12jColorLookUp.patというチュートリアルパッチを開いて下さい。

チュートリアルパッチには2つの新しいオブジェクトがあります。jit.charmap オブジェクトは、ルックアップテーブルマトリックスによって、入力されたセルの値を新しい出力値にマップします。そして、 jit.gradient オブジェクトは色のグラディエントを生成します。


イメージの読み込み

パッチの左上には、2つの異なったファイルを読み込むことができる jit.qt.movie オブジェクトがあります。このオブジェクトは(loadbangによって)初期化され、colorwheel.pct を読み込みます。また、read rain.mov と書かれたメッセージボックスをクリックしてrain.movというムービーを読み込むこともできます。このチュートリアルを通して、2つのイメージソースを交替させても構いません。

・パッチの上部にある toggle ボックスをクリックして metro オブジェクトをスタートさせて下さい。パッチの上と下の両方の jit.pwindow にカラーホイールが現れるのがわかると思います。加えて、パッチの下部にある3つめの(矩形の)jit.pwindowにグラディエントが現れるのがわかるでしょう。


jit.charmapの出力とルックアップテーブルマトリックス

パッチの下部には、このチュートリアルでイメージのセルの値をリマップするために使う jit.charmap オブジェクトがあります。このオブジェクトは2つのインレットを持っていて、左インレットはパッチの上部にある jit.qt.movie オブジェクトと接続されています。右インレットは、1次元、4プレーンのchar型 jit.matrixと接続されていますが、このマトリックスは名前( colortable )を持ち、256セルの幅を持っています。これが、jit.charmap が左のマトリックスのセルの色の値をリマップするために用いるルックアップテーブルです。ctable という名前を持ったreceiveオブジェクト( r と略されています)はパッチの他の場所からデータを受け取り jit.matrix に送ります。例えば、パッチの上部で toggle ボックスをオンにするとbang メッセージが jit.matrix に送られ、それによって jit.matrix はマトリックスメッセージ(jit_matrixcolortable)を jit.pwindowjit.charmap の右インレットの双方に送ります。

ルックアップテーブル

ルックアップテーブル(多くの場合、伝達関数と呼ばれます)は、入力された数値がテーブルのインデックスとして「参照」される数値の配列です。このインデックス(あるいはアドレス、または位置)に格納された数値が取り出され、もとの数値と置き換えられます。jit.charmap オブジェクトは、右インレットに送られたマトリックスをルックアップテーブルとして、(左インレットから)入力されたマトリックスのすべてのセルのすべてのプレーンの値を、ルックアップテーブルの該当するインデックスの値に置き換えます。

例えば、jit.charmapに送ったマトリックスが、4つのプレーンに100 50 35 20 という値を持つセルを含んでいると仮定しましょう。すると、このオブジェクトはルックアップテーブルマトリックスの該当の位置で各々のプレーンを個別に探して、その値に置き換えます。ルックアップテーブルが最初のプレーンのセル100に値73を持ち、2番目のプレーンのセル50に値25、3番目のプレーンのセル35に値0、4番目のプレーンのセル20に値203を持っていたとすると、出力セルは73 25 0 203 になります。

jit.charmap オブジェクトのためのルックアップテーブルは、1次元マトリックスで256のセルを持ち、リマップしようとするマトリックスと同じ数のプレーンを持っていなければなりません。これは、charマトリックスが取り得る値の範囲が0〜255であるため、ルックアップテーブルのすべての範囲をカバーするには256個の数値が必要となるためです。

ルックアップテーブルの生成

パッチの右上横には3つの multiSlider オブジェクトがあり、これを使ってルックアップテーブルマトリックス colortable のプレーン1〜3の 伝達関数 をデザインすることができます。


multiSliderからの値でルックアップテーブルマトリックスを埋めます

multiSliderオブジェクト(0〜255のレンジの整数のスライダを256個持っています)は、その下の jit.fill オブジェクトにリストを送ります。3つの jit.fill オブジェクトはそれぞれ、すでにマトリックス colortable のプレーン1 〜 3(すなわち、赤、緑、青)に格納されている値を multiSlider オブジェクトからの値に置き換えます。(チュートリアル11を参照)マトリックスが新しい値によって編集されると、jit.fillオブジェクトは bang メッセージを送信し、これが(sendオブジェクトによって)jit.charmapの右インレットに接続された、jit.matrixに送信されます。このチュートリアルではプレーン0は無視していますが、これは4プレーンの Jitter マトリックスをビデオとして扱っている場合、プレーン0はアルファ値だけを含んでいるためです。

このパッチのjit.matrixjit.fillオブジェクトは、同じ名前(colortable)を共有しています。その結果、2つのオブジェクトの読み込み、書き出しが同じマトリックスに対して行われるため、片方のオブジェクト(jit.fill)によって生成されたデータは、他のオブジェクト(jit.matrix)によって、2つの別々のマトリックスの間でコピーする必要なく、読み込むことができます。これは、多くのMSPオブジェクト(例えば、 peek~play~groove~)が1つのbuffer~ に格納されたサンプルデータを共有できることと同様です。名前を持ったマトリックスの使用についてのより詳しい情報は、チュートリアル11、16、17を参照して下さい。

multiSliderオブジェクトの内側でフリーハンドで何か描いて下さい。これがルックアップテーブル(小さな jit.pwindow オブジェクト)と jit.qt.movie からの出力イメージの双方にどんな影響を与えるかを観察して下さい。忘れずに2つのイメージソースを交互に試してみて下さい。

プレーンを y = x という伝達関数(すなわち、全ての値を全く変化させないような直線的に増加する線)にリセットしたい場合は、該当の multiSlider オブジェクトの上にある button をクリックして下さい。p clear というサブパッチャーは multiSlider オブジェクトを Uzi によって初期化します。

重要な注:多くのMaxオブジェクトと同様、Jitterオブジェクトでは、あるインレットに格納されているマトリックスは、他のインレットに新しいマトリックスが入力されても保持され続けます。したがって、このパッチの metro オブジェクトはjit.qt.movieオブジェクトにトリガを与えるためだけに必要なものです。jit.charmap へのルックアップテーブルを持っている jit.matrix オブジェクトは、実際に格納されているデータが変化した場合にのみ、その値を jit.charmap に出力する必要があります。

次に示すのはいくつかのルックアップテーブルとその結果です。


multiSliderオブジェクトの設定と、その結果生じるカラー
ルックアップテーブル、および出力されるカラーホイール

最初の例では、緑の伝達関数がノーマルな状態であるのに対し、赤と青の伝達関数はほぼ反転されています。結果として、入力イメージの赤と青の高い値は低い値をもたらし、低い値は高い値をもたらします。白かったカラーホイールの背景がここでは緑に見えるのはこのためです(値が0 255 255 255であったセルは、0 0 255 0 にマップされます)。

2番目の例では、緑のプレーンは完全に0(伝達関数は入力値の全ての範囲で0に設定されています)です。赤と青のプレーンもスレッショルドまでは0に設定され、スレッショルド点から急勾配を描いています(赤は青よりも急勾配になっています)。結果として、カラーホイールのほとんどが黒(特に「緑」の領域)になります。赤のプレーンは非常に高い値の所(すなわち、カラーホイールの背景のマゼンタ)でのみ見ることができます。

3番目の例では、赤のプレーンはノーマルな状態でマップされています。緑のプレーンはパラボラ状の形をしているため、両端の値は高く、中間の明度の部分は低くマップされています。青のプレーンでは中間の明度の領域で0にされていますが、その他の部分はノーマルです。このような非直線性によって、赤い「断層線」がカラーホイールの上部から右下にかけて走っています。

このようにマトリックスのセルの値をリマップする方法は無限にあります。それでは、より緻密な方法でカラーの値をリマップすることができる他のオブジェクトを調べてみましょう。

jit.gradientオブジェクト

チュートリアルパッチの右下部分には jit.gradient オブジェクトによってルックアップテーブルを生成する方法が示されています。


jit.gradient オブジェクトの使用

jit.gradientオブジェクトは、2つの指定されたセル値の間を滑らかに変化する1次元のcharマトリックスを生成します。startend というアトリビュートはこれらのセル値を指定するリストです。例えば、start アトリビュートが 0 0 0 0end アトリビュートが 0 0.5 1.0 0.5 の場合、黒(マトリックスのセル0)からうす緑(マトリックスの最後のセル)までのグラディエントを生成します。ここでは、jit.gradient オブジェクトに適切なアーギュメントを与えて256個のセルの長さを生成するようにしています。そのため、変化が与えられると colortable という jit.matrix に値を格納することができます。jit.gradient がアトリビュートのリストとして浮動小数点数を受け取り、それによって char の値を指定していることに注意してください(すなわち、アトリビュートの値1.0は char の値255を指定します)。

このアトリビュートは、Max の swatch オブジェクトの出力するRGBリストを使い、それをARGB の float の値に変換することによってフォーマットされています。アトリビュートが jit.gradient オブジェクトに送られた後、jit.gradient trigger オブジェクトから bang メッセージを送信され、それによってパッチの左側にある jit.matrix にマトリックスを送信します。

swatch オブジェクトでいくつかの色を選んで下さい。start および end アトリビュートはルックアップテーブルの境界値を指定するため、入力イメージの値は、2つの色の間をモーフィングするデュオトーンのようになります。パッチの上部にある multiSliderjit.gradientオブジェクトによって生成された正確なルックアップテーブルを反映します。

 


ルックアップテーブルとしてのカラーグラディエントの使用

最初の例では、イメージは反転されています。ルックアップテーブルの start は白(start 0 1.0 1.0 1.0)に、end は黒(end 0. 0. 0. 0.)に指定されているため、結果として入力値 0 は255にマップされ、逆も同様です(y = 255 - x)。

2番目と3番目の例では、カラーホイールのスペクトルを赤とオレンジ(例2)、オリーブとシアン(例3)のそれぞれの間にリマップするデュオトーン・グラディエントになります。カラーホイールの異なる場所にある元の色によって、どのようにグラディエントカーブが急激になったり、緩やかになったりしているかに注意して下さい。

jit.gradient オブジェクトの3つめのアトリビュートは cheby アトリビュートです。これはマトリックスの startend の値の間のモーフィングを行う際のカーブを、次のような形に指定します。chebyアトリビュートはアーギュメントとして浮動小数点数のリストを取ります。これらのアーギュメントはチェビシェフ多項式(後述)の異なる次数の振幅値になります。これらの特殊な関数曲線はルックアップテーブルとして使用される場合に様々な効果を作り出します。

チュートリアルパッチの cheby アトリビュートを設定する multiSliderによって、関係するチェビシェフ多項式曲線の最初の8つの振幅値を指定することができます。これは次のような形になります。(黒から白への変化としてみた場合)


チェビシェフ次数1〜4(上の行)と5〜8(下の行)を使って生成されたグラディエント

技術的な詳細:チェビシェフ多項式は、デジタルシンセシスアルゴリズムでオーディオシグナルのウェーブシェイピングを行う場合の伝達関数として一般的に用いられます。(これらは、サイン状の波形を、異なる次数の振幅値に等しい倍音スペクトルを持つように歪めるという特殊な性質を持っています。MSPの lookup~ オブジェクトは buffer~ に読込まれた関数と共に使用することができ、それによって、オーディオシグナル処理においてこのチュートリアルでイメージに対して行ったものと同じ処理をすることができます。詳しくはMSPマニュアルのチュートリアル12「シンセシス:ウェーブシェイピング」を参照して下さい。

・グラディエントの start end をリセットしてください(これらの上にあるメッセージボックスをクリックしてください)。そして、cheby アトリビュートをコントロールする multiSlider を徐々に変化させて下さい。カラーホイールの色が様々な領域で消えたり、現れたりするようすを観察して下さい。

jit.gradient オブジェクトの cheby アトリビュートを使うと、グラディエントの start end が黒と白のままでも、いくつかの非常に面白い色を歪める効果(ワープ効果)を得ることができます。次のいくつかの例は、ムービークリップ rain.mov に適用したものです。


rainに適用された、カラースペクトル上の様なグラディエントカーブによるイフェクト

左側のイメージは rain ムービーの未処理の静止画です。中央のイメージは2次のチェビシェフ多項式を使って生成したグラディエントの場合に、カラースペクトルにどのような変化が起きるかという例です(ここでは、イメージの最も暗い領域はカラースペクトルの中央にあります)。右側のイメージはより複雑なグラディエントを示しています。ここではカラースペクトルは多くの山と谷を持っています。

・パッチの上部にある multiSlider オブジェクトはルックアップテーブルの正確な状態を反映しています( jit.gradient オブジェクトで生成されたマトリックスは、p showit サブパッチの中にある jit.iter オブジェクトへ送られ、ここで数値がグループ化されてmultiSlider オブジェクトに状態をセットします)。グラディエントを生成し、さらに手動で multiSlider オブジェクトを変化させて、ルックアップテーブルを加工してみて下さい。このようにより複雑なルックアップテーブルを作るための出発点として jit.gradient オブジェクトを使用することも可能です。

まとめ

jit.charmap オブジェクトを使って、char型のJitterマトリックスのセルの値を、マップすることができます。jit.charmap の右インレットは256個のセルによるマトリックスを受け取り、これによって入力されるマトリックスに適用するルックアップテーブル(または、伝達関数)を定義します。ルックアップテーブルを定義するにはいくつかの方法があります。その中には、jit.fillを用いてMaxのリストから生成する方法、あるいは jit.gradient オブジェクトを使って、最初(start)と最後(end)のセル値を指定し、cheby アトリビュートによってカーブの形状を指定したカラーグラディエントを生成する方法などがあります。