Swift Playgroundsで学ぶiOSプログラミング

2種類のフィルターをスイッチで切り替えるプログラム

文●柴田文彦 編集●吉田ヒロ

2017年11月22日 17時00分

木版画のようなタッチと、線画化の効果を試してみる

 ここまでできたら、とりあえず効果を確かめてみましょう。適当に写真を撮影してから、まずスライダーを動かしてみます。すると、木版画調に加工された画像が撮影した元の画像の下に表示されます。

今回のプログラムも、プログラムを起動すると写真撮影が始まります。撮影後に「写真を使用」をタップすると、そのままの画像が上下に表示されます。スライダーを動かすと、Edge Workのフィルターがかかります。スライダーの位置で、タッチの荒さを調整できます

 スライダーを右に動かすほど、荒い「彫り」になります。撮影する内容によっては、棟方志功の木版画のようなタッチになるかもしれません。

 スイッチにタッチしてオンにすると、撮影した画像の輪郭を抽出したような効果の画像が表示されます。

スライダーの右のスイッチをオンにすると、フィルターはEdgeに切り替わります。この場合、スライダーでは画面の明るさを調整できます。スライダーが左端だとほとんど真っ暗で、右に動かすほど黒い部分の面積が減っていきます

 このフィルターでは、白黒が反転したモノクロ画像のように見える場合もありますが、派手めの色調の写真を撮影すれば、結果にもそれなりに色が付きます。効果の色は元の色に近い色になるとは限りませんが、必ずしも反転するわけではないのが面白いところです。このフィルターの場合、スライダーが左端にあると、ほとんど何も表示されないので、右の方に動かしてみてください。

ほぼリアルタイムでフィルターがかかるように工夫する

 はじめに述べたように、パラメータの調整用に配置したスライダーでは、isContinuousをfalseに設定していました。それによって、スライダーを操作中には、値が変化してもフィルター処理メソッドが呼ばれないようにしているのです。そうした訳は、フィルターの処理にはそれなりに時間がかかるので、スライダーが動いている最中に毎回呼び出されると、動きがカクカクしてしまうからです。しかしユーザーからすれば、スライダーを動かしながら、効果の変化を見たいところです。それをスムーズな表示で可能にするには、今よりもずっと処理速度の速いiPadの登場を待つか、実質的なフィルター処理の時間を短縮する方法を考えればいいのです。

 このプログラムでは、撮影した画像も、それを加工した画像も、画面の中のかなり狭い領域に表示しています。つまり、表示するだけなら、実際に必要な画像の解像度は、撮影した画像よりもかなり少なくても構わないのです。

 そこで、撮影した写真画像を、あらかじめ小面積での表示用の低解像度に変換しておくことで、フィルター処理の時間を短縮することにしました。iOSでは、画像の解像度を変換する方法はさまざまなものが考えられます。ここではついでなので、Core Imageのフィルターとして用意されているLanczos Scale Transformを使うことにしました。

 まずそのための下準備として、解像度変換した画像を保持しておくためのCIImageクラスのオブジェクトorgImageを、クラス定義の先頭に付け加えます。

フィルター処理をほとんどリアルタイムで実行できるようにして、スライダーを動かしながら表示を更新できるようにするために、元の画像を縮小した画像を保持するCIImageクラスのオブジェクトorgImageを追加します。スライダーのisContinuousもtrueに変更します

 また、スライダーのisContinuous属性をtrueに設定して、スライダーのツマミの操作中もフィルター処理が起動されるようにしています。

 実際の解像度変換処理は、イメージピッカーコントローラーのdidFinishPickingMediaWithInfoメソッドの中に組み込んで、撮影する都度、自動的に解像度が変換されるようにします。

写真を撮影したあと、「写真を使用」をタップすると呼ばれるdidFinishPickingMediaWithInfoメソッドの中では、撮影した画像をCore Imageフィルターの1つを使って、縦横とも10分の1のスケールで縮小(解像度変換)します。その結果はorgImageに保存するとともに、画面にも表示します

 iPadのカメラは、かなり高解像度なので、ここでは、元の10分の1の解像度となるように、スケールを決めるパラメータの値を0.1に設定しています。変換後の画像は、撮影したままの画像の代わりに、画面の上下のイメージビューに張り付けておきます。

 あとの処理は、基本的に変わりませんが、1つだけ修正しておくべきところがあります。それは、EdgeWorkフィルターの半径パラメータです。このフィルターは、パラメータの値が同じでも、画像の解像度によって効果の見え方が大きく変わってしまうからです。画像の解像度を低くしたら、それに合わせて半径も小さくする必要があります。ここでは、スライダーによって0.2から1.2の範囲でパラメータの値が変化するように変更しました。

フィルター処理自体はほとんど変わりませんが、Edge Workのパラメータだけは、設定範囲を変更しておきます。このフィルターは、結果の見栄えが元の画像の解像度によって大きく異なるため、高速化のために縮小した画像に対応させるためです

 以上のようなプログラムの変更による動作の変化は、もはや細かく説明する必要はないでしょう。スライダーを動かしている最中もフィルター結果の画像がアップデートされるようになれば成功です。実行結果の画面は上の例と何も変わらないので特に示しませんが、各自スライダーを動かして確認してみてください。

次回の予定

 Core Imageフィルターは、非常に種類が多いので、とてもすべてを試してみるわけにはいきません。また、1つのプログラムでいろいろなフィルターを切り替えられるようにするには、それなりにユーザーインターフェースが複雑になり、プレイグラウンド向きではなくなってしまいます。次回は、多い、多いと言われるCore Imageフィルターの種類が、実際にどれだけあるのか、テーブルビューを使って一覧表示してみます。そこから、それぞれのフィルターのパラメータの説明も見られるようにするプログラムを作ってみることにしましょう。

■今回作ったプログラム

mobileASCII.jp TOPページへ

mobile ASCII

Access Rankingアクセスランキング