チュートリアル6

カラーレベルの調整


このチュートリアルでは、前の章での色の解説に関してより詳しく見ていきます。さらに、マトリクスのARGBカラープレーンの加工のために特別に設計された、jit.scalebiasオブジェクトを紹介したいと思います。

ここでの「スケール」という語は、特定の係数の値によるスケーリング処理、すなわち、それを与えられた値に掛けることを指します。「バイアス」という語は値に一定の値を加えてオフセットすることを指します。乗算と加算の処理を組み合わせることによって、入力された値を出力する値に線形にマッピング(写像)することができます。

jit.scalebiasは画像のARGBカラー情報の加工に関与するため、4プレーンのcharデータ型マトリクスだけを取り扱います(チュートリアル5のARGBカラーとcharデータに関する解説を参照して下さい)。


charデータでの計算

前の章で述べたように、8ビットのcharデータは0から255までの整数値、または0から1までの小数値を表すことができます。一例として、チュートリアル2ではjit.printオブジェクトがcharデータを0〜255までの整数値として示しているのを見ました。しかし、char型の値をマトリクス内で(そのアトリビュートの1つを変更することによって)加工しようとする多くの場合、Jitterオブジェクトはアトリビュートの値としてfloatを受け取ることを予想しています。これは、ちょっとした混乱を招く恐れがあるので、このチュートリアルパッチで実例を用意しました。

・Jitter Tutorial フォルダにある06jAdjustColorLevels.patというチュートリアルパッチを開いて下さい。パッチの中程にあるpatcher explain_scalebias オブジェクトをクリックして、サブパッチ[explain_scalebias] の内容を見て下さい。


charデータにおけるfloatによる計算の説明

上の例では、1つのセルしか持たない、4プレーンのcharデータという、非常に小さなマトリクスを作ってみました。これによって、マトリクスの1つの数値に起こることに対して焦点を絞ることができると思います。プレーン2(緑のプレーン)に値100がセットされているのがわかると思います。例の左側では、この整数値を0と1の間の小数で表す方法がわかるようになっています。:このケースでは0〜1の間の100/255 なので、0.392です。

jit.scalebiasオブジェクトはscaleアトリビュートで指定された特定の値で乗算し、その後、biasアトリビュートで指定された特定の値を加算します。jit.scalebiasによってマトリクスが変更される時には、全ての値は計算のためにfloatとして扱われ、その後charデータとしてマトリクスにリストア(再び格納)されます。

ここでは、scale および bias アトリビュートは scale 2.0 および bias 0.2 メッセージによってセットされています。この場合、スケーリング係数(掛け合わせる値)は2.0、バイアス(その後に加算されるオフセット)は0.2になります。そこで、jit.scalebiasの内部で何が行われているかを理解するためには、緑の値0.392が2.0倍されて、0.2を加えられ、結果は0.984になると考える必要があります。jit.iterオブジェクトは各セル(このマトリクスには1つのセルしかありませんが)の各々のプレーンの値を示してくれるので、その(charとしてマトリクスに格納された時の)値が251(または、0から1にスケールされれば0.981)であるのを見ることができます。

(ちょっとした頭の体操ですが、上の例でjit.scalebiasが赤と青のプレーンをどんな値にしているか計算できますか?もともとのマトリクスのこれらのプレーンは0ですから、結果としてのマトリクスの値は0掛ける2.0足す0.2イコール0.2 となります。これは0から255 の値に換算すると51です。このため、下のjit.pwindowオブジェクトに表示されるRGBの値は 51 251 51 になります。)


charデータの計算の例をもう少し

もし、前の説明が非常に明確に感じられたとしたら、これ以降の補足的な例は飛ばしてしまいたいかも知れませんが、charデータによる演算が(特に、jit.scalebiasの場合)どのような結果をもたらすかについて確信が持てないという場合のために、いくつかの例をあげてみます。

・presetオブジェクトのプリセットを、左から右へ順番に1つずつクリックして下さい。以下のパラグラフで、各々のプリセット例について説明します。

1. もともとのマトリクスの緑のプレーンの値は255です(これは0〜1に換算すると1.0になります)。jit.scalebiasオブジェクトはこれに0.5を掛けますから、結果は127.5 という中間の値になります。しかし、char として格納される場合、jit.scalebiasは小数部を丸める(切り捨てる)ので、127という値が格納されます。

このことは、確かに不正確な結果を生みます(期待される値が0.5であるのに対して、0〜255のスケールにおける127は、0〜1のスケールでは0.498になります)。しかし、これは8ビットのcharデータで可能な最善の値です。これより細かい精度が必要な場合、charデータは不向きです。代わりにlong、float32、float64のデータ型によるマトリクスを用い、jit.op @* 及び jit.op @+ オブジェクトで演算を行う必要があります。

