/**/

チュートリアル 3:
マトリックスにおける演算操作

このチュートリアルでは、Jitterのマトリックスに保存されているデータに対して簡単な演算操作を行う方法について説明します。マトリックスのセル、またはその中の個別のプレーンに対してスケーリング演算を行う場合の jit.op オブジェクトの使い方について見てみましょう。

・Jitter Tutorial フォルダにある 03jMathOperationsを開いて下さい。

このチュートリアルパッチは3つの部分に分かれていて、それぞれ jit.op オブジェクトで行うことができる簡単な数値演算の例を示しています。jit.opオブジェクトは、個別の数値に対してではなく、マトリックス全体のデータを一度に処理するような数値演算を行います。


マトリックスのすべてのセルに定数値を加算します

最初の例では、jit.matrix オブジェクトが jit.op に接続されていて、この jit.op の出力を jit.pwindowによって見ることができるようになっています。jit.op オブジェクトの右インレットに接続されているナンバーボックスの値を変えるたびに、bang メッセージによって jit.matrix が新しいマトリックスを送信するようになっています。アーギュメントからもわかるように、この jit.matrix オブジェクトは、プレーンが1で、データ型がchar(すなわち、データは0-255の範囲の値)の、4×3のマトリックスを生成しています。jit.pwindow オブジェクトは、このマトリックスをグレースケールの画像として視覚化しています。ナンバーボックスをドラッグすると、jit.pwindow のグレーレベルが黒(0) から白(255) まで変化します。

jit.matrix オブジェクトが、全てのセルの値が0にセットされた Jitter マトリックスを送信しているという事実を理解することは重要です。jit.opを経由せずに、jit.matrixjit.pwindow が直接接続されていた場合、黒い画像が現れ、jit.matrixに何回 bang メッセージを送信しても何も変化は起こらなかったでしょう。jit.opオブジェクトは、(ナンバーボックスで決定された)数値を、jit.matrix から jit.op に送られたJitterマトリックスの全てのセルに加算します。

@記号による操作

上の文で、jit.op オブジェクトが、受信したマトリックスの全てのセルに対して加算を行うと説明しました。この jit.op オブジェクトが(除算や乗算ではなく)加算を行った理由は、そのop アトリビュートの値にあります。この op アトリビュートとは、jit.opが受信したマトリックスに対して行う演算を定義するシンボル(またはシンボルのリスト、すぐ後で述べます)のことです。このケースでは、op アトリビュートが + という値にセットされているのがわかります。これは、左インレットにどんなマトリックスが送られて来た場合でも、単純に加算を行うということを意味し、右インレットの整数値をマトリックスの全てのセルに加算します。マトリックス全体に同じ値が加算されるので、この値をスカラと呼びます。(チュートリアル9では、 jit.opによって、同様に2つのJitterマトリックスを使った演算を可能にする方法ついて説明します)

重要な注:jit.opオブジェクトの右インレットでスカラの値を変化させても、新しいマトリックスは出力されません。ナンバーボックスと button オブジェクトを結ぶパッチコードが切断されていたとしたら、jit.pwindow オブジェクトの表示の変化はストップしてしまったでしょう。これは、次のような理由によります。多くのMaxオブジェクトと同様、ほとんどのJitterオブジェクトは左インレットに何らかの入力が行われた場合にだけデータを出力します。上のケースでは、ナンバーボックスの値を変化させるたびに、 jit.opオブジェクトは新しいスカラー値を保存します。その直後に button オブジェクトが jit.matrixbang メッセージを送り、新しい Jitter マトリックス(全ての値が0にセットされたもの)を jit.op オブジェクトの左インレットに送信させます。これが引き金となってマトリックスが出力され、それを見ることができたわけです。TraceメニューのEnableコマンドを選択し、Stepコマンド(Command+T)を使ってメッセージ命令を段階的に見ていくと、この様子を見ることができます。(トレース機能によってMaxメッセージをトレースする方法についての詳細は、Max4.0 Tutorial and Topics マニュアルの"デバッギング"の章を参照して下さい。)

スカラの値は jit.opval アトリビュートを使った定数として与えることもできます。例えば、受け取った Jitterマトリックスの全てのセルに対して常に134を加算したい場合、このようなオブジェクトを使ってナンバーボックスを省略することができます。


スカラ値をアトリビュートとして設定します。

同様に、与えられた jit.op オブジェクトによって行われる数値演算を変更しようとする場合には、op の後に関連した数学記号を続けたメッセージを左インレットに送ります。

データの複数のプレーンに対する演算

2つめの例では、jit.opを使って、入力されるマトリックスに値の加算を行う、より複雑な場合が示されています。


マトリックスの各プレーンに対して個別のスカラ値を使います

