【Android】GlideでPhotoshopのトーンカーブを利用する


# TL;DR

- GPUImageのフィルターはPhotoshopフレンドリー
- Glideでacvファイルを設定するにはひと工夫必要
- エンジニアさんにっこり
- デザイナーさんも思わずにっこりするかも？

---

# はじめに

この記事では一貫してGlide４を利用しています。
Glide３とは若干記述が変わりますので、ご注意ください。

GPUImage for Androidは[GPUImage2](https://github.com/BradLarson/GPUImage2)のAndroid移植版で、GPUを利用することで、CPUよりもはるかに高速な画像処理を実現しています。
また、Photoshopとの親和性、汎用性ともに高いフィルターが数多く揃っているのも魅力ではないでしょうか。

今回はそのフィルター郡の中でも、Photoshopで作成したトーンカーブをGlideで手軽に利用する方法についてメモを残します。

---

# 試してみる

Photoshopでトーンカーブを作成し、acvファイルとしてエクスポートします。
実際の現場ではデザイナーさんに準備していただいてください。
作るのが難しいよという方は、[こちら](https://coliss.com/articles/build-websites/operation/design/photoshop-curves-by-juliatrotti.html)からプロカメラマンさんのテクニック光るacvファイルが無料でDLできます。

つぎに、acvファイルをAndroidプロジェクトの `app/assets` にインポートします。

No Image :bow: 

以上でリソースの準備が整ったので、コーディングに移ります。
例によってそれっぽいTransformationを探していると...

**ありませんでした。（なぜ）**

ので、自作することに。

---

### Glideで利用できるように

Glideに設定するフィルターはTransformation\<Bitmap\>のサブクラスでなければいけません。
そのため、さらにそのサブクラスであるGPUImageの `GPUFilterTransformation` のサブクラスを作っていきます。

実装は至ってシンプルです。

```kotlin
class ToneCurveFilterTransformation(
    // asvファイルと...
    input: InputStream
    // ラップするフィルターの実体を渡して...
) : GPUFilterTransformation(GPUImageToneCurveFilter()) {

    init {
        val filter = getFilter<GPUImageToneCurveFilter>()
        // フィルターにトーンカーブのパラメータを設定します。
        filter.setFromCurveFileInputStream(input)
    }
}
```
はい、これだけです。

---

### Module化しておく

ちょっと味気ないので、ついでに各所で使いまわせるようにGlideをModule化しておきましょう。
`@GlideModule` をつけた `AppGlideModule` のサブクラスを作り、ビルドします。
`glideName` を指定すると自動生成されるクラス名を変更できます。

```kotlin
// GlideToneCurveというクラス名で生成します。
@GlideModule(glideName = "GlideToneCurve")
class ToneCurveGlideModule : AppGlideModule() {

    override fun applyOptions(context: Context, builder: GlideBuilder) {
        // assetsフォルダからacvファイルを開いて...
        val input = context.assets.open("hoge.acv")
        val options = RequestOptions()
            .transform(
                // 先ほど作成したTransformationを設定する。
                ToneCurveFilterTransformation(input)
            )
        builder.setDefaultRequestOptions(options)
    }
}
```
あれ？ `openしたらcloseしないといけない` のでは...？
安心してください。さきほど作ったTransformationのスーパークラスがcloseしてくれています。

---

### 使ってみる

準備が整ったのでViewから呼び出してみます。

```kotlin
// GlideToneCurveはModuleから自動生成されたクラスです。
GlideToneCurve.with(this)
            .load(R.drawable.hoge)
            .into(image_view)
```
普段と変わらぬGlideの使い方で利用できます。
さきほどのModuleから自動生成されたクラスには、すでにトーンカーブが適応された状態ですのでViewでは特にオプションを設定する必要はありません。

---

# 成果物

トーンカーブ適応の前後の比較です。

| Before | After |
|---|---|
| ![Screenshot_1577290996.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252756/6ce278f3-ee82-64b1-8ea3-7512d30a66db.png) | ![Screenshot_1577291258.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252756/119a12ff-0b09-2371-d1ba-257e6dac23f0.png) |

しっかり適応されているのが確認できました。

---

# ライブラリ

**Glide**
https://github.com/bumptech/glide

**GlideTransformations**
https://github.com/wasabeef/glide-transformations

---

## リファレンス

素材提供
http://gahag.net/006522-cat-santorini/
https://coliss.com/articles/build-websites/operation/design/photoshop-curves-by-juliatrotti.html

GPUImage for Android で超爆速画像フィルターを作成しよう！
https://dev.classmethod.jp/smartphone/android/gpuimage/