【jpegtran】 出来る!ベースラインJPEG ⇔ プログレッシブJPEGのロスレス変換 ~Droplet編~
さよなら、全てのプログレッシブJPEG
Walkmanがクソ雑魚だからしゃぁない(爆)
概要
以前Qiitaでこんな記事を書いた。
(いずれ、こっちに移動したい)
jpegtran を用いることで、ベースラインJPEG と プログレッシブJPEG を (ほぼ) 欠損無く相互変換が行えることが分かった。しかしながら。 jpegtran のWindowsバイナリの国際文字の扱いに何があり、扱いが難しい。Windowsを捨てたくなるけどそれはさておき。
私はアルバム アートの一括変換用として使いたいのだが。画像ファイルはアルバムのフォルダ名と対にして管理をしており、どうしても管理上国際文字は避けられない。また、一括変換にしても、変換不要なものは特に弄りたくない。後に、音声データに設定する際に、更新日時を指標にしたいためである。
さらに、今回は一括変換ではあるが。今後のリッピング作業於いて画像収集した際には、逐次実行のし安さも必要になる。画像管理ツールを色々探したが、希望を叶えるものがなかった。
単ファイルの変換用バッチ と、ExplorerのSendtoから活用するための 変換Droplet の作成を行った。
jpegtran だけでなく、 batfile と Droplet と sendto の活用サンプルにも若干なると思うので、興味がある人はご参考に。
jpegtran の Windowsバイナリ
jpegtran
は jpegclub版
のWindowsバイナリを利用する。
-
New jpegtran features
https://jpegclub.org/jpegtran/ -
mozilla/mozjpeg: Improved JPEG encoder.
https://github.com/mozilla/mozjpeg/
mozjpeg版
では、jpegtran
で標準入出力が利用出来き、今回のファイル名問題の回避方法としては若干嬉しいが。標準入出力の同時利用でファイル上書きが出来ないため、結局今回は意味ない。加えて、Premature EOF in JPEG file
というエラーが多発するため。実用には欠ける。。。
プログラミング
基本コマンド
JPEG process
の確認
① rdjpgcom
はチェックだけなので、標準入力を利用することで、国際文字問題は回避可能。
@REM check JPEG process.
rdjpgcom.exe -verbos < "album.jpg"
JPEG process: Baseline
JPEG process: Progressive
この JPEG process: Progressive
findstr
で捕まえる。
@REM check JPEG process.
(rdjpgcom.exe -verbos < "album.jpg" | findstr /C:"JPEG process: Progressive" > nul) && ECHO hoge
これで、プログレッシブJPEGの時だけ処理する
ための土台 (トリガー) が出来た
② 安全なファイル名に退避し変換処理
jpegtranの実行の為に、安全なファイル名変換して変換を実行。移動で上書きをすることで、一時ファイルの残留も抑える。
@REM copy to tempfile.
copy /B /Y "album.jpg" "tmp.jpg"
@REM convert.
jpegtran -outfile "tmp.jpg" "tmp.jpg"
@REM move (overwrite).
move /Y "tmp.jpg" "album.jpg"
これを、前処理が成功時のみに整形
(
@REM copy to tempfile.
copy /B /Y "album.jpg" "tmp.jpg" > nul
) && (
@REM convert.
jpegtran -outfile "tmp.jpg" "tmp.jpg"
) && (
@REM move (overwrite).
move /Y "tmp.jpg" "album.jpg" > nul
)
③ より安全な一時ファイル名の生成
同時処理を加味した場合に、一時ファイル名が固定名のは望ましくない。そのため、一時フォルダを用いた安全な一時ファイル名を生成し、より安全に処理出来る様にする。
:loop
@SET TEMP_FILE_NAME=
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET TEMP_FILE_PATH=%TEMP%\%TEMP_FILE_NAME%
@IF EXIST "%TEMP_FILE_PATH%" @(
@GOTO :loop
)
%RANDOM%
の桁数が保証されていないが、1桁ずつ切り出すのも効率が悪いため。0埋めして下の桁から切り出す感じ。ここで生成されたパスを先程の一連の変換処理で使う。ソース画像も引数にすると、こんな感じ。
(
@REM copy to tempfile.
copy /B /Y "%~1" "%TEMP_FILE_PATH%" > nul
) && (
@REM convert.
jpegtran -outfile "%TEMP_FILE_PATH%" "%TEMP_FILE_PATH%"
) && (
@REM move (overwrite).
move /Y "%TEMP_FILE_PATH%" "%~1" > nul
)
青果物
上記コマンドをベースに。利用形態別にbatfileを作成する。
Dropletは引数を全てファイルで使用するため、形式を指定出来ない。なので、 Baselineへ変換用
と Progressiveへ変換用
をそれぞれ設ける。
- jpegxproc.bat
- jpeg2baseline.bat
- jpeg2progressive.bat
以上3種。
① (簡易変換用) jpegxproc.bat
@SETLOCAL
@SET JPEGTRAN_HOME=jpegtran インストール先
@SET PATH=%JPEGTRAN_HOME%;%PATH%
@GOTO :l_main
:sub_conv
:l_sub_conv_init
@SET TEMP_FILE_NAME=
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET TEMP_FILE_PATH=%TEMP%\%TEMP_FILE_NAME%
@IF EXIST "%TEMP_FILE_PATH%" @(
@GOTO :l_sub_conv_init
)
@REM proc.
@(
@REM check JPEG process.
rdjpgcom.exe -verbos < "%~4" | findstr /C:"%~2" > nul
) && (
@REM copy to tempfile.
copy /B /Y "%~f4" "%TEMP_FILE_PATH%" > nul
) && (
@REM convert.
jpegtran %~3 -outfile "%TEMP_FILE_PATH%" "%TEMP_FILE_PATH%"
) && (
@REM move (overwrite).
move /Y "%TEMP_FILE_PATH%" "%~f5" > nul
) && (
@REM message.
ECHO %~1 "%~f4" =^> "%~f5"
)
@GOTO :EOF
:l_main
@SET OPT="%~1"
@SET SRC_FILE="%~2"
@SET TGT_FILE="%~3"
@SET WORKED=0
@IF %TGT_FILE% == "" SET TGT_FILE="%~2"
@IF %OPT% == "-baseline" (
@CALL :sub_conv "converted to baseline." "JPEG process: Progressive" "" %SRC_FILE% %TGT_FILE%
@SET WORKED=1
)
@IF %OPT% == "-progressive" (
@CALL :sub_conv "converted to progressive." "JPEG process: Baseline" "-progressive" %SRC_FILE% %TGT_FILE%
@SET WORKED=1
)
@IF %WORKED% EQU 0 (
@ECHO not work....
@ECHO ^( arguments : %* ^)
)
@ENDLOCAL
② (Droplet用) jpeg2baseline.bat
@SETLOCAL
@SET JPEGTRAN_HOME=jpegtran インストール先
@SET PATH=%JPEGTRAN_HOME%;%PATH%
@ECHO start. %DATE% %TIME%
@ECHO.
@GOTO :l_main
:sub_conv
:l_sub_conv_init
@SET TEMP_FILE_NAME=
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET TEMP_FILE_PATH=%TEMP%\%TEMP_FILE_NAME%
@IF EXIST "%TEMP_FILE_PATH%" @(
@GOTO :l_sub_conv_init
)
@REM proc.
@(
@REM check JPEG process.
rdjpgcom.exe -verbos < "%~4" | findstr /C:"%~2" > nul
) && (
@REM copy to tempfile.
copy /B /Y "%~f4" "%TEMP_FILE_PATH%" > nul
) && (
@REM convert.
jpegtran %~3 -outfile "%TEMP_FILE_PATH%" "%TEMP_FILE_PATH%"
) && (
@REM move (overwrite).
move /Y "%TEMP_FILE_PATH%" "%~f5" > nul
) && (
@REM message.
ECHO %~1 "%~f4" =^> "%~f5"
ECHO.
)
@GOTO :EOF
:l_main
@IF NOT "%~1" == "" (
@CALL :sub_conv "converted to baseline." "JPEG process: Progressive" "" "%~1" "%~1"
@SHIFT
@GOTO :l_main
)
@ECHO end. %DATE% %TIME%
@ECHO.
@ENDLOCAL
@pause
③ (Droplet用) jpeg2progressive.bat
@SETLOCAL
@SET JPEGTRAN_HOME=jpegtran インストール先
@SET PATH=%JPEGTRAN_HOME%;%PATH%
@ECHO start. %DATE% %TIME%
@ECHO.
@GOTO :l_main
:sub_conv
:l_sub_conv_init
@SET TEMP_FILE_NAME=
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET _R=00000%RANDOM%
@SET TEMP_FILE_NAME=%TEMP_FILE_NAME%%_R:~-5%
@SET TEMP_FILE_PATH=%TEMP%\%TEMP_FILE_NAME%
@IF EXIST "%TEMP_FILE_PATH%" @(
@GOTO :l_sub_conv_init
)
@REM proc.
@(
@REM check JPEG process.
rdjpgcom.exe -verbos < "%~4" | findstr /C:"%~2" > nul
) && (
@REM copy to tempfile.
copy /B /Y "%~f4" "%TEMP_FILE_PATH%" > nul
) && (
@REM convert.
jpegtran %~3 -outfile "%TEMP_FILE_PATH%" "%TEMP_FILE_PATH%"
) && (
@REM move (overwrite).
move /Y "%TEMP_FILE_PATH%" "%~f5" > nul
) && (
@REM message.
ECHO %~1 "%~f4" =^> "%~f5"
ECHO.
)
@GOTO :EOF
:l_main
@IF NOT "%~1" == "" (
@CALL :sub_conv "converted to progressive." "JPEG process: Baseline" "-progressive" "%~1" "%~1"
@SHIFT
@GOTO :l_main
)
@ECHO end. %DATE% %TIME%
@ECHO.
@ENDLOCAL
@pause
使い方
上記batfileはbatfileは jpegtran
のインストール先に合わせて修正する。
あと、batfile の置き場もお好みなので、とりあえず言及なし。
① (簡易変換用) jpegxproc.bat
まぁ取り立てて特別なこともなく。
FOR %A IN (*.jpg) DO jpegxproc.bat -baseline "%~A" "%~A"
FOR %A IN (*.jpg) DO jpegxproc.bat -progressive "%~A" "%~A"
② (Droplet用) jpeg2baseline.bat
以下の項目一緒にまとて記載。
③ (Droplet用) jpeg2progressive.bat
Droplet なので適当な場所にショートカット作るだけで良いのだけど。汎用的に sendto は Droplet を活用出来るので、利用頻度の高いものなどには結構オススメ。
shell:sendto
にショートカット を作成する。
① わかりやすく名前を買えると良い感じ。
送る
② ファイルを選択して
Getty - FLVSH ØUT には S-JIS に収録されていない Ø
が含まれていたが、正常に変換できる。
漢字
、全角記号
、カッコ ()
、アンパサンド &
、アポストロフィ '
なども特にエラー無く変換できる。
検証
変換実行
確認
FOR %A IN (*.jpg) DO @(rdjpgcom -verbos < "%~A" | findstr /C:"JPEG process: Progressive" > nul) && (ECHO JPEG process: Progressive %~fA )
変換前
変換後
ベースラインJPEGは1件も無くなってしまった...
ファイル比較
ちゃんと歯抜けで更新されている。
更新されたファイルには、追加で劣化した様なところは一応見受けられない。
Q&A
Q. batファイルに @
多くね?
A. そういうもん。
Q. ラベルの l_
って?
A. GOTOジャンプ
用のラベルとしての目印
Q. ラベルの sub_
って?
A. CALL
でで呼び出すサブルーチン用のラベルとしての目印
Q. なんか書き方変じゃない?
A. exit /b
なんか使ってたらろくな部品にならないからな。。。。そういうのも加味して書くと、上部にサブルーチン、下部にエントリ ポイントを持ってくる感じにするのは、そこそこ扱いやすい。
あとがき
なんとか一括変換環境が出来たので、クソ雑魚WALKMAN NW-A30でのMP3運用に向けた、アルバム アートのBaseline化にようやく動き出せる。これのお陰で、Rippingも多少止まっていたほど。。。
まぁギャップレス再生を加味すると、ATLACが使えるWALKMAN NW-Aシリーズが結局最強にはなってしまうのだけれどもね。ギャップレス再生もできないデバイスでMIX音源をどう聴けとな。代替のフォーマットもなく、NW-Sシリーズが非対応になり廃れていくのは、本当に勘弁しやがれ。
とは言っても、ATLACの音質はMP3以上に宜しくなく、x-アプリも使い勝手が悪いので。ファイル システムとの併用になりそう。
と言うところで、ローカルのFLACをMP3に変換して入れたところ、アルバム アートが表示されない楽曲がちらほらで、愕然としたわけで。。。。
このご時世にBaselineしか対応していませんって、意味がわかんないんですけど。チェック ツールとか、他にProgressiveで起きる問題とかもなかなか無いのに。。。。
jpegtranでロスレス変換が出来ることが分かってから、技術的には可能というのが判明したので、そこから1年近く一括変換方法を考えていた。結局既存のいい感じのフロント エンドも無く、自作するにもライブラリ調査などで死ぬほど時間かかりそうで中々アクション起こせなかったけど。
今回ようやっと、当初から思案していたbatfileレベルの実装が出来た感じ。
まぁ、jpegtranのwindowsバイナリがちゃんとUNICODE対応していてくれれば、全然問題なかったのにね。。。
画像管理ソフトも自前で作りたい気持ちもあるので。いずれ、普通のウィンドウ アプリで baseline
/ progressive
の確認・ロスレス変換が出来る様なGUIアプリを作りたい。
参考 (謝辞)
- New jpegtran features
https://jpegclub.org/jpegtran/
Discussion