ImageMagick で長方形画像のアスペクト比を変えずに正方形にリサイズする

# はじめに

矛盾したタイトルに対してトンチに近い対策の話で、
画像をリサイズする際に(元と異なる)特定の縦横アスペクト比の画像ファイルを作りたいシーンは結構あります。

ImageMagick を使い始めたばかりだと、例えば、正方形(200x200)の画像を得ようと以下の通り実行して、その結果にガッカリするかもしれませんが、実はここにヒントがあります。

```shell:
% magick rose: rose.png  # サンプル画像
% magick convert rose.png -resize 200x200 rose0.jpg
% magick identify rose.png rose0.jpg
rose.png PNG 70x46 70x46+0+0 8-bit sRGB 6975B 0.000u 0:00.001
rose0.jpg JPEG 200x131 200x131+0+0 8-bit sRGB 8329B 0.000u 0:00.000
```

| rose.png (70x46) | rose0.jpg (200x131)| 
|---|---|
| ![rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/0ec3cfa4-c5dd-515b-5615-b2e222420c03.png) | ![rose1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/cb642664-5e00-19c0-7e37-33e52859b652.jpeg) |

処理結果は 200x200 になりません。ImageMagick の "-resize 200x200" は、画像の**縦横比を維持して** 200x200 を**超えない**範囲でサイズ変更する指定です。

正方形でない画像を元に、正方形の画像ファイルをつくるとき。主に以下の選択肢が考えられます。

```shell:
% magick convert rose.png -resize '200x200!' rose1.jpg
% magick convert rose.png -resize 200x200x -background white
               -gravity center -extent 200x200 rose2.jpg
% magick convert rose.png -resize '200x200^'  \
               -gravity center -crop 1:1 rose3.jpg
% magick identify rose[1-3].jpg
rose1.jpg JPEG 200x200 200x200+0+0 8-bit sRGB 10783B 0.000u 0:00.000
rose2.jpg JPEG 200x200 200x200+0+0 8-bit sRGB 9470B 0.000u 0:00.000
rose3.jpg JPEG 200x200 200x200+0+0 8-bit sRGB 9652B 0.000u 0:00.000

```

|rose1.jpg (アスペクト無視) | rose2.jpg (内接,パディング) | rose3.jpg (外接,クロップ) |
|---|---|---|
| ![rose1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/b5057969-eb7b-85d9-ee7a-12ada530f126.jpeg) |![rose2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/470c0961-621d-a552-222c-abbfda826ae0.jpeg) | ![rose3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/1d5b12d3-68ef-40fe-8b43-7e4a60bed9f0.jpeg) | 

rose1.jpg は縦横比を維持せずに 200x200 に引き伸ばす方式です。特殊用途です。

大抵は、rose2.jpg、rose3.jpg のどちらかを選択すると思います。
考え方としては、額縁に大きさの合わない写真を嵌め込むイメージです。どこに隙間を許すか、または隙間は許せないのでいっそ写真の端っこを切り取るか。前者を内接、後者は外接と呼びます。

# 各々の説明

## rose0.jpg

-resize オプションを使った普通のリサイズです。ImageMagick のリサイズは特別な事をしないと元画像のアスペクト比を維持します。ただ、これだと元が正方形でない限り、正方形の画像は作れません。

| rose.png (70x46) | rose0.jpg (200x131)| 
|---|---|
| ![rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/0ec3cfa4-c5dd-515b-5615-b2e222420c03.png) | ![rose1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/cb642664-5e00-19c0-7e37-33e52859b652.jpeg) |

## rose1.jpg

-resize に ! をつけると、**アスペクト比を維持せずに**指定されたサイズに引き伸ばします。

```shell:
% magick convert rose.png -resize '200x200!' rose1.jpg
```

! は shell が特別な解釈をするので、'〜' で囲う事で防いでます。