このパッチは最初のものとよく似ていますが、重要な違いは、ここでは 4つのプレーンを持つマトリックスを扱っているという点です。このことは、ここで使用されるマトリックスを生成する jit.matrix の最初のアーギュメントからわかります。jit.pwindow は Jitterマトリックスデータの 4つのプレーンを、アルファ、赤、緑、青という4つの別々なカラーチャンネルとして解釈し、これらをカラーで表示します。この例では、 jit.op オブジェクトの op アトリビュートは 4つのシンボルからなるリストを伴っています。各々のシンボルは入力されるマトリックスの1つのプレーンに対する数値演算を設定します。このパッチでは、最初の(アルファ)プレーンはそのまま通過させ、他のプレーンでは個々に数値を加算します。(このように、思いのままに演算子を混ぜ合わせたり、一致させたりすることができます。)

この jit.op オブジェクトの右インレットに接続されている pak オブジェクトは、4つの整数を受け取りリストにまとめます。pak とMaxの pack オブジェクトの唯一の違いは、(左インレットに新しい数値、またはbangメッセージが送られた時にだけ新しいリストを出力する pack オブジェクトに対し)pak では、どの数値が変更された場合でも新しいリストを出力する点です。pak によって生成されるリストの4つの数値は、 jit.op オブジェクトに入力されるマトリックスの個々のプレーンに対するスカラ値を決定します。上の例では、(opアトリビュート最初のアーギュメントが pass であるため)プレーン0には何も加算されません。プレーン1、2,、3では、それぞれ、161、26、254が加算されます。jit.pwindow オブジェクトは出力されるマトリックスのセルを美しいマゼンタをのような色として解釈します。(画面は単に一色に見えますが、実際にはマトリックスにはすべて同じ値をセットされた12個の異なるセルがあります。)

重要な注 :上の例で、jit.opオブジェクトの op アトリビュートに1つの値だけを与えた場合(そして、スカラとして1つの数値だけを使用した場合)、jit.opは、その数学演算子とスカラ値を入力されるマトリックスの全てのプレーンに適用します。

画像の色の変更

3つめの例では、jit.opオブジェクトを、すでに一連のデータが格納されているマトリックスに適用しています。


個々のプレーンにスカラを乗算します

importmovie colorbars.pictというメッセージボックスをクリックして下さい。jit.matrix オブジェクトに importmovie メッセージを送ると、オブジェクトによって格納される Jitter マトリックスに、ピクチャまたはQuictTimeムービーから画像の1フレームを読み込みます。この場合、ディスク上のピクチャはオブジェクトの持つマトリックスの大きさに合わせられます(このケースでは、320×240になります)。

button オブジェクトをクリックするとパッチの右側にある jit.pwindow オブジェクトには画像補正カラーバーが表示されます。このケースでは、jit.op オブジェクトには、算術演算子としてアルファプレーン用に pass が、他のプレーン用に * (乗算)がセットされています。4つのプレーンを持つ画像を操作しているため、個々のスカラーを4つの浮動小数によるリストを使ってセットします。1から3までのプレーンに1. を適用するとオリジナルの画像が示されます。


すべてのスカラが1の場合

スカラを0., 1., 0., 0., にセットすると次のような画像になります。


これは赤を表します。

カラーバーが格納されているマトリックスの(プレーン1を除く)すべてのプレーンには0が掛けられています。これによって、マトリックスのアルファ、青、緑のプレーンが取り除かれ、後には赤(プレーン1)だけが残ります。

jit.opのスカラとして(0., 0., 1., 0.5のような)中間の値を設定すると、カラーバーはまた違った画像に見えます。


かわいいでしょ?

この場合、アルファチャンネルは無視され、赤のチャンネルは0になります。青のプレーンの値はすべてもとの画像の半分になります。緑のチャンネル(プレーン2)はそのままです。

重要な注:jit.opの数学的なスカラには、浮動小数の数値で表されているもの、整数で表されているものがあります。これは、入力されるマトリックスの数値の型だけでなく、(op アトリビュートで定義され)関連づけられている演算子にも依存します。このチュートリアルの全ての例ではcharのマトリックスが使用されているため、これらに加算を行う場合、整数を用いることは道理にかなっています。(マトリックスのデータは常に 0 〜 255 の範囲の整数である必要があるため、すべての浮動小数点の数値は丸められてしまいます)。入力にfloat32によるマトリックスを使っている場合には、それに浮動小数点の数値を加算することは意味があるでしょう。同じように、charのマトリックスに浮動小数点スカラを掛け合わせることは道理にかなっています(240 * 0.5=120であり、これは整数です)。しかし、jit.op が出力するマトリックスはcharマトリックスのままなので(下記の注を参照)、依然として0〜255の間の数値だけを得ることができます。

