Epson Print CDからの画像救出作戦報告!(PNG/JPEG抽出の実践記)

[主題]
Epson Photo+が見つけられなかったEpson Print CD書類内部の画像を救出するまでの経緯を説明したい。

[背景]
Epson Print CDおよびEpson Photo+は、いずれもIntelベースのアプリケーションである。Appleシリコン搭載Macで、これらを起動するにはRosetta 2の助けが必要だ。しかし、そのRosetta 2もすでにサポート終了予定が公表されている。
こうした事情から、筆者は以前の記事で説明したとおり、ディスクレーベル印刷の環境をEpson Photo+からAdobe Photoshopへ移行した。
そして最近、Epson Print CDで作成した既存書類をPhotoshop形式へ移し替える作業に着手した。

作業手順はシンプルだ。
Epson Print CD書類をEpson Photo+で開き、埋め込まれた画像を抽出、それをPhotoshop上で再レイアウトする――という流れである。

ところが…である。
あるEpson Print CD書類をEpson Photo+で開いたところ、埋め込まれているはずの画像3点のうち、1点が見つからないという事態に遭遇した。
本稿は、その行方不明の画像を救出するまでの紆余曲折の記録である。

[環境]
参考までに、筆者の環境を記載しておく
MacBook Air 2023 15.3inch(Apple Silicon Mac, M2)
macOS Tahoe 26.3
Xcode 26.3
CommandLine Tools for Xcode 26.3.0.0.1

[結論]
Epson Print CD書類にはJPEG/PNGが生のまま埋め込まれており、コマンドライン(grep/dd)またはImHexで救出可能である。

[彷徨の履歴]
結論に至るまでの彷徨(?)の履歴を、かいつまんで記録しておく。

Epson Photo+でEpson Print CD書類を開くと、埋め込まれている画像はTIFF形式で書き出される。参考までに、その保存先はホームディレクトリの以下の場所になる。

ピクチャ/EPCDImages

このことから筆者は、Epson Print CD書類内部でも、画像がTIFFフォーマットで埋め込まれているのではないかと考えた。macOS環境では、画像処理にTIFFが多用されることも、そう考えた理由のひとつである。
そこで、バイナリエディタでEpson Print CD書類を開いて見た。

TIFFファイルは、エンディアンの違いにより2種類のヘッダを持つ。

リトルエンディアン

49 49 2A 00

ビッグエンディアン

4D 4D 00 2A

確認の結果、書類からは、ビッグエンディアンであることを示す後者のTIFFヘッダがひとつだけ見つかった。この書類を作成した際に使用した画像は3個である。これはおかしい。

次に試したのは、TIFFよりも一般的な画像フォーマットであるJPEGである。JPEGは、

FFD8FF

から始まり、終端は

FFD9

である。
検索の結果、この開始位置と終了位置(オフセット)は簡単に見つかった。

FFD8FF 0x2A9
FFD9 0x67084

ところが、書類を開いたバイナリエディタ(Hex Fiend)で、その範囲選択がどうしてもできない。
色々試したが、どうやらHex Fiendは、画像データのように比較的大きな範囲を選択するのには向いていないようだ。そこで、GUIではなくCLI(ターミナル)を使ってJPEGデータを抽出して見る事にした。

先ほどのJPEG開始位置と終了位置(オフセット)をddコマンドで処理するために16進数(Hex)を10進数に変換する。

printf "%d\n" 0x2A9 = 681
printf "%d\n" 0x67084 = 422020

後は、単純な引き算(ただしFFD9まで含めるため、結果に2バイト加算する)で、

422020-681+2=421341

得られる421341(バイト)がサイズである。

ddコマンドはifに入力ファイル名、ofに出力ファイル名、skipにファイル先頭からのオフセット、そしてcountに上で計算したサイズを指定する。最終的に以下のようになる。

dd if="input.printcd2" \
of=extracted.jpg \
bs=1 skip=681 count=421341

得られたJPEG画像は、このレーベル印刷の背景に使用しているものだった。この方法ならば、確かに画像が抽出できる事が確認された。ただし、ちょっと複雑で分かりにくい。

レーベル印刷データを作成した時に使用した画像は、背景JPEGの他、2点である。この2つは透過PNGである。JPEGが、そのまま埋まっているのならば、PNGも埋まっている可能性が高い。

