Re: DVIOUT V3.18 の画像表示について

名前: hoge
日時: 2008-02-19 20:56:14
IPアドレス: 60.36.224.*

hoge@言い出しっぺです。反応が遅れて申し訳ありません。 pTeX 最新版 (08/02/17) で dviout.def が更新されているのを 確認しました。有難うございます。 ※何年か溜めてた疑問(世間では愚問=ゴミ)を問うては見たものの、 リアルタイムではこんなペースです(よく車の運転が出来るな>自分)。 >>50906 >"in" は余計です。 はい。余計でした(ツッコまれて良かった…)。 極端な大きさにして変化をみる実験のゴミコードが残っていました。 なので、 >>50863 > スタイルファイルでマクロ上書き」という不自然をしてます。 も嘘でした(暫く使っていたこちらは "in" は無いです)。 重ね重ね、すみませんでした。 -- ムダ話 ------------------------------------------------------------ DVIOUT は dvips 等他のドライバ向けの special もある程度受け入れるので、 それなら(本当は「そういえば」)ということで graphicx のオプション(*.def) 毎に、\special に於ける画像・図形の座標値の扱われ方を一覧にしてみました (hoge が注目するもののみ)。今時こういう使い方は少ないと思うので あまり意味は無いですが…(環境が様変わりしまくっている) ※"形式" (*.def ファイル中で採用されている "rule" の種類)でソート ※"精度" は整数 "I" と実数 "R" ※BB: BoundingBox(llx,lly 等), サイズ: 表示サイズ (\Gin@req@width等) ※数値のみで単位が明示されない場合は "(bp)" のように括弧書き ※dviout と dvipdfmx は大幅に変更(また嘘書いてるかも) *.def 形式 BB単位 精度 サイズ単位 精度 サフィックス例 dviout eps (bp) R (1bp/10) I eps/ps dvipdfm eps (bp) R (.1bp) I pdf/* dvipdfmx eps (bp) R pt R pdf/ps/eps/* dvips eps (bp) R (.1bp) I eps/ps/* dviout common * * pt R pbm/* dvipdfm bmp * * pt R jpg/jpeg/png dvipdfmx bmp (bp) R pt R jpg/jpeg/png/bmp dvips bmp * * bp R bmp/msp/pcx dvips oztex * * (bp) I pict/pntg 代用可能なオプションは、対応するラスタ形式(jpeg/png が可)と表示サイズ が pt で指定できることから(少し古い) dvipdfm が唯一の状態でしたが、 dviout.def の更新で素直に使えるようになりました。 ※ピッタリ合わせるには DVIOUT 本体に手を入れる必要がある ※dvipdfmx も DVIOUT で通らない→後述 こうしてみると、 Postscript 系の画像は(eps のラスタ形式に対しても) bp 単位ですが、その場合単位は省略されることが多いです。 また、画像サイズは 0.1bp 単位の整数値のみなので、 picture 環境で枠や目盛を描くと微妙にズレます。 ※dviout は一旦 10 倍してから 1bp で除しているので同じことになる。 ※唯一、最新の dvipdfmx が pt 単位で逸脱している(精度向上)。 他のラスタ形式 (pbm/jpg/png/bmp 等)の場合(表の下半分)は、 dvips の oztex 形式と(表には無いですが)旧 dviout が bp 単位の整数 になる以外は pt/bp の実数値で指定できるため、(変換誤差以外は) 精度が失われることは無く、また pt では、(ディメンジョンを \the で 出力すれば)単位も明示されます。 上にあげた例では "明示されない pt 値" というのはありません。 結局、(あくまで画像取り込みの special に限った話ですが) 1) 単位が明示されていればそれに従う 2) そうでなければ bp (1/72 in) として扱う 3) 表示サイズ rwi, rhi だけは 0.1bp 単位の整数として扱う として解釈すれば無難かと思います(気弱な表現)。 そこで 50906 で言われる通り、 epsbox.c の get_pt() 関数にスケールが必要です。 ==↓=========== epsbox.c(1454) if (...) return((float)sp/65536.0); epsbox.c(1455) else return(atof(sf)*1.00375); ==↑=========== この場合 50863 で指摘した箇所はやはり ==↓=========== epsbox.c(2064) width *= dpi/72.27; epsbox.c(2065) height *= DPI/72.27; epsbox.c(2066) // コメントアウト epsbox.c(2067) // ==↑=========== となります。あるいは関数名を get_bp() として ==↓=========== (1454) if (...) return((float)sp/(65536.0*1.00375)); (1455) else return(atof(sf)); --------------- (2064) width *= dpi/72.00; (2065) height *= DPI/72.00; ==↑=========== としても良いかもしれません。 但し、オリジナルの epsbox_pret() では special のそれぞれのキーに対して ・(単位が不要な)llx,lly 等は直接 atof() を用いている(従って bp 単位) ・(整数の) rwi,rhi は atoi()*0.100375 とスケール(pt 単位になる →オリジナルの epsbox.c(2064-2067) と矛盾) ・(単位を受け付ける)hsize,voffset 等は get_pt() で pt 単位に変換 (→無名数は pt 扱い→やはり矛盾) などと、扱いが異なるため、どちらかに統一して考える必要があります。 ガタガタ言う暇があったらテメェでコード書いたらどうだ>自分 -- さらにムダ話 ------------------------------------------------------ 以上は dviout.def の special を用いる場合にも、 他の special (dvips/dvipdfm) を用いる場合にも必要な DVIOUT 本体の変更です。 そもそも「一覧表」を作った当初の目的は「他の package オプションが 代用にならないか」というもので、 dvipdfm なら通るという結果だったの ですが、拡張された dvipdfmx を使いたいこともあります。 dvipdfmx.def (旧版) は dvipdfm と良く似た special を返していたので、 そのまま DVIOUT に持ち込めるかと思えばそうではありませんでした。 dvipdfm: \special{pdf: image width <w> height <h> depth 0.0pt(file)} dvipdfmx(旧): \special{pdf:image width <w> height <h> (file)} と、 "image" の前のスペースと "depth" 項目が無いだけで弾かれていました。 これだけなら該当の関数 pret.c/pdf_special() を緩くして変換した special を epsbox_pret() に丸投げすれば良いのかと思ってたら、 そうはいきませんでした。 "pdf: image" で取り込まれる画像の原点は左下なのですが、 DVIOUT が内部で用いている参照位置が左上なので、画像の高さ分 オフセットしてから下請け epsbox_pret() を呼び出すという 手順を取っています。…てことは、画像の高さを先読みして 解釈しなければならないということになります。 下請けの epsbox_pret() に於いては "width" や "height" は単位が ついているため、(bp/pt の違いは別にして)問題なく解釈されます。 ところが、直前の pdf_special() のコードは atof() となっており 単位を読んでいません。そしてこの数値は bp と解釈されていました。 ※pt と迷ったみたいで PT_TO_SP() マクロが残っている (^^; 従って、 \special で pt 単位で指定されたものが下請け epsbox_pret() で正しく解釈された場合、呼び出し側 pdf_special() では その数値を bp 単位で見ます。画像の高さに対して持ち上げ量が多いため 想定しているラインから微妙に「浮いた」結果になります。 ※A4 短辺 210mm を一杯に埋めた場合で約 0.79mm。 (DVIOUTの) V3.18 では epsbox_pret() も bp 扱いしているので、 この「浮き」は相殺されますが、その分サイズが狂うという訳です。 それで pret.c(2165-2219) の pdf_special() 関数を置き換える 私案 [1] を持ってきたのですが、これは不完全です。 ※バッファ長が決め打ちだったり、 key の順序が 固定だったりもしますが… ※単位を解釈するため関数が2つに分かれています。 dvipdfmx.def が更新されて BoundingBox が追加された分、 表示サイズの一方のパラメータが省略されるようになりました。 そのため、表示サイズの高さ情報が無い場合、オフセット値を 算出できません。 残りのパラメータから推定する場合は、 graphicx.sty 等が既に行って いる、あるいは下請けでやるであろう計算を2重に行うことになります。 いっそ文字列として組替えて epsbox_pret() に丸投げした方が 良いのでは?と思います(単位を解釈しなくて済む)。 ※dvipdfmx.def を先祖帰りさせれば割と短くなるのですが、 (ちょっとの変更で)サポート形式が増やせる思ったのが甘かった。 ま、文章共々ゴミみたいなものなので、そのまま付けてしまいます。 長くなりました。失礼します。 hoge == ↓[1] ============================================================= static SCALED_PT get_sp(char *sf) { int length_to_sp(char *, SCALED_PT *); SCALED_PT sp; if (length_to_sp(sf, &sp) == 0) return sp; else return atof(sf)*(65536.0*1.00375); /* (とりあえず)bp 扱い */ } static BOOL pdf_special(const char *special) { char tmp[1024], *t; char llx[32], lly[32], urx[32], ury[32]=""; char w[32]="", h[32]="", d[32]=""; const char *f, *g, *e; /* ファイル名, 走査用, 終端 */ int p = 0; sscanf(special, "pdf: image%n", &p); if(!p)return FALSE; special += p; if(4==sscanf(special, " bbox %30s %30s %30s %30s%n" , llx, lly, urx, ury, &p)) special += p; #define SC(key, var) \ if(1==sscanf(special, " " #key " %30[^( ]%n", var, &p)) \ special += p; SC(width, w) SC(height, h) SC(depth, d) #undef SC if(!*h)return FALSE; /* 現状逃げ */ if(!*ury && (!*w || !*h))return FALSE; f = special; while(*f && *f == ' ')f++; if(*f++ != '(')return FALSE; g = e = f; while(*g) /* 最後の閉じ括弧を探索 */ { if(*g == ')')e = g; g++; } if(e - f > 750)return FALSE; t += sprintf(t=tmp, "bmpfile=\"%.*s\"", e-f, f); if(*ury)t += sprintf(t, " llx=%s lly=%s urx=%s ury=%s" , llx, lly, urx, ury); if(*w)t += sprintf(t, " hsize=%s", w); if(*h)t += sprintf(t, " vsize=%s", h); { SCALED_PT sx, sy, dy; if(*d)dy = get_sp(d); /* depth が有ったら */ else dy = 0; dy -= get_sp(h); get_current_xy(&sx, &sy); set_current_xy(sx, sy+dy); if (!(epsbox_special)(tmp)) error(WARNING, "Cannot interpret special %s", special); set_current_xy(sx, sy); } return TRUE; } == ↑[1] =============================================================

この書き込みへの返事:

お名前
題名 
メッセージ(タグは <a href="...">...</a> だけ使えます。適宜改行を入れてください)