Hori Blog

フリーランスでバックエンドエンジニアとして活動している Ryota Hori のブログです。
最近はテック系記事より雑記ブログ気味。

eyecatch image of ImageMagick で黒帯背景に白文字を載せた画像を生成するシェル芸

ImageMagick で黒帯背景に白文字を載せた画像を生成するシェル芸

よくタイトル画像やアイキャッチ画像で見かける “半透明な黒帯背景に白文字でタイトルが書いてあるあの画像” (なんて呼ぶのだろう?)を生成するシェル芸です。

できること

これが

元画像

これで

$ ./createImageWithText.sh tmp/src.jpg "ドラム式洗濯機はいいぞ\nめっちゃいいぞ\nm9(^Д^)プギャー" tmp/dst.jpg

こう!

出力画像

ブログのアイキャッチ画像を簡単に生成するために作りました。

script

createImageWithText.sh
#!/bin/bash

set -e

usage="createImageWithText.sh src.jpg 'text' dst.jpg"

if [ ! $# -eq 3 ]; then
  echo $usage
  exit 1
fi

srcImage="$1"
text="$2"
dst="$3"

bgcolor='#0008'

echo "srcImage = $srcImage"
echo "text = $text"
echo "dst = $dst"

size=($(identify -format "%w %h" "$srcImage"))
srcW=${size[0]}
srcH=${size[1]}
echo "srcWidth = $srcW"
echo "srcHeight = $srcH"
bandW=$srcW
bandH=$(expr $srcH \* 3 / 7)
padW=$(expr $bandW / 8)
padH=$(expr $bandH / 6)
textW=$(expr $bandW - $padW \* 2)
textH=$(expr $bandH - $padH \* 2)

convert "$srcImage" \
  \( \
  -gravity center \
  -size "${textW}x${textH}" \
  -fill white \
  -font ~/Library/Fonts/NotoSansCJKjp-Regular.otf \
  -background $bgcolor \
  label:"$text" \
  -bordercolor $bgcolor \
  -compose copy \
  -border ${padW}x${padH} \
  \) \
  -gravity center \
  -compose over \
  -composite \
  "$dst"

open "$dst"

ざっくり解説

ImageMagick を使用しています。

convert "$srcImage" \
  \( \
  -gravity center \
  -size "${textW}x${textH}" \
  -fill white \
  -font ~/Library/Fonts/NotoSansCJKjp-Regular.otf \
  -background $bgcolor \
  label:"$text" \
  -bordercolor $bgcolor \
  -compose copy \
  -border ${padW}x${padH} \
  \) \
  -gravity center \
  -compose over \
  -composite \
  "$dst"

composite オプションで $srcImage と括弧内で錬成している “帯と文字部分” を重ねて $dst に出力しています。

括弧内ですが、

  -gravity center \
  -size "${textW}x${textH}" \
  -fill white \
  -font ~/Library/Fonts/NotoSansCJKjp-Regular.otf \
  -background $bgcolor \
  label:"$text" \

の部分で黒背景の文を作成し、

  -bordercolor $bgcolor \
  -compose copy \
  -border ${padW}x${padH} \

で padding 分を埋めています。

ImageMagick には extent という領域を拡大するオプションがあるのですが、透過の background と組み合わせるとなぜか label で描画した部分の背景が extent した部分に比べ濃くなってしまうため、背景色と同じ色の border で囲って padding としました。

帯部分のサイズ計算がこちらです。

bandW=$srcW
bandH=$(expr $srcH \* 3 / 7)
padW=$(expr $bandW / 8)
padH=$(expr $bandH / 6)
textW=$(expr $bandW - $padW \* 2)
textH=$(expr $bandH - $padH \* 2)

計算内容は見ての通りなので解説は省略しますが、もし見ためが気に入らなければここを調節していただければサイズが変わります。

テキストの行数や長さに応じて可変にしてもよさそうですね。

以上

とりあえずのアイキャッチ画像としては及第点ではないでしょうか。

次は

  • Hugo 向けに画像を最適化しつつ記事用ディレクトリに突っ込むスクリプト
  • リサイズしてアイキャッチ画像を生成する wrapper スクリプト

を用意して Hugo でも画像周りでストレスの溜まらない環境を整備する予定です。

追記:

書きました

Hugo のサムネ作成、画像追加、画像最適化を自動化するシェル芸