| rose.png (70x46) |rose1.jpg (200x200) |
|---|---|
| ![rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/0ec3cfa4-c5dd-515b-5615-b2e222420c03.png) | ![rose1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/b5057969-eb7b-85d9-ee7a-12ada530f126.jpeg) | 

## rose2.jpg

内接と呼ばれるリサイズ方法です。適当な色で隙間をうめサイズを合わせます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/4653a5ce-7beb-a1e5-1904-a0d574d70f91.png)


```shell:
% magick convert rose.png -resize 200x200 -background white  \
               -gravity center -extent 200x200 rose2.jpg
```

2つの処理があります。まずは、アスペクト比を維持して、小さめに(200x200を上回らない大きさに)リサイズします。その後、上下、または左右に白で隙間を埋めます。

```shell:
% magick convert rose.png -resize 200x200 rose2-1.jpg
% magick identify rose2-1.jpg
rose2-1.jpg JPEG 200x131 200x131+0+0 8-bit sRGB 8329B 0.000u 0:00.000
% magick convert rose2-1.jpg-background white  \
               -gravity center -extent 200x200 rose2.jpg
```

| rose.png (70x46) | rose2-1.jpg(200x131) | rose2.jpg (200x200) |
|---|---|---|
| ![rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/0ec3cfa4-c5dd-515b-5615-b2e222420c03.png) | ![rose2-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/81e63b67-ae16-f6e3-6eec-7b2f68d27a40.jpeg) | ![rose2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/470c0961-621d-a552-222c-abbfda826ae0.jpeg) |

### x:y# 記法 (蛇足)

7.1.0-14 から  x:y# 記法が追加されたので、もう少しシンプルに出来ます。

```shell:
~/ImageMagick/7.1.0-14/bin/magick convert rose.png -resize 200x200  \
               -background white -gravity center -extent '1:1#' rose2.jpg
```

同じサイズ 200x200 を二度指定しなくて済みます。正直、バージョンを考えると使うのは慎重になる方が良いかもです。

参考までに、7.1.0-13 以前で実行した時のエラーです。

```
% ~/ImageMagick/7.1.0-13/bin/magick convert rose: -resize 200x200  \
                  -background white -gravity center -extent '1:1#' rose2.jpg
convert: invalid argument for option '-extent': 1:1# @ error/convert.c/ConvertImageCommand/1562.
```

## rose3.jpg

こちらは外接と呼ばれるリサイズ方法です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/e81ab18f-4c01-ef34-1219-f35f2b111a46.png)

```shell:
% magick convert rose.png -resize '200x200^'  \
               -gravity center -crop 1:1 rose3.jpg
```

2つの処理があります。まずは、アスペクト比を維持して、大きめに(200x200を下回らない大きさに)リサイズします。そこから真ん中を 200x200 でクロップします。

```shell:
% magick convert rose.png -resize '200x200^' rose3-1.jpg
% magick identify  rose3-1.jpg
rose3-1.jpg JPEG 304x200 304x200+0+0 8-bit sRGB 14069B 0.000u 0:00.000
% magick convert rose3-1.jpg \
               -gravity center -crop 1:1 rose3.jpg
```

| rose.png (70x46) | rose3-1.jpg(304x200) |  rose3.jpg (200x200) |
|---|---|---|
| ![rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/0ec3cfa4-c5dd-515b-5615-b2e222420c03.png) | ![rose3-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/2aff8b28-ff4a-59e6-22bf-8fb2ae0f533d.jpeg) | ![rose3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/1d5b12d3-68ef-40fe-8b43-7e4a60bed9f0.jpeg) | 


# 参考

- ImageMagick 公式サイト
  - http://www.imagemagick.org/Usage/resize/
  - https://legacy.imagemagick.org/discourse-server/viewtopic.php?t=26183

- ImageMagick の Geometry 仕様
  - https://qiita.com/yoya/items/704fdfbd881f166125d8
- 画像リサイズ処理のうんちく
  - https://qiita.com/yoya/items/95c37e02762431b1abf0