2. もともとの値は100で、これを2倍(スケーリング係数2.0)し、期待される答え200になります。この場合、精度によるロスはありません。

3. もともとの値は100(0.392)です。係数1.0を掛けますから、値はそのままで変化しません。そして-0.2 をそれに加えます(これは、0.2を引くことになります)。結果は49(0.192)になります。

4. 0.392に2.0を掛け、0.2を足します。0〜255のスケールでは251です。

5. この例と次の例では、乗算、及び加算が行われた結果が8ビットcharの範囲を超えた場合にどうなるかを示しています。jit.scalebiasは単に結果をcharの最大値または最小値にクリップ(制限)します。ここでは、0.392に4.0を掛けて、1.568 (すなわち、100掛ける4で400)になるので、結果は可能な最大値である255にセットされます。

6. 逆方向の場合、0.392から0.5 を引くと-0.108なので、結果は0にセットされます。

7. これまでに説明した誤差や限界は、結果をcharとして格納する時点でのみ生じるということは注目すべき点です。その時点まで、値は内部的にはfloatとして計算されるので、精度は保たれています。内部的には、たとえ乗算の結果が0〜1の範囲を超える値になっても制限は起こらず、加算処理によって値を範囲内にもどすことができます。ここでは、0.392を3.0 倍(=1.176)してから、0.5を引いて、結果は0.676 になります。しかし、この値がcharとして格納される際に、小さな誤差が生じます。0.676 は0〜255のスケールでは172.38 になりますが、小数部は切り捨てられ、172(すなわち0.675)が格納されます。

8. 変更を加えないためには、スケーリング係数は1 、バイアスは0 でなければなりません。

・jit.scalebiasについて、また8ビットcharデータがもたらす結果について十分な理解が得られるまで、他の値で試してみて下さい。終わったら、[explain_scalebias] ウィンドウを閉じて下さい。


画像のカラーレベル調整

jit.scalebias をカラー画像に対して使ってみましょう。チュートリアルパッチの左上隅には、おなじみの組み合わせがあります。;jit.qt.movieオブジェクトとムービーを読込むためのメッセージボックス、jit.qt.movieオブジェクトからjit_matrixメッセージを出力させるトリガとなるmetroオブジェクトです。このパッチでは、jit.scalebiasの持つ乗算と加算の機能を使ってマトリクスを加工します。


ピクチャまたはムービーを読込みます

・read chillis.jpgメッセージボックスをクリックして、JPEG画像を読込んで下さい。jit.qt.movieオブジェクトにビデオではなく静止画増を読込んでいる点に注意して下さい。QuickTimeは、PICT、またはJPEG形式を含む、様々な広範囲にわたるメディア形式を取り扱うことができます。jit.qt.movieオブジェクトは静止画像を1フレームの長さのビデオのように取り扱います。

jit.qt.movieの出力はjit.scalebiasへ送られて処理され、jit.pwindowで表示されます。(今の所、jit.matrixオブジェクトはまだ気にしないで下さい。この使い方に関しては、この章の後の方で説明します。)scale と bias の値はjit.scalebiasオブジェクトのscale及びbiasアトリビュートを変更することによって変えることができます。

・トグルをクリックして、metroオブジェクトをスタートさせて下さい。scale $1 メッセージボックスの上のナンバーボックスをドラッグして、scaleアトリビュートの値を1.25まで大きくして下さい。


画像のブライトネス(明るさ)を強めます;scale の値を大きくすると、より強められます

これによって、画像の4つのプレーン全ての0でない値は係数1.25を掛けられます(25%の増加)。乗算を行うと、より大きな値は、より小さな値に比べて増加する量が大きいことに注意して下さい。例えば、元のマトリクスのあるセルの赤の値が200だとした場合、これは250(結果として50の増加)になりますが、同じセルの青の値が30だったとしたら、これは37(結果として7の増加)にしかなりません。

・scaleアトリビュートを20のような非常に大きな値にして下さい。値が13以上になると、元のマトリクスは255 という最大値の方へ押しやられ(そして、非常に小さな値でさえ可視レベルまで押し上げられ)て、人工的な「露出過度」状態を作ります。

・scaleアトリビュートを0と1の間まで小さくして下さい。予想したように、これは画像を暗くします。scaleの値が0以下になると、すべての値は0にセットされます。

・scaleアトリビュートを1に戻して下さい。今度はbiasアトリビュートを調整してみましょう。これはマトリクスのすべての値に一定の量を加算します。正の値は画像を明るくし、負の値は暗くします。


一定の量によって、すべての値のレベルを増加(減少)させます

