/**/

チュートリアル 15:
イメージの回転

jit.rota オブジェクトによる回転とズーム

Jitterでは、jit.rota と呼ばれるオブジェクトを使って、簡単にイメージの回転、やズームイン、ズームアウトを行うことができます。回転およびズームは一般的で役に立つビデオイフェクトですが、 jit.rota を利用してこれらを様々な方法で組合わせることにより、いろいろな「万華鏡のような効果」を得ることができます。jit.rota はビデオデータのマトリックス(他のあらゆる種類のイメージ)をインレットで受け取り、ズーム、回転、そしてオブジェクトのアトリビュートの設定に基づいた別な方法によるディストーションを施されたバージョンを出力します。

基本的な回転

・Jitter Tutorialフォルダの15jImageRotation.patというチュートリアルパッチを開いて下さい。loadbang からの bang メッセージによって、dishes.mov という QuickTime ビデオが jit.qt.movie オブジェクトに自動的に読み込まれます。metro オブジェクトをスタートさせる toggle をクリックしてビデオを見て下さい。

このビデオは左から右へパンをするカメラで撮影した色々なお皿の3秒間の映像です。しかし jit.qt.movieloop アトリビュートに初期値として2が設定され、ムービーが往復再生されているので、まるで左右に往復するパンのような錯覚を与えます。

注:Jitterオブジェクトの多くのアトリビュートは、「オン」「オフ」を表わす 1 と 0 だけをアーギュメントとして取ります。そのため、jit.qt.movie の loop アトリビュートも同様なものと考えるのは当然なことです。実際に、loop 0 でループはオフに、loop 1 でループはオンになり、loop 2 ではビデオが順方向に再生されてループ終了点に達すると、一気にループ開始点に戻るのではなく逆方向の再生を行います。

jit.rotatheta アトリビュートは、「アンカーポイント」を中心とした回転の角度を決定します。

・Rotation Angle と表示されたナンバーボックスをドラッグしてビデオを回転させて下さい。正の(あるいは増加する)値によって反時計周りに回転し、負の(あるいは減少する)値によって時計周りに回転します。回転角である角θ(シータ)はラジアンで表わされます。値0(または2π(6.283185)の倍数)の場合には通常のまっすぐな位置になります。π(3.141593)(またはπの奇数倍)の場合には、さかさまになります。theta の値と jit.rotaの動作の関係について納得がいくまで実験してみて下さい。

技術的な詳細:jit.rota は多量の内部的な計算を三角法を用いて行い、それによってどのようにイメージを回転させるかを決定しています。あなたがあまり三角法になじみがない場合、角度をラジアンで考えることに慣れていないかもしれません。日常的な会話では1回転を360度で表わす「度」がより一般的に用いられます。三角法では1回転が2πになるラジアンの方がより一般的です。なぜなら、半径1の円がちょうど2πの円周を持っているからで、これによって単位円と交わる点を参照することであらゆる角を表すことができるからです。(例えば、単位円上の1点からスタートして、円周上をちょうどπ/2の距離だけ進んだ場合、スタートした地点から円の中心に対して90°の角、すなわち、π/2 ラジアンの角だけ動いたことになります。)

また、三角法では正の値の角度の変化は、単位円周上の時計と反対回りの回転と考えます。しかし、日常生活では、一般的に時計周りの方向を直感として「正の方向」あるいは「増加している」(時間が過ぎるように)と考えるでしょう。

このため、時計周りの「度」による回転を、ラジアンで表した同じ回転に直すためには、度数に2πをかけて、-360で割る必要があります。

自動化された回転

手動でイメージを回転させる以外に、回転角を継続的に変化させるようなMaxの自動的なプロセスを書くことができます。前の章では、line オブジェクトを使って色相の回転角を継続的に0°〜360°まで増加させる rotate と名付けられたサブパッチを書きました。この章でも同様なことを行いますが、今回は、回転角が増加したムービーを表示させるために metro オブジェクトによる bang メッセージを使います。「ユーザ・フレンドリ」であるために、ユーザにはラジアンではなく度数表示によって回転角を示し(サブパッチの中で、度をラジアンに変換しています)、さらに回転速度を「1秒あたりの回転数」で表示しています。

・Degrees per bang と表示されたナンバーボックスに数値 6を入力して下さい。これによって、回転角は metro からの1回の bang メッセージにつき6度増加します。metro オブジェクトは毎秒20回(50ミリ秒毎に)bang を送信するため、毎秒の回転数は d * 20 / 360という式で表されます(結果は d/18になります)。ここで、d は bang 1回あたりに増加する角度(度)です。On/Offと表示された toggle をクリックして自動的な回転をスタートさせて下さい。

patcher rotate オブジェクトをダブルクリックして、サブパッチの内容を見て下さい。


[rotate]サブパッチの中の自動的な回転

