チュートリアル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.movie のloopアトリビュートに初期値として2が設定され、ムービーが往復再生されているので、まるで左右に往復するパンのような錯覚を与えます。

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


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

・Rotaton 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はbang1回あたりに増加する角度(度)です。On/Offと書かれたtoggleをクリックして自動的な回転をスタートさせて下さい。

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


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

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

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

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

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

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

イメージのズームインを行った場合(仮にズームの値を2に設定した場合)でも、かなり良い画質が保たれています。これは、あらかじめinterp 1メッセージによってjit.rotaのinterpアトリビュートがオンになっているためです。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.pwinodowの左上隅を起点としたマウスの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_tアトリビュートによって、簡単にズームイン/ズームアウトを行う手段をも提供しています。anchor_xとanchor_yアトリビュートによって回転の中心点を変更することができ、offset_xとoffset_yアトリビュートによって結果として作られたイメージを出力マトリクス中で移動させることができます。jit.rotaが結果として作られたイメージの外側のマトリクスセルをどのように扱うかは、boudmodeアトリビュートによって変更することができます。これら全ての機能を組合わせて使用することによって、シンプルな回転やズームだけでなく、イメージの複製効果やカレイドスコープ効果を得ることができます。

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

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