・次のような2つの極端なscaleとbiasの設定を試してみたいと思われるかもしれません。scaleの値を40に、biasの値を-20に設定して下さい。これによってほとんどすべての値は255または0に押しやられ、白と黒以外にはわずかな色だけが残ります。今度は、scaleの値を-1に、biasの値を1に設定してみて下さい。これによって、大きい値はすべて小さく、また小さな値はすべて大きくなるので、色彩の設定(カラースキーム)を反転させる効果があります。scaleの値をさらに減少させると(-4、あるいは-8など)同様な反転が起こりますが、もともとの小さな値だけが強調され、biasの正の値によって0〜1の範囲に押し上げられます。


各プレーンごとの調整

jit.scalebiasオブジェクトでは、各プレーンのレベルを個別に調整することができます。これには、ascale、abias、rscale、rbias等のアトリビュートを使います。

・scaleの値を1に、biasの値を0に戻して下さい。そして、適当なアトリビュートに新しい値を与えて各々のカラープレーンを個別に調整する実験を行ってみて下さい。


各カラープレーンのレベルを調整します

3つのカラープレーンすべてのスケーリングの調整を一度に行えるようなコントローラを使って、処理を多少「インタラクティブ」にしてみました。swatchオブジェクトをクリック、またはドラッグすると、オブジェクトはマウスが置かれた場所のRGB値を示す3つの要素からなるリストを送り出します。これらの値は0〜255のスケール上で表されているので、vexprオブジェクトを使って、リストの値すべてを0〜1の範囲に変換します。そして、unpackによってリストを3つのfloatに分割し、その値を使ってjit.scalebias オブジェクトのrscale、gscale、bscaleアトリビュートを変更します。


swatchからの値はjit.scalebiasオブジェクトのアトリビュートとして使用されます

swatchオブジェクトをドラッグして、同時にRGBプレーンのスケールを行って下さい。(これは、0〜1の範囲のスケーリング係数を出力するので、実際にはすべてのレベルを減らすことになります。このため結果としての画像は通常いくぶん暗いものになります。)

・これらすべての操作は様々な画像で試してみることができます。colorswatch.pictやwhiee.mov(あるいは何か他の画像)のような、別のカラフルな画像を読込んでカラーレベル調整の実験を行って下さい。


マトリクスのプレーン再割当て

前のチュートリアルでは、jit.unpackおよびjit.packオブジェクトを用いてマトリクスのプレーンの再割当てを行いました。同じ事を行う別の方法があります。これには、jit.matrixオブジェクトのplanemap アトリビュートを使います。この例では、planemapアトリビュートを説明するために、jit.qt.movie オブジェクトから出力されるマトリクスをjit.matrixに通しています。


jit.matrixを通過する際に、マトリクスのプレーンの再割当てを行うことができます

jit.matrixオブジェクトのplanemapアトリビュートは、入力されるマトリクスのどのプレーンでも「マップ」(再割当て)することができます。planemapという語の後に、マトリクスの持つプレーン数と同じ数だけの数値を続けます(この場合は4つです)。リストの各プレーンは出力するプレーンを意味し(最初のプレーンは出力のプレーン0を、2番目のプレーンは出力のプレーン1を意味しています。以下同様です。)、その値は、再割当ての対象である入力されてくるプレーンを表しています。デフォルトでは、planemapの値は、0 1 2 3(等)となっているので、入力されるマトリクスの各プレーンは出力されるマトリクスの同じプレーンに割当てられます。しかし、この割当てを好きなように変えることができます。例えば、jit.matrixオブジェクトにplanemap 0 3 2 1 というメッセージを送った場合、入力のプレーン3を出力のプレーン1に(値3がリストの出力プレーン1の場所にあるため)、入力のプレーン1を出力のプレーン3に割当てます。実際には、画像の赤と青のカラープレーンを入れ替えることになります。

・read whiee.mov というメッセージボックスをクリックして、ムービーを見るためにmetroオブジェクトをスタートさせて下さい(もとのままの画像をjit.pwindowに表示させるために、jit.scalebiasオブジェクトのscaleアトリビュートは1に、biasアトリビュートは0にセットして下さい。)。パッチの右下部分の、planemap 0 3 2 1 というメッセージボックスをクリックして、マトリクスの赤と青のプレーンを入れ替えて下さい。planemap 0 1 2 3 というメッセージボックスをクリックして、通常のプレーン割当てに戻して下さい。

出力するRGBの3つのプレーン全てに同じプレーンを適用すると、RGB3つのプレーンすべてが同じ値になるので、結果としてグレースケールの画像になります。

・planemap 0 1 1 1 というメッセージボックスをクリックして、この効果を見て下さい。リストのRGB3つのプレーンの各々の場所が1になっているので、もとの画像の赤プレーンが、出力マトリクスのRGB 3つのプレーン全てに適用されます。

