Quartz Composerにどっぷり!
じわじわスライドショー

今回のテーマ

今回のテーマは、スライドショーです。

推奨環境 この解説は、以下の環境を前提に作成し、動作確認等を行っています。ご確認ください。

改版履歴

画像ファイルの取得

今回のテーマはスライドショーです。指定したフォルダの中に含まれる画像ファイルを順に表示していきます。指定されたフォルダに含まれる画像ファイルをピックアップしてくれるパッチ Folder Images をエディタに配置します。Inspector で読み込むフォルダのパスを入力します。Settings のところでサブフォルダも含めて画像を取り出すかも決められます。

RSS Feedのときと同じように、File List ポートからは、ファイル情報が束ねられて出てきます。データの構造は以下のようになっていて、1つのファイルには、ファイル名 ( = name )、ファイルパス ( = path )、URL ( = url ) の情報が入っています。ファイルパスの方は "/Library/" のような形式、URLの方は "file://Library/" のようなプロトコル込みの形式です。Struct Index Member パッチでリストからファイル情報を1つ取り出して、さらに中の情報を Struct Key Member で取り出します。

ファイルを順に表示

ファイル情報を順に取り出すための方法は、RSSのときと基本的に同じです。「 0 〜 ファイルの最後のインデックス値 ( 番号 ) 」の数値を繰り返し出力するパッチを作って、Structure Index Member パッチと Structure Key Member パッチで URL を取得していきます。それを Image Downloader パッチで読み込んで Billboard パッチで画面に表示します。今回は以下のような構成で作成します。

Folder Images パッチの横に 2 つのマクロパッチがありますが、この 2 つのマクロパッチを作成します。

Folder Images Counter パッチは、「 0 〜 ファイルの最後のインデックス値 」の数値を繰り返し出力するパッチです。Folder Images の File List ポートから Folder Images Counter パッチの File List ポートへファイル情報を渡します。また、カウントアップの間隔を Interval ポートから指定できるようにします。Folder Image Billboard パッチは、ファイル情報をFile List ポートから受け取り、Index ポートから受け取ったインデックス値の画像を ( Billboard を使って ) 表示するパッチです。

まずは、Folder Images Billboard パッチを作っていきます。

構造は単純です。表示する画像のインデックス値が Index ポートに渡ってきますので、Structure Index Member パッチでファイル情報を取り出し、Structure Key Member パッチでキーを「 url 」に指定して URL 情報を取り出します。それを Image Downloader パッチに私でダウンロードして、Billboard パッチで表示します ( Structure Index Member の Structure ポートは、File List という名前で 、Index ポートは Index という名前で Publish しています )。この Billboard パッチは、Width = 2 にすることでウィンドウ幅いっぱいに画像を表示させます。

続いては、Folder Image Counter パッチです。

数字をカウントアップしていくための基本になるのが、Patch Time パッチです。これは、Quartz Composer の再生を開始した時点からの経過秒数を出力するパッチです。これを加工して、最終的に画像のインデックス値にします。

画像の切り替え間隔が、このパッチの Interval ポートから渡ってきます。これは、左側の Math パッチの Operand #1 を Publish したものです。Patch Time から出力される秒数を、Interval の値で割っておくことで、カウントアップを遅くします。これを Round パッチの Floor Value で小数点以下を切り捨てます。そして、最後の画像のインデックス値を超えたら 0 に戻るように右側の Math パッチでは、ファイルの数で割った余りを計算しています ( ファイルの数を得るために、Structure Count パッチを使っていますが、この Structure ポートは、 File List という名前で Publish しています )。これで画像のインデックス値が求まりますので、右側の Math パッチの Resulting Value を Index という名前で Publish して外部へ出力します。

これで、もう、スライドショーが始まっているはずです。

サンプル
Quartz Composerのファイル
フェード付きスライドショー

一応、スライドショーが表示できるようになりましたが、やはり次の絵に切り替わるときにはじわじわとフェードイン/フェードアウトさせたいですよね。次は、このフェードイン/フェードアウトにチャレンジします。

フェードイン/フェードアウトを行うためには、2 枚の Billboard パッチを使います。片方の Billboard パッチの透明度を徐々に上げることでフェードアウトし、同時にもう片方の Billboard パッチの透明度を下げることでフェードインさせます。

透明度の遷移をグラフで書いてみました。cos 波を LFO パッチで発生させて、それぞれの Billboard パッチの透明度 0.0 〜 1.0 の間で変化させます。片方の位相を 180 度変えることで上下逆の cos 波ができます。

どちらの Billboard パッチも処理の内容はほぼ同じです。まずは、Billboard A の方から作ります。下の図は、透明度の変化と表示する画像のインデックス値の関係を書いたものです。透明度が 0.0 になったとき、つまり、完全に透明になったときに画像を次の画像に進めるということです。また、2 つの Billboard パッチで交互に画像を表示しますので、インデックス値は 2 ずつ進めることになります。

では、作っていきます。まず、全体像です。透明度をコントロールするための Alpha ポートを Folder Images Counter パッチと Folder Images Billboard パッチにつけます。Folder Images Counter パッチ側で時間の管理をしていますので、透明度の計算もこちらで行い、Folder Images Billboard パッチは純粋に表示のみを扱います。

Folder Images Billboard パッチの方は、Billboard パッチの Color ポートに RGB Color パッチをつなげて、Alpha ポートを Publish して外部から透明度の情報を受け取れるようにします。