PNGは、8バイトの署名に続いて、IHDRからIENDまでのチャンク列で構成される。JPEG画像の抽出が、コマンドでうまく行った事に気を良くして、まずはこのPNG署名を探して見る事にした。

LC_ALL=C grep -aob $'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A' "input.printcd2"

ところが…。
何も出力されなかった。これはおかしい。では、PNGの実データ(チャンク列)はあるだろうか?
PNGデータの先頭(IHDR)と終端(IEND)をgrepコマンドでフィルタして見る。

grep -aob IHDR "input.printcd2"
grep -aob IEND "input.printcd2"

やはりあった。それぞれ…。

422251:IHDR
434511:IHDR
433854:IEND
491852:IEND

であれば、実データを抽出、それに署名(PNGシグネチャ)をフランケンシュタインのようにくっつければ良いだろうと考えた。

さて、求めるPNG実データ開始位置はIHDRの4バイト前である。

422251-4=422247
434511-4=434507

計算過程は、JPEGの時と同様のため省略するが、PNG実データ(チャンク列)を抽出するddコマンドは、以下の通りである。

dd if="input.printcd2" \
of=png1.raw \
bs=1 skip=422247 count=11619
dd if="input.printcd2" \
of=png2.raw \
bs=1 skip=434507 count=57357

PNG署名は

printf '\x89\x50\x4E\x47\x0D\x0A\x1A\x0A' > sig.bin

署名と実データ(チャンク列)の合体:

cat sig.bin png1.raw > png1.png
cat sig.bin png2.raw > png2.png

抽出できた。だが、手順はJPEGの時よりも、さらに込み入っている。本当にPNG署名はない(削られている)のだろうか?

ここで、もう一度Hex Fiendを使ってPNG署名を検索して見たところ、ちゃんと2点見つかった。つまり、コマンドラインでは、何らかの理由でPNG署名をgrepできなかったのだ。
察しの良い方なら既にお気付きかもしれないが、その一因として、PNG署名に含まれる

0x0D0x0A

すなわち改行コード(CR/LF)の存在が考えられる。BSD grepは改行をレコード区切りとして扱う実装のため、バイナリ中のパターン検索が期待通りに動作しない場合があるのだ。

試しに、PNG署名を改行コードの手前で切ったもの

LC_ALL=C grep -aob $'\x89\x50\x4E\x47'

でgrepすると、ちゃんと結果が出た。

しかし、JPEG抽出の項でも述べた通り、Hex Fiendでは、広い領域の「ここからここまで」という選択は、できなくはないが、ひどく骨が折れる。どうすれば良いだろうか?

色々調査した結果、macOSをサポートし、かつ無料で使える、もうひとつのバイナリエディタがある事が分かった。ImHexが、それである。
ただ、ImHexは開発者による署名がされていない。利用するためには、次のようにして、起動を許可する必要がある。(Sentinelを使っても良いが、いずれにしても自己責任でお願いしたい)

xattr -d com.apple.quarantine /Applications/ImHex.app

参考までに、ImHexを用いたPNG抽出手順を書いておく。

  1. ImHexで、Epson Print CD書類を開く
  2. 表示メニューから検索を選ぶ
  3. 16進数で「89504e470d0a1a0a」を検索、アドレスをメモする
  4. asciiで「IEND」を検索、アドレスをメモする
  5. 編集メニューから、「選択」(Shift+⌘+A)を選び、開始と終了アドレスを入力、selectボタンを押す
  6. ファイルメニューから、エクスポート… > Selection to File…を選び、画像を保存する

[本件から分かった事]
以下の事が分かった。

  • Epson Print CDには、JPEG/PNG画像が、そのまま埋めこまれている
  • grep/ddコマンドにより、画像を抽出する事はできる。ただし、多少計算が面倒
  • PNG署名を、macOSのgrep(BSD系)で検索する際は、改行コード(0x0D0x0A)を含まないように注意する必要がある
  • Hex Fiendは、画像等の大きなサイズを範囲選択するのには向いていない
  • ImHexを用いれば、GUIでの画像抽出は可能だが、開発者署名がないので対応が必要

参考サイト

以上。

この投稿へのコメント

コメントはありません。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

この投稿へのトラックバック

トラックバックはありません。

トラックバック URL