ImageMagick で PNG の半透明を反映して alpha(透明)チャネルを消す方法

# はじめに

以下の記事で紹介されているコマンドを呪文のように使っている方が多いと思われますが、中身が分からないまま使うのが気持ち悪い人用に、これらの具体的な動きを解説してみます。

https://qiita.com/iwiwi/items/fdec3466c4dea5818b3a

```shell
% convert HOGE.PNG \
          \( +clone -alpha opaque -fill white -colorize 100% \) +swap \
          -geometry +0+0 -compose Over -composite -alpha off \
          PIYO.PNG
```

# サンプル画像

半透明のあるサンプル画像を、以下のように作ってみます。

```shell
% convert -size 200x200 gradient:cyan-magenta cyan-magenta.png
% convert cyan-magenta.png -alpha on -channel A -fx "(i-w/3)/w*3" HOGE.PNG
```

シアン-マゼンタの縦グラデーション画像をまず作り、そこに横グラデーションの透明度を適用します。
左1/3は完全透明、1/3〜2/3はグラデーション、2/3以降は不透明とします。

| cyan-magenta.png | HOGE.PNG|
|---|---|
|![cyan-magenta.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/888d92cf-6705-48f0-8368-284e64d64585.png) | ![HOGE.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/12f1da97-868f-5712-a0dd-31e5a9310e30.png) |

iwiwi さんのコマンドを実行すると、以下のようになります。qiita の背景が白でわかりにくいので、以降は yellow に変えます。

|PIYO.PNG | PIYO.PNG (yellow) |
|---|---|
![PIYO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/044b7279-185c-e4b1-8fe2-8124818cf6ae.png) | ![PIYO(yellow).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/6758c8d6-e46a-60d8-2895-f9c19fa2fdb5.png) |

# コマンドを分割

コマンドを２つに分けるとこうです。(white を yellow に変えてます)

```shell
# 元画像と同じ大きさの黄色画像を作る
% convert HOGE.PNG -alpha opaque -fill yellow -colorize 100% YELLOW.PNG
# 黄色画像の上に元画像を重ねて合成する
% convert YELLOW.PNG HOGE.PNG -compose Over -composite -alpha off PIYO.PNG
  (YELLOW.PNG HOGE.PNG は HOGE.PNG YELLOW.PNG +swap と同じ)
```

|YELLOW.PNG | PIYO.PNG |
|---|---|
|![FUGA.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/d249455c-d00d-1763-4d6f-7f1eb0107f8b.png) | ![PIYO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/26718bf8-4145-9ac0-82f8-5beac76bd9ee.png) |

# オプションの説明

## +clone

直前に読んだ画像をメモリ上でコピーします。

例えば、同じ画像を横に連結するとき、

```shell
% convert HOGE.PNG HOGE.PNG +append HOGEHOGE.PNG
```
でも良いですが、これだと HOGE.PNG を二回ファイルから読んでデコードする手間がありまして、

```shell
% convert HOGE.PNG +clone +append HOGEHOGE.PNG
```

こっちの方がメモリコピーで済んでお得です。

|HOGEHOGE.PNG|
|---|
|![HOGEHOGE.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/2cd73ff1-aa67-ca25-0cb1-d08fd9a4c704.png)|

## -alpha opaque

透明度を全て不透明にします。

```shell
% convert HOGE.PNG -alpha opaque OPAQUE.PNG
```

|OPAQUE.PNG|
|---|
|![OPAQUE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/3d7cb73e-21b6-8129-7ecb-52fd1e6eacea.png)|

## -fill white -colorize 100%