すべての異なったカラープレーン交換のしかたを循環させるために、collオブジェクトに様々なプレーン割当てがすべて(前の章で行ったのと同じ方法で)書き込まれています。そして、これらの割当てを jit.matrixオブジェクトに送信して、そのplanemapアトリビュートを変更します。

patcher rotatecolorplansオブジェクトをダブルクリックして、サブパッチの内容を見て下さい。ここでは、メインパッチのcollオブジェクトに格納されている異なったマッピングが順に行われるように、単に1から6までがカウントされています。(そして、オフにされた場合には数1を送り、デフォルトのプレーン割当てにリセットします。)[rotatecolorplanes]ウィンドウを閉じて下さい。

patcher rotatecolorplanesオブジェクトの上にあるトグルをクリックして下さい。すると、1秒に1回の速さで異なったプレーン割当てが段階的に行われます。右インレットの上にあるrateナンバーボックスを小さい値(80位)に変えて下さい。素早いプレーンの再割当てによって引き起こされるフリッカー(点滅)効果を見ることができます。

次のチュートリアルでは、jit.hueを使ったより巧妙な方法によって画像の色相をローテーションさせるやりかたについて、また、jit.brcosaオブジェクトを使った他のカラーレベル調整方法についてご説明します。


画像の読込みとインポート

このチュートリアルパッチでは、3つの異なる種類の画像をjit.qt.movieオブジェクトに読込みました。PICT、JPEGの静止画、そしてQuictTimeムービーです。ムービーを再生するために設計されたオブジェクトに静止画を読込むことは奇妙に思われるかもしれません。しかし、実際にはQuickTimeは多くのタイプのメディアファイルを読込むことができ、jit.qt.movieオブジェクトはそれらすべてを読込む手段を備えています。(AIFFオーディオファイルでさえ、jit.qt.movieに読込んで、start/stopメッセージによって聞いたり、timeアトリビュートによって別の場所へジャンプしたり、等のことができます。もちろん、この場合には視覚的なマトリクス情報を見ることはありません。) 

静止画の場合、チュートリアル3でご説明したように、簡単にimportmovieメッセージによって、直接 jit.matrixオブジェクトに読込むことができます。この方法でQuickTimeムービーをインポートした場合には、ムービーの1フレームだけがjit.matrix格納されます。

このパッチでは、全ての画像の読込みにjit.qt.movieオブジェクトを使いました。その理由の第1は、読込みたいものの1つがムービーそのもの(ムービーの1フレームではなく)であったこと、第2は、jit.matrixオブジェクトのplanemapアトリビュートについて説明したかったからです。planemapアトリビュートは、実際に入力されてくるマトリクス(左インレットで受け取られるjit_matrixメッセージ)にのみ適応されます。もし、importmovieで画像をjit.matrixに直接インポートしたとしたら、planemapアトリビュートは何の効果も及ぼしません。


まとめ

jit.scalebiasオブジェクトは、乗法と加法を用いて、4つのプレーンを持つcharマトリクスのある特定のプレーン−あるいは同時に全てのプレーン−のすべての値を加工します。scaleアトリビュートは乗算を行われるマトリクスの全ての値に掛け合わせられる係数です。またbiasアトリビュートは乗算が終わったあと、各々の値に加算される値です。scale及びbiasアトリビュートはマトリクスの4つのプレーンすべてに作用します。いちどに1つのプレーンにだけ作用させたい場合には、ascale、abias、rscale、rbias、のような特定のプレーンに対応したアトリビュートを使用します。

これらのアトリビュートにはfloat(小数による値)の値を与えなければなりません。乗算と加算を行うために、jit.scalebiasはcharの値を0から1の間の小数として扱い、floatとの演算を行います。その後、計算の結果をchar(0から255までの整数)に変換し直し、再び格納します。0から1の範囲を超えた計算結果は、charに変換し直される前に、1または0に制限されます。

jit.matrixオブジェクトのplanemapアトリビュートを使用して、マトリクスのプレーンの再割当てを行うことができます。planemapに対するアーギュメントは出力するプレーンを順に並べたリストで、その値は、再割当てを行うために入力されるマトリクスのプレーンを表しています。従って、例えば入力マトリクスのプレーン1を、出力されるマトリクスの4つ全てのプレーンに割当てたい場合には、アトリビュートをplanemap 1 1 1 1 と設定する必要があります。

jit.scalebiasオブジェクトは4プレーンchar(ARGBカラー)マトリクスのカラーレベルを調整するための強力なツールを提供します。このような働きをもつ別のツールに関しては、チュートリアルの次の章でご説明します。