miauのブログ

はてなダイアリー「miauの避難所」をはてなブログに移行しました

eps2jpg を使う際の注意点

現在の顧客はカタログで販売していた商品/サービスを Web システムに展開した経緯があり、「印刷会社から DTP データを受け取って Web サイトに載せる」という作業が多いのですが。

今日も受け取った画像ファイルが .eps ファイルだったので、Web サイトに載せるべく .jpg 等に変換する方法を調べてみると、

というページがヒットしまして。

ページ先頭にあるように ImageMagick を使えば早いんですが、気づかずに eps2jpg(eps2png)でがんばってしまったので、とりあえずハマった点のメモです。ImageMagickCMYK データ(?)で色がおかしくなってしまうことがあるようですし、何か役にたつかもしれません。

前提

  • ActivePerl と Ghostscript は元々入ってたのでその手順は書きません
  • Windows XP、ActivePerl 5.8.9.825、Ghostscript 9.00 の環境で試しました

eps2jpg のインストール

(2011-01-15 追記)私が編集したバージョンへのリンクが最後のほうにありますので、よろしければそちらをお使いください。

CPAN モジュールなら cpan コマンドでインストールできると思ったんですが、なぜかうまくいきませんでした。このページに解説があるとおり、CPAN 内のページ から「Download」をクリックして .tar.gz を落とすのがいいみたいです。

展開して src/eps2png.pl をパスが通ってる場所にコピーします。私は Ghostscript のパス(C:\gs\gs9.00-\bin)に入れておきました。

このとき eps2jpg 等の別名でコピーしておき、perl eps2jpg のように実行すると、-jpg 等のオプションを省略できるので楽なんですが、スクリプトのフルパスを指定するのは面倒ですし、後述するようにスクリプトに変更が必要だったりもするので私はコピーしていません。

gswin32c.exe のコピー

Windows 上では gs はgswin32c.exe という名称でインストールされるので、この参考サイトでは Perl スクリプト側を変更しているみたいですが、私は gswin32c.exe のほうを gs.exe にコピーしておきました。

eps2png.pl のエラー回避1

(2011-01-15 追記)こちらも末尾のバージョンを使えば不要です。

ではさっそく

eps2png.pl -resolution 300 -verbose -trace C:\001_1.eps

のようにして実行してみると・・・(元サイトを真似て -resolution を指定していますが、あまり意味はありません。また、ここではあまり関係ありませんが、エラーを追いやすいように -trace オプションをつけています。)

Producing png (png16m) image.
No bounding box in C:\001_1.eps

のようなエラーになってしまいます。

原因は .eps ファイルが改行コード CR で生成されていたことで、XMP を見ると xmp:CreatorTool が「Adobe Photoshop CS4 Macintosh」になっていたので、よくわかりませんが Macintosh で生成されるとこうなるみたいです。

対策は、ファイル読み込み処理の前(適当でいいです。16 行目あたり?)に

$/ = "\r";

を入れること。これだと改行コード CR で決め打ちになってしまうのであまり汎用性はないのですが、とりあえず回避策ということで。

eps2png.pl のエラー回避2

スクリプトを変更して再度実行すると、

Producing png (png16m) image.
C:\001_1.eps: x0=0, y0=0, w=175, h=126, width=730, height=526
Creating C:\001_1.png
+ gs -q -dNOPAUSE -r300 -g730x526 -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=png16m -sOutputFile=C:\001_1.png -
>> (C:\001_1.eps) run
>> showpage
>> quit
Error: /ioerror in --run--
Operand stack:
   (C:\001_1.eps)   (r)
Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   fa
lse   1   %stopped_push   1942   1   3   %oparray_pop   1941   1   3   %oparray_pop   1925   1   3   %oparray_pop   1819   1   3   %oparray_pop   --nostringval-
-   %errorexec_pop   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   1942   1   3   %oparray_pop   --nos
tringval--
Dictionary stack:
   --dict:1166/1684(ro)(G)--   --dict:0/20(G)--   --dict:79/200(L)--
Current allocation mode is local
Last OS error: Invalid argument
GPL Ghostscript  9.00: Unrecoverable error, exit code 1
cmd close:

のようなエラーになってしまいます。

まあパスの扱いが怪しそうなので、

eps2png.pl -resolution 300 -verbose -trace C:/001_1.eps

のようにパスの区切りを「\」でなく「/」にするとうまく動作して、C:/001_1.png が生成されました。

.jpg を生成するには、

eps2png.pl -jpg -resolution 300 -verbose -trace C:/001_1.eps

のように -jpg オプションとかを付加すればよいです。

あとは -width 等を適切に設定すれば完了、と。縮小アルゴリズムは Nearest neighbor 法か何かで汚い感じなので、一度大きめの画像で出力して縮小したほうがよさそうです。

2011-01-15 追記

受領した .eps に改行コード CR のものと LF のものが混ざっていたようで、CR 固定ではうまく動作しませんでした。
どちらでも動作するように変更したバージョンを

に置いていますので、よろしければどうぞ。

diff はこんな感じです。(gist に変更前のバージョンあげておけば gist 側で diff 見れたんでしょうけど・・・取り急ぎ。)

--- eps2png.pl.org	Wed May 20 22:55:23 2009
+++ eps2png.pl	Fri Jan 14 12:11:02 2011
@@ -69,9 +69,21 @@
 	next;
     }
 
-    my $line = <EPS>;
-    unless ( $line =~ /^%!PS-Adobe.*EPSF-/ ) {
-	print STDERR ("Not EPS file: $eps_file, skipped\n");
+    my $eol;
+    do {
+	local $/;
+	my $buffer = <EPS>;
+	unless ( $buffer =~ /%!PS-Adobe[-\d.]* EPSF-[\d.]*([\r\n])/ ) {
+	    print STDERR ("Not EPS file: $eps_file, skipped\n");
+	    $err++;
+	    next;
+	}
+	$eol = $1;
+    };
+    $/ = $eol;
+
+    unless ( open (EPS, $eps_file) ) {
+	print STDERR ("Cannot open $eps_file [$!], skipped\n");
 	$err++;
 	next;
     }
@@ -85,7 +97,7 @@
     my $width = $width;
     my $height = $height;
 
-    while ( $line = <EPS> ) {
+    while ( my $line = <EPS> ) {
 
 	# Search for BoundingBox.
 	if ( $line =~ /^%%BoundingBox:\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/i ) {
  • ファイルを一気に読み込んで EPS のヘッダを探す
    • サムネイルつきのもの(?)は先頭にバイナリデータが大量に入っていて、「先頭の n バイトを読んでチェックする」みたいな手が使えなかったので
  • EPS ヘッダ行末の改行コードを区切り文字としてファイルを読み込みなおす

というような処理になっています。

あと、Windows 環境で実行すると、Shift_JIS の 2 byte 目が \x5c になっているファイルでエラーになってしまうようです。回避策はよくわからなかったので、一旦日本語を含まないファイルにコピーして変換をかけて回避しています。