画像を白く塗りつぶす、恐らく一番簡単な方法です。(-draw "rectangle 〜 でもいけますが、-colorize の方が良いでしょう)
割合指定でオーバーレイ効果をかけます。

- 白のオーバーレイ 25%,50%,75%,100%

```shell
% convert OPAQUE.PNG -fill white -colorize  25% WHITE-25.PNG
% convert OPAQUE.PNG -fill white -colorize  50% WHITE-50.PNG
% convert OPAQUE.PNG -fill white -colorize  75% WHITE-75.PNG
% convert OPAQUE.PNG -fill white -colorize 100% WHITE.PNG
```

- 黄色のオーバーレイ 25%,50%,75%,100%

```shell
% convert OPAQUE.PNG -fill yellow -colorize  25% YELLOW-25.PNG
% convert OPAQUE.PNG -fill yellow -colorize  50% YELLOW-50.PNG
% convert OPAQUE.PNG -fill yellow -colorize  75% YELLOW-75.PNG
% convert OPAQUE.PNG -fill yellow -colorize 100% YELLOW.PNG
```

| WHITE-25.PNG  | WHITE-50.PNG | WHITE-75.PNG | WHITE.PNG |
|---|---|---|---|
|![WHITE-25.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/36cdb582-cd13-9b28-4569-3860783bb6c2.png) |![WHITE-50.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/0411b1d5-558b-8e5b-23c7-6efe6f5890f3.png) | ![WHITE-75.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/3686ef2c-1484-bc4f-7a64-df25e7c979d7.png) | ![WHITE.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/9342e5c8-bac3-c641-561c-495e4d18091b.png) |
|YELLOW-25.PNG|YELLOW-50.PNG|YELLOW-75.PNG|YELLOW.PNG |
| ![YELLOW-25.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/b5731eb2-37b0-78d4-9c3b-c47341f65301.png) | ![YELLOW-50.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/928cf84e-7a8a-07b8-8ac9-15d240f4f98f.png) | ![YELLOW-75.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/7d9caacd-8b2f-e0cc-593a-1a6160e87509.png) | ![YELLOW.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/b0da3e25-f4dc-3a83-249e-fc1e7d1f8b4e.png) |

## +swap

```shell
% convert HOGE.PNG \( 黄色画像 \) +swap \
          -geometry +0+0 -compose Over -composite -alpha off \
          PIYO.png
```

HOGE.PNG と 黄色画像の順で画像を指定して合成(-composite)を行うと、HOGE.PNG が下、黄色画像が上にきて、合成してもただの黄色画像です。+swap を指定する事で、黄色画像を下(地)にして合成できます。

## -geometry +0+0

左上の位置合わせだと思うのですが、必要性がよく分かりません。PNG 仕様の screen と image が合ってない時対策かと思って検証してみても、オプションの有無で動作は変わりませんでした。誰か分かる方いたら教えて欲しいです！

## -compose Over -composite

画像を重ねて、手前の画像の透明度を元に合成します。

## -alpha off

透明度のチャネルを削除します。

# 簡単な方法

iwiwi さんの記事では以下ので半透明が無視されると説明されています。

```shell
% convert HOGE.PNG -background white -alpha deactivate -flatten PIYO.PNG
```

恐らく 6系での挙動を意識していると思いますが、当時は半透明どころか透明ピクセルも無視してました。
なお、7系でも当初は半透明は処理するけど透明度が消えない動作でした。
実は ImageMagick-7.0.4-6 で治っています。white を yellow に変えてバージョン毎に実行してみました。

```shell
% convert HOGE.PNG -background yellow -alpha deactivate -flatten PIYO.PNG
```

|6 系 | 7.0.4-5 以前 | 7.0.4-6 以降|
|---|---|---|
![6.9.9-51-out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/63fafb0b-5dbb-a4d5-53ac-55c6be8b72e9.png) | ![7.0.4-5-out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/27948ed4-c70a-45f0-489c-52ff6e9a1c6d.png) | ![7.0.4-6-out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/18c8840c-670e-eee0-12c4-f36b15c262fa.png) |
|単に透明度を削除| 透明度を反映するが透明度を消し忘れ | 期待するもの |

あと、以下のコマンドだと、7.0.4-5 以前(6系含む)でも大丈夫でした。

```shell
% convert HOGE.PNG -background yellow -flatten -alpha off PIYO.PNG
```

|6 系 | 7.0.4-5 以前 | 7.0.4-6 以降|
|---|---|---|
| ![6.9.9-51-PIYO.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/80774145-673b-92d1-23e1-d4b009a0afb5.png) | ![7.0.4-5-PIYO.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/4c053293-7a79-bc5d-cf82-160a375bdef2.png) | ![7.0.4-6-PIYO.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/dbbe62ff-2ad8-2604-e2a4-e949f8c0cfec.png) |