チュートリアル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.matirxに送られ、それによってjit.matrixはマトリクスメッセージ(jit_matrix colortable)をjit.pwindowjitcharmapの右インレットの双方に送ります。


ルックアップテーブル

ルックアップテーブル(これはしばしば伝達関数と呼ばれます)は、入力される数値をテーブルのインデックスとして「参照」される数値の配列です。このインデックス(あるいはアドレス、または位置)に格納された数値が取り出され、もとの数値と置き換えられます。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オブジェクトにリストを送ります。これらのオブジェクトはその時点でマトリクスcolortable のプレーン1〜3(すなわち、赤、緑、青)に格納されている値を、multiSliderオブジェクトからの値に置き換えます。(チュートリアル11を参照)マトリクスが新しい値によって編集されると、jit.fillオブジェクトはbangメッセージを送信し、これがjit.charmapの右インレットに接続された、パッチの右側(訳注:左側が正しい?)にあるjit.matrixに(sendオブジェクトによって)送られます。このチュートリアルではプレーン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 というサブパッチャーはmulitSliderオブジェクトを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マトリクスを生成します。startとendというアトリビュートはこれらのセル値を指定するリストです。例えば、startアトリビュートが0 0 0 0 でendアトリビュートが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.gradienttriggerオブジェクトから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アトリビュートです。これはマトリクスのstartとendの値の間のモーフィングを行う際のカーブを、次のような形に指定します。chebyアトリビュートはアーギュメントとして浮動小数のリストを取ります。これらのアーギュメントはチェビシェフ多項式(後述)の異なる次数の振幅値になります。これらの特殊な関数曲線はルックアップテーブルとして使用される場合に様々な効果を作り出します。チュートリアルパッチのchebyアトリビュートを設定する multiSlider
によって、関係するチェビシェフ多項式曲線の最初の8つの振幅値を指定することができます。これは次のような形になります。(黒から白への変化としてみた場合)


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

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

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

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



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

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

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


まとめ

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