「degrees per bang (bang1回当たりの角度)」でユーザが指定した値に 2πを掛け、-360で割って(上の「技術的な詳細」というコラムを参照して下さい)ラジアンに直しています。左インレットで bang メッセージを受信すると、回転がオンになっている場合には bang を通過させますが、これによってaccum オブジェクトへ加算が行われ、回転角が増加します。「degrees per bang」を負の値で指定した場合でも問題なく動作することに注意して下さい。この場合イメージは時計と反対回りに回転します。回転角の合計が 2π(または-2π)を超えた場合は、outlet から出力を行う前にモジュロ演算によって値を -2πから 2πの範囲に戻して(accumオブジェクトの値をリセットして)います。回転がオフにされた場合は、それを sel 0 によって検出し theta の角度を0にリセットします。

・サブパッチウィンドウを閉じて下さい。On/Offの toggle をクリックして自動的な回転をストップさせて下さい。

ズームインとズームアウト

jit.rota のもう1つの主な機能は、イメージのズームを行うことです。どれくらいズームを行うかは、 jit.rotazoom_xzoom_y というアトリビュートによって決定されます。これによって、水平方向、垂直方向のズームイン/ズームアウトを独立して行うことができます。また、両方のアトリビュートを一度に変化させて、2つの方向でのズームを同時に行うことも可能です。

・Zoomと表示されたナンバーボックスをドラッグして、ズームイン/ズームアウトを行って下さい。値が1より大きくなるとイメージが拡大(ズームイン)され、1より小さくなるとイメージが縮小(ズームアウト)されます。x、y と表示されたナンバーボックスに直接値を入力すると、x 軸方向とy 軸方向のズームを別々に変化させることができます。(ズームに負の値を指定すると、サイズが変更されると同時にイメージが反転します。)

イメージのズームインを行った場合(仮にズームの値を2に設定した場合)でも、かなり良い画質が保たれています。これは、あらかじめ interp 1 メッセージによってjit.rotainterp アトリビュートがオンになっているためです。interp をオフにすると、ズームインを行った場合ピクセレーション(画素化)が生じます。ズームアウトを行った場合には interp は何の効果ももたらしません。これは、かなりなコンピュータの時間の浪費であると言えます。(チュートリアル14のピクセレーションと補間に関する説明を参照して下さい。)しかし、イメージがズームアウトによって縮小された場合でも、補間を行うことによって回転するイメージの画質は改善されます。

イメージの境界の外側

・両軸方向のズーム値を0.25程度の小さな値に設定して下さい。

イメージの回転や縮小が行われた結果イメージが表示領域全体を埋め尽くさない場合に、jit.rota はイメージ領域の外側にあるマトリックスの残りの部分をどのようにするかを決めます。この時点では jit.rota はイメージ領域の外側のセルを全て0にし、黒で表示されるような設定になっていると思います。jit.rota がイメージの境界の外側にあるセルをどのように処理するかは、boundmode アトリビュートによって決定されます。boundmode の設定による違いは、パッチの右上隅にある Space outside the image と表示されたポップアップメニューによって見ることができます。ここでは boundmode の値は1で初期化されているため、 jit.rotaは外側のセルをすべてクリアします。boundmode アトリビュートによる処理の内容は次のようなものです。

0 Ignore 外側の全てのセルはそれまでの値のままで、変更されません。
1 Clear 外側の全てのセルの値を0にします。
2 Wrap マトリックス全体を満たすまで、何回でもイメージを繰り返します。
3 Clip 外側の全てのセルにイメージの境界線上の値を連続して設定します。
4 Fold) イメージを逆方向に反転させて繰り返します。

boundmode アトリビュートを、「ウォーホール」のような複製によるイメージ効果をもたらす 2(wrap)、あるいは万華鏡のような効果をもたらす 4(fold)に設定して、イメージがズームアウトされた場合の特殊な効果を試してみて下さい。

・自動回転をオンに戻してローテーションとズームの双方を使い、様々なパラメータ(Degrees per bang、 Zoom、Space outside the image)を変化させてみて下さい。

・実験が終わったら、自動回転をオフにし、ズームアトリビュート(zoom_x およびzoom_y )を1に戻して下さい。

アンカーポイントとオフセットによる調整

これまで、イメージの中心点を回転の中心として使ってきました。しかし、実際にはイメージの回転の中心点として任意の点を選択することができます。回転の中心となる「アンカーポイント」は anchor_x および anchor_y アトリビュートによって設定されます。現時点でこのアトリビュートは160と120に設定されていますが、Anchor point と表示されたナンバーボックスオブジェクトでその値を変更することができます。

・いろいろなアンカーポイントを設定し、Rotation Angle ナンバーボックスをドラッグしてその効果を試してみて下さい。いくつかのアンカーポイントの設定として、0,0、 40,30、160,-120、320,240等を試してみるとよいでしょう。boundmode アトリビュートを1に設定すると、様々な回転効果をより明確に見ることができると思います。anchor_x および anchor_y の値はマトリックスの左上隅を起点として指定されますが、マトリックスの各ディメンションの大きさを超えた値を指定することも可能である点に注意して下さい。

さらに、offset_x および offset_y アトリビュートを使用することによって、回転およびズーム処理を行った後のイメージを出力マトリックスの別の位置に移動させることもできます。