スカラ値を変えていろいろ実験してみると、簡単にいくつかのカラーバーを消したり、隣り合ったバーを結合させたりすることができることがわかると思います。これはカラーバーが同じ範囲にある標準的な色の値に設定されているためです。1度に1つのチャンネルだけを見る(1つを除くすべてのプレーンを0に設定する)と、上に並んでいる7つのバーのうちの4本がカラーで示されます。

このチュートリアルでは + と * という演算子について説明してきました。しかし、実際にはjit.opは他にも非常に多くの数学演算を行うことができます。扱える演算子を網羅したリストはリファレンスページで、またはjit.opのヘルプファイルにあるp op_list というサブパッチをダブルクリックして見ることができます。

サイズの変更

jit.pwindowオブジェクトを生成すると、幅80ピクセル、高さ60ピクセルのウィンドウとしてMaxにあらわれます。このサイズは、Maxの他のインターフェイスオブジェクトと同じように、グローボックスを使って変更することができます。正確にサイズの変更を行いたい場合は、インスペクタを利用するか、size という語の後に、幅と高さをピクセル単位で表した値を続けたメッセージを送ります。


jit.pwindowのサイズを変更します

あるサイズ(ピクセル値)の jit.pwindow オブジェクトに異なるサイズ(セル数)のマトリックスを送った場合、jit.pwindow オブジェクトは、マトリックス全体を表示するために、入力されたマトリックスをスケーリング(拡大、縮小)します。非常に大きな jit.pwindow に非常に小さなマトリックスを送ると、ピクセレーション(全く同じ色のままの、画像の中の矩形の領域)として表示されます。また、小さな jit.pwinodow に大きなマトリックスを送ると、詳細な変化の度合いが失われて表示されます。

重要な注:上の例では、jit.matrixは320×240セルのサイズ(dim というリストで指定されています)、4つのプレーン(planecount が4)、char型のカラーバーを持っています。jit.op オブジェクト(そして、今後紹介するほとんどのJitterオブジェクト)はこの情報を認識し、マトリックス全体に演算を行い、同じ形のマトリックスを出力するために適応を行います。jit.matrix オブジェクトが違うサイズに変更されると、jit.op オブジェクトは即座にこれを認識し、再び適応を行います。jit.pwindow オブジェクトもまた入力されてくるマトリックスに適応しますが、少しだけ異なった方法をとります。入力されるマトリックスが自分自身の大きさより小さい場合、データを複製してすべてのピクセルを満たします(この結果は、前の段落で述べたピクセレーション効果になります)。入力されるマトリックスが自分自身の大きさより大きい場合、データの一部を無視せざるを得なくなり、可能なものだけを表示します。このため、チュートリアルパッチの jit.pwindow は、入力されてくるマトリックスのサイズ(セル数)とは決して一致しないにもかかわらず、jit.opオブジェクトのマトリックスのサイズに適応するためにベストを尽くします。最後の例の jit.pwindowでは、jit.opオブジェクトの出力するマトリックス全体を可能な限り表示しようとしますが、受け取った320×240のマトリックスを、自分自身が持つ160×120の表示領域にはめ込むために、行や列を1つおきに無視しなければなりません。

まとめ

jit.opオブジェクトによって、一度にJitterマトリックスのすべてのデータに対して数学的な演算を行うことができます。マトリックスのセルすべて、または個々のプレーンに対しての演算が可能です。jit.opが行う数学的な演算は、jit.opオブジェクトの op アトリビュートによって決まります。これは、オブジェクトに@op [演算子] というアトリビュートアーギュメントをあらかじめ設定しておくか、op [演算子] というメッセージを左インレットに送ることによって設定できます。複数のプレーン(マルチプレーン)を持つマトリックス(カラー画像、ビデオのようなもの)では、演算子のリスト(例えば、op pass * * *)を送ることによって、個々のプレーンに対しての演算方法を指定することができ、それぞれ異なったスカラ値を設定できます。チュートリアル9では、単純なスカラの代りに2つめのJitterマトリックスを使用する方法について説明します。

jit.pwindowのサイズは size [幅] [高さ] というメッセージで設定できます。jit.pwindowは、受け取ったすべてのマトリックスのサイズに最大限に適応しようとします。入力されるマトリックスのサイズが jit.pwindow 自身のサイズより小さい場合は、データを複製し、大きい場合はいくつかのデータを無視します。たいていのJitterオブジェクトは、受け取ったマトリックスの大きさ、型、プレーン数に最大限に適応しようとします。jit.op の場合には、それ自身の大きさは指定されないので、入力されてくるマトリックスの属性に適応します。