見開きの雑誌画像を2分割して再保存する

雑誌などに掲載されている記事をiPadで読む際には、フラットベッドスキャナやスマホを使用して画像として取り込んで読んでいます。

雑誌の電子化にあたってAmazonなどの電子書籍を購入することも考えましたが、DRMによる利用制限やサービス停止などで永続的に使用できる保証もなく、目的の記事以外は不要でノイズになるので却下しました。

ScanSnapなどで自炊する方法もありますが、本を切断しスキャンした後は本として再利用できずゴミになってしまうことと、そもそもスキャン効率を求めるほどにはスキャンする頻度も多くないので、こちらも断念しました。

そこでスマホを使用してスキャンしていますが、片面ごとにスキャンしようとすると位置合わせが面倒です。このため、見開きでスキャンすることになります。

しかし、見開きでスキャンするとスマホやタブレットの画像ビューワーでは常に両開きで表示され画像が縮小表示されてしまい、ページを繰るたびに画像サイズと位置を調節する必要があるため、非常に読みにくいです。

そこで、スキャン直後にMacのAutometerで簡単に左右のページを分割できるようにスクリプトを組みました。スクリプトを無くさないようにここにメモしておきます。

なお、半ページのみをスキャンし縦長の画像となった場合は、画像中心を基準に指定した比率で画像を切り取って縮小する処理をします。

利用の際にはSquooshとImageMagickをインストールする必要がありますので、下記記事を参考にインストールしてください。

#!/bin/zsh

export PATH=$HOME/.nodebrew/current/bin:$PATH
export PATH=/opt/homebrew/bin:/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH
export PATH=/opt/homebrew/Cellar/imagemagick/7.1.0-45/bin:$PATH

### パラメータ設定 ###
#変換後の縦横サイズ
config_convert_width=762
config_convert_height=1200

#右開きか左開きか
config_first_page=right

#Squooshでjpg圧縮する。画像の幅が高さより長い場合は画像の中心で2分割してから保存する
function convert_images(){
	#Fullパスへ変換
	file_fullpath=`ls $1(:a)`

	#ファイル名を取得する
	filename_extention=$(basename "$file_fullpath")
	filename="${filename_extention%.*}"
	extention="${filename_extention##*.}"

	# #PNG/JPEGファイルでなければ処理をせずに終了する
	if [ "$extention" != "jpg" ] && [ "$extention" != "png" ]; then
		return 0
	fi

	#変換ファイル出力先を'Download/Convert/<画像ファイルが格納されているフォルダ名>'に設定する
	output_directory=${HOME}/Downloads/Convert/$(dirname $file_fullpath | sed -e 's/.*\/\([^\/]*\)$/\1/')
	mkdir -p "$output_directory"

	#変換後の長辺サイズを設定する
	if [ $config_convert_width -gt $config_convert_height ]; then
		max_dimension=config_convert_width
	else
		max_dimension=config_convert_height
	fi

	#元画像の縦横サイズを取得
	original_width=`identify -format "%[width]" $file_fullpath`
	original_height=`identify -format "%[height]" $file_fullpath`

	#横幅の方が大きい場合は画像の中心から分割して保存する
	if [ $original_width -gt $original_height ]; then
		file_firstpage="${output_directory}/${filename}_1.jpg"
		file_secondpage="${output_directory}/${filename}_2.jpg"

		#すでに変換済みファイルがある場合は処理をスキップする
		if [ ! -f "$file_firstpage" ]; then
			#中心位置を取得
			center=$original_width/2
			width_divide=$original_height*$config_convert_width/$config_convert_height

			#左右ページの左座標を取得
			if [ "$config_first_page" = "right" ]; then
				left_corner_first_page=$center
				left_corner_second_page=$center-$width_divide
			else
				left_corner_first_page=$center-$width_divide
				left_corner_second_page=$center
			fi

			#画像を分割する
			file_divide_firstpage="${output_directory}/${filename}_1.png"
			file_divide_secondpage="${output_directory}/${filename}_2.png"

			convert "${file_fullpath}" -crop "$(($width_divide))x$(($original_height))+$(($left_corner_first_page))+0" "${file_divide_firstpage}"
			convert "${file_fullpath}" -crop "$(($width_divide))x$(($original_height))+$(($left_corner_second_page))+0" "${file_divide_secondpage}"

			#squooshで画像を変換する
			squoosh-cli --mozjpeg '{}' --resize "{enable:true,height:$(($max_dimension))}" -d "${output_directory}" "${file_divide_firstpage}"
			squoosh-cli --mozjpeg '{}' --resize "{enable:true,height:$(($max_dimension))}" -d "${output_directory}" "${file_divide_secondpage}"
			
			#一時ファイルを削除する
			rm $file_divide_firstpage $file_divide_secondpage
		fi

		/usr/bin/osascript -e 'display notification "'"${filename_extention//\"/\\\"}"'" with title "画像を分割してSquoooshで圧縮しました"'
	else
		file="${output_directory}/${filename}.jpg"

		#すでに変換済みファイルがある場合は処理をスキップする
		if [ ! -f "$file" ]; then

			#中心位置を取得
			center=$original_width/2
			width_crop=$original_height*$config_convert_width/$config_convert_height

			#左座標を取得
			left_corner=$center-$width_crop/2

			#画像をcropする
			file_crop="/tmp/${filename}.jpg"
			convert "${file_fullpath}" -crop "$(($width_crop))x$(($original_height))+$(($left_corner))+0" "${file_crop}"

			#画像を圧縮する
			squoosh-cli --mozjpeg '{}' --resize "{enable:true,height:$(($max_dimension))}" -d "${output_directory}" "${file_crop}"

			#一時ファイルを削除する
			rm "${file_crop}"

			/usr/bin/osascript -e 'display notification "'"${filename_extention//\"/\\\"}"'" with title "Squoooshで圧縮しました"'
		fi
	fi
}


for file_dir in "$@"
do
	#ファイルかフォルダかで処理を分岐
	if [ -d $file_dir ]; then
		#フォルダを指定された場合は格納されているすべてのファイルを変換する
		foreach file (${file_dir}/**/*.*){
			convert_images $file
		}
	else
		#ファイルを指定された場合は対象ファイルを変換する
		convert_images $file_dir
	fi
done

参考になれば幸いです。