・これをより効果的に見るために、まずパッチの右下隅にある pvar オブジェクトの上のメッセージボックスをクリックして下さい。これによって、回転角、境界モード、ズーム、アンカーポイントが、この章の最初で用いた状態に戻されます。(関連するインターフェイスオブジェクトには名前を付けてあるため、pvar を経由して情報をやり取りすることができます。) Zoomナンバーボックスに0〜1の値をセットして、イメージをズームアウトさせて下さい。

・Location offset と表示された ナンバーボックスを使って、offset_x および offset_y の値を変更しイメージをあちこち移動させて下さい。これを boundmode 4 と同時に試してみて、「万華鏡(カレイドスコープ)」モードでの効果を見て下さい。

・終了したら、Location offset の値を0に戻して下さい。

回転のコントロール

イメージを回転させる方法をもう1つ考えてみました。

jit.pwindow display オブジェクトの内側をクリックし、マウスボタンを押しながら、オブジェクトの中央付近で小さな円を描くようにドラッグして下さい。

jit.pwindow は、マウスボタンが押されている間、マウスの動きを追跡してその座標情報(そして他のマウス情報)を右アウトレットから mouse メッセージという形で出力します。mouse メッセージの最初の2つのアーギュメントは jit.pwindow の左上隅を起点としたマウスの x および y 座標値を表わします。ここでは、これらの座標値を使って jit.pwindow の中心から見たマウスの角度を計算し、それを jit.rota に対し theta アトリビュートのアーギュメントとして送っています。


jit.pwindow 内でのマウス位置をコントロール情報として使用することができます

技術的な詳細:どのようにしてこの角度を求めているかを知りたい方は、この下の文章をお読み下さい。

jit.pwindow座標の原点0,0と考え、さらにその時点のマウスの位置を原点の周りの円周上にあると考えた場合、この2点に基づいて直角三角形を書くことができます。それで、マウス座標のy/xのアークタンジェントを取ることによって jit.pwindow の中心点を基準としたマウスの角度を得ることができます。


そのためには、入力される x および y 座標を得た後、まず最初にそれらを jit.pwindow の中心点を起点とした値に変換します。x 座標の値から160を引き(x の値が-160〜160の範囲になるようにします)、y 座標の値に-1を掛けて(値が上に行くに従って、減少するのではなく増加するようにします)から119.5を加算します(ちょうど120を加えた場合、jit.pwindow からy 座標として120を受け取るごとに expr の中で数学的な演算で定義されない0除算を行おうとしてしまいます)。 x および y 座標を変換してしまえば、角度をラジアンで求めるためにy/xのアークタンジェントをとることができます。さらに、この角度の値に-1を掛け、時計方向のマウスの動きにあわせて、イメージが時計方向に回転するようにします。

この方法は180°の範囲の中だけで動作します。それは、アークタンジェント関数ではマウス位置とその円の反対側の位置との間に違いが現れないからです。(y/xの計算はどちらの点でも同じ結果になります。)このため、マウスのy座標が jit.pwindow の下半分にある場合には常に theta の角に -π をオフセットとして加え、対応する反対側の位置と区別しています。(これは式の最後の部分です。)

この式は jit.pwindowの160,120という点を原点とした場合にのみ適切に動作するという点に注意して下さい。どのようなサイズの jit.pwindow でもちゃんと動作する式を作りたい場合には、getsize メッセージによって jit.pwindow の大きさを取得し、この size の値を式の変数として使用します。よく数学書にあるように、「これは、読者の演習問題として残して」おきます。

まとめ

jit.rota オブジェクトは、その theta アトリビュートに回転角をラジアンで指定することによって、簡単にイメージを回転する手段を提供します。このオブジェクトはまた、zoom_x および zoom_y アトリビュートによって、簡単にズームイン/ズームアウトを行う手段をも提供しています。anchor_xanchor_y アトリビュートによって回転の中心点を変更することができ、offset_xoffset_y アトリビュートによって結果として作られたイメージを出力マトリックス中で移動させることができます。結果として作られたイメージの外側のマトリックスセルを jit.rota がどのように扱うかは、boudmode アトリビュートによって変更することができます。これら全ての機能を組合わせて使用することによって、シンプルな回転やズームだけでなく、イメージの複製効果やカレイドスコープ(万華鏡)効果を得ることができます。

ズームや回転は、jit.rota によって行われるかなり集中的な内部演算を含んでいるため、これらの命令はコンピュータのプロセッサに対してかなりな要求を行うことになります。もし興味があれば、これらの演算の式は jit.rota のヘルプファイルにあります。このチュートリアルでは紹介できなかったアトリビュートがまだまだあります。これらによって実際に回転に関する式の全ての係数にアクセスすることができ、イメージのディストーションや回転に関するより多くの可能性を与えてくれます。これらも jit.rota の ヘルプファイルで紹介しています。

非常に多くのアトリビュートを一度にコントロールするために、アトリビュートの値を生成するMaxの自動処理を工夫することや、ジェスチュアによって値を変化させるようなインタラクティブなコントロールを考案することも可能です。