Folder Images Counter パッチには、画像のインデックスを 2 ずつカウントアップする仕組み ( 上段 ) と、透明度を出力する仕組み ( 下段 ) を組み込みます。

まず、左側にある Input Splitter パッチです。このパッチは、Input ポートから入力されたものをそのままスルーして Output ポートへ流すパッチです。マクロパッチで外部からの入力を複数の内部のパッチへ分配するときに主に使用します。また、Input ポートに何も繋がずに、固定値を Inspector で入力できますので、固定の数字や固定の文字列を生成するのにも利用できます。

今回は、画像の切り替えのインターバルの値を 2 箇所で使用するために導入しています。Patch Time パッチの時計の進みを遅くするための Math パッチと下段の透明度を出力する LFO パッチの周期に分配しています。

LFO パッチは、先程の波形を実現するために、Type = cos、Phase = 180、Amplitude = 0.5、Offset = 0.5 とします。Result ポートは、Alpha という名前で Publish します。

インデックス値を出力する方は、Math パッチで時刻の進みを制御するところまでは以前と同じです。そこから先は JavaScript パッチを使います。数式がある程度以上複雑になる場合は、JavaScript パッチで一気に処理する方が、スパゲッティ状態にならずに済みます。JavaScript の中身は以下のとおりです。

time = inputs[ 0 ];
count = inputs[ 1 ];
outputs[ 0 ] = ( 2 * Math.floor( time ) ) % count;

以前は、Round パッチを使って時刻を整数に変換していましたが、Math.floor メソッドを使っています。それに 2 を掛けることでカウントアップを 2 ずつにして、それを画像の数で割った余りを求めてループさせています。で、その結果である Output #0 を Index という名前で Publish します。これで Billboard A の方は完成です。Billboard B がないので、1 枚の画像がフェードインアウトします。

サンプル
Quartz Composer のファイル
同時に 2 枚の Billboard をフェードインアウト

ここまで来たら、あとは、Billboard B の方をほぼ同じ方法で作るのみです。

Folder Images Counter パッチと Folder Images Billboard パッチの 2 つをコピー & ペーストしてもう一対作ります。Folder Images Counter の Interval ポートには、同じ値を入れなければならないので、Input Splitter パッチを追加しています。

Billboard A の時と異なるのは、LFO パッチと JavaScript パッチです。Billboard A の時との違いは、下のグラフを見ると、波形が上下逆なのと、画像の切り替わるタイミングが半周期ずれていること、画像のインデックス値が奇数のみという点です。

LFO パッチは、Billboard A の時と上下逆なので、Phase = 0 にします。JavaScipt パッチの中身は、半周期ずらすために time - 0.5 としています。また、奇数のみにするために +1 してから割り算のあまりを求めています。

time = inputs[ 0 ];
count = inputs[ 1 ];
outputs[ 0 ] = ( 2 * Math.floor( time - 0.5 ) + 1 ) % count;

これで一応は動くようになります。しかしファイルサイズの大きな画像などの読み込みに時間のかかる画像を読み込むと、画面がバタバタすることがあります。Image Downloader パッチが、画像の読み込みをしている最中も透明度はどんどん変化していきます。画面の切り替わりの瞬間は透明度が 0.0 ですが、画像の読み込みに時間がかかっていると、どんどん不透明になっていきますので、画像が切り替わる前に画面上にはっきりと古い画像が表示されて、その後、新しい画像に切り替わるという現象が発生するのです。

そこでちょっと小細工をします ( 本来ならば、Image Downloader の読み込み完了と同期して処理をするべきなのですが、あまり簡単ではないのです )。LFO パッチの Amplitude = 1.0、 Offset = 0.5 に変えます。すると、以下のように出力する値が -0.5 〜 +1.5 になります。

RGB Color パッチに透明度に 0.0 以下の値を与えると、0.0 として扱い、1.0 以上の値を与えると、1.0 として扱ってくれますので動作上は問題ありません。これによって、透明度が 0.0 のままになっている時間が長くなりますので、読み込みにある程度時間がかかっても赤で書いている時間の範囲内であれば大丈夫です。完全な対策ではありませんが、極端に大きな画像でない限りはこれでうまくいきます。1.0 よりも大きな値を出力するようにしたのは、完全に不透明な状態の時間を長くしたかったためです。この辺りは見せ方によって色々と調整するとよいでしょう。

サンプル
Quartz Composer のファイル
ズームイン!

最後にもう一工夫。Mac OS X に標準添付のスライドショータイプのスクリーンセーバは、フェードしながらズームもします。これを真似てみます。やることは簡単です。ズーム用の LFO パッチを作って Billboard パッチの Width に入れるだけです。

Folder Images Counter パッチは、ズーム用 LFO パッチを追加しています ( 右側 )。

Type = Sawtooth Up、Amplitude = 0.5、Offset =2.5 としました。Sawtooth Up というのはノコギリ波で以下のような形をしています。

Sawtooth Down の場合は、右肩下がりの形になります。変化する値の範囲は、Billboard パッチの Width に与えるので 2.0 〜 3.0 としました。2.0 というのは、画像をウィンドの幅に合わせて表示する値なので、これを最低値としています。最高値は、お好みで調整するとよいでしょう。

最後に、Folder Images Billboard パッチの中身です。Billboard パッチの Width を Publish するだけです。これで完成です。動かしてみると分かりますが、ズーム処理のためか今までよりは処理が重いです。

サンプル
Quartz Composer のファイル
クイックリファレンス