はじめに
AndroidでiOS風のすりガラスエフェクトをかけようとしたら案外面倒だったのでメモ
多少無理やりな方法ですがそれっぽいものを作ることができました。
必要なもの
GPUImage for Androidを使うので、gradleのdependencyに追加します。
app.gralde
repositories {
mavenCentral()
}
dependencies {
compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.2.3'
}
ソースコード
すりガラス的なエフェクトはガウスブラーをかけることで再現できます。
Bitmap source; //これがフィルターをかける画像のBitmap
GPUImageGaussianBlurFilter filter_gaussian = new GPUImageGaussianBlurFilter();
GPUImageNormalBlendFilter filter_blend = new GPUImageNormalBlendFilter();
// 白っぽくするために前面に置くBitmapを生成する
Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Canvas cv = new Canvas(bitmap);
Paint p = new Paint();
p.setColor(0x30FFFFFF);
cv.drawRect(0, 0, 1, 1, p);
filter_blend.setBitmap(bitmap);
GPUImage gpuImage = new GPUImage(context);
gpuImage.setImage(source);
gpuImage.setFilter(filter_blend);
gpuImage.setImage(gpuImage.getBitmapWithFilterApplied());
gpuImage.setFilter(filter_gaussian);
filter_gaussian.setBlurSize(10.0f);
gpuImage.setImage(gpuImage.getBitmapWithFilterApplied());
filter_gaussian.setBlurSize(5.0f);
gpuImage.setImage(gpuImage.getBitmapWithFilterApplied());
filter_gaussian.setBlurSize(1.0f);
Bitmap filtered = gpuImage.getBitmapWithFilterApplied(); // filteredがフィルターをかけたあとの画像
filter_blend.setBitmap(null);
bitmap.recycle();
// もう元画像を使わないのであればメモリ解放
source.recycle();
これで、filteredの中にいい感じにフィルターが掛かったBitmapが保存されます。
GPUImage for Androidのガウスブラーのサイズ指定で1.0f以上を指定すると大きくブラーがかかりますが、変な感じになってしまいます。
(ソースを見る限り、0.0f-1.0fまでしか対応していない)
この方法では、わざとおかしくなるように大きくブラーをかけて、もう一度小さくブラーをかけることで滑らかにしています。
いろいろ試した結果、10.0f→5.0f→1.0fの順にフィルタをかけるとそれっぽくなりました。
ただ、この方法だとフィルターを複数回掛ける必要があるので、連続的に処理が行われるような使い方には向いていないかもしれません。
ちなみに
OpenCVを使えば、一回の変換でうまくフィルターをかけることができます。
ただ、アプリサイズが大きく増えてしまうので、それでも問題ない場合にはそちらのほうが手っ取り早いでしょう。