自炊した連番画像ファイル群の前処理を ImageMagick で行う（回転・切除）

どうも、自炊[^jisui]初心者です。
今日は私が自炊した画像ファイルを色調整・圧縮するより前にやる、簡単な処理のやり方についてご紹介しようと存じます。
ImageMagick についている `magick` `mogrify` コマンドと、`zsh` を使います（多分 `bash` でも可能です）。
`mogrify` は複数画像の一括処理用のコマンドです。

## 環境
Windows10 64bit, msys2上のzsh, ImageMagick Version 7.0.10-29 Q16

## 連番の画像ファイルをまとめて回転させて向きを正す
書類をスキャナの皿に載せる向きを間違えたり横向きに載せていると、すべての画像が上下逆さまだったり、偶数ページ/奇数ページが横向きでそれぞれ逆を剥いていたりすることがあります。
`mogrify -rotate <回転角度> <ファイル名>...` で画像をまとめて回転させることができます。
`mogrify` と [ブレース展開](https://qiita.com/laikuaut/items/642aa329a8d214a2cccb)を使います。[^seq]

```bash
$ mogrify -rotate 180 {001..100}.bmp    # 100個のbmpファイルを180度回転させる
$ mogrify -rotate 90 {001..100..2}.bmp  # 奇数番のbmpファイルを右に90度回転させる
$ mogrify -rotate -90 {002..100..2}.bmp # 偶数番のbmpファイルを左に90度回転させる
```


## ノドを切り落とす
もしかしたら裁断機の刃が痛んでいるのかもしれませんが、私は切るのが下手で裁断面が見開きで見たとき悪目立ちします[^cut]。そこで裁断面（本のノドにあたる）を15ピクセル程度カットして悪目立ちを抑えます。

コミックの場合はノドのギリギリまで絵があるのでカットしたくはないのですが、文字だけの書籍ならノドは白紙なのでガタガタの切断面をまっすぐに切断することができます。

`mogrify` を使うと直接ファイルを加工してしまいますが、今回は念のため、`magick (convert)` コマンドを使って、加工したファイルを別に `out` ディレクトリに出力します。
奇数ページと偶数ページでノドの位置が逆なので注意します。
`-chop` オプションで端から 15ピクセル切り落とす例です。数値は調整してください。
`-gravity` でどこを切り落とすか指定します。`-gravity` で指定できる値は `magick -list gravity` で確認できます。

`magick(or convert) <変換前の画像名> [ -gravity {position} ] -chop {width}x{height} <変換後の画像名>`

```bash
$ mkdir out
# 001～099までの奇数ページ (West で左側を切り落とす)
$ seq -f '%03g.bmp' 1 2 99 | xargs -I{} magick {} -gravity West -chop 15x0 out/{}
# 002～100までの偶数ページ (East で右側を切り落とす)
$ seq -f '%03g.bmp' 2 2 100 | xargs -I{} magick {} -gravity East -chop 15x0 out/{}
# ※スキャンによって偶数奇数の処理を逆にしなければいけないかもしれません。要確認
```

`seq [-f <FORMAT>] <FROM> [[<STEP>] <TO>]`
連番を生成。seq の FORMAT は一般的な printf と違って数字は `%d` の代わりに `%g`。[^seq]

`xargs -I<変数名> <コマンド>` 
パイプから渡ってきたデータを変数に代入してコマンドをそれぞれ逐次実行する。
今回は変数名に `{}` を指定したので `{}` にファイル名が代入されて実行される。

### ノド落としをスクリプトにしました
人間は3動作以上の作業に苦痛を感じます。作業が3動作を超えたらスクリプトにすべきです。ノド落としは
`mkdir` → 奇数ページのファイルについてファイル数を数えて左右どちらを切るか判断して実行→偶数ページについても同じく
と、明らかに動作数・判断数が多いので、せめて、開始ページと終了ページを認識する、開始ページは左右どちら側を切るのか判断する、くらいで済むようにスクリプトを書きました。

```bash:nodochop
#!/bin/bash

function usage_exit {
  cat <<EOM >&2
Usage: ${1##*/} [[-s <size=15>] [-o <outdir=out>]] <first:Number> {west|east} <last:Number>
<first> から <last> までのbmpファイルについて、ノドをそれぞれ <size> ずつ切除する
{west|east} <first>の画像について西側を切除するか東側を切除するか。以降交互に切除方向を変える。
EOM
  exit 1
}

chopsize=15
outdir=out
while getopts "hs:o:" optkey; do
  case "$optkey" in
    :)
      echo "argument expected after -$OPTARG option" >&2
      exit 1
      ;;
    s )
      chopsize=$OPTARG
      ;;
    o )
      outdir=$OPTARG
      ;;
    h | \? )
      usage_exit $0
      ;;
  esac
done
shift $((OPTIND-1))

if [[ $# != 3  || ! ( $1 =~ ^[0-9]+$ && $2 =~ ^(west|east)$ && $3 =~ ^[0-9]+$ ) ]]; then
  usage_exit $0
fi

if [[ ( "$2" == 'west' && $(($1 % 2)) -eq 0 ) || ( "$2" == 'east' && $(($1 % 2)) -eq 1 ) ]];then
  westeast=(west east)
else
  westeast=(east west)
fi

mkdir -p "$outdir"
seq $1 $3 | while read -r n; do
  fname=$(printf "%03d.bmp" $n)
  echo -ne "$fname \r" >&2
  magick "$fname" -gravity ${westeast[$(($n % 2))]} -chop ${chopsize}x0 "$outdir"/$fname
  if (($?)); then
    exit $?
  fi
done
echo -ne '\n' >&2
```

## 最後に
この単純な処理の後、画像に問題がないか確認してから圧縮や色味の調整など細かい調整をします。

## 参考リンク
- [画像のサイズ変更\(切り抜き・塗足し etc\.\) \| \| Imagemagickの使い方日本語マニュアル](https://imagemagick.biz/archives/550)
- [ImageMagick の画像 crop \- Qiita](https://qiita.com/yoya/items/62879e6e03d5a70eed09)

[^jisui]: 書籍などを裁断して、スキャナで取り込み、デジタルデータにする行為。
[^seq]: ブレース展開ではステップ指定は三番目の要素なのに対して、`seq`コマンドのステップ指定は2番目の要素なのに気を付けよう。
[^cut]: また、カッターでコミックを切り裂くときにはこまめに刃を更新しないと糊で切れ味が悪くなりひどい切り跡になります。カッターの刃はどうせ安いのだからケチらずすぐ取り換えましょう。