Troubleshooting distorted or cut-off images printed by the Dymo CUPS driver for Linux.
以前に、こんな記事を書かせて頂いたことがあります。
Dymo 社の LabelWriter シリーズは、技術マニュアル等が公開されていて、面白いラベルプリンタです。また、最近はあまりアップデートされていないようですが、Linux 用の CUPS ドライバも公開されており、これまた好感を覚えます。
しかしながら、上記のブログ記事を書いた時から、特定の画像イメージをプリントする際に画像がゆがんだり途切れてしまったりする問題に悩まされていました。こんな感じです。
上のラベルは(ほぼ)正常にプリントされるのですが、下のラベルは「30」という表示の途中で画像が途切れてしまい、またゴミがプリントされています。(この現象は決定論的(deterministic)で、上の例で見るように、日付の末尾が「0」のときに、必ず再現するという不思議な現象です。)
私は長い間、これが Dymo 社の CUPS ドライバの問題だと思っていたのですが、対応が面倒くさくてずっと放置していました。最近になって、ちょっと時間の余裕があったので分析してみた次第です。
ちなみに、トラブルが発生しているバージョン(環境)は下記の通りです。
- Raspberry Pi Model B(revision 000e)← Raspberry Pi 2 でも 3 でもない、無印 Model B です
- Raspbian GNU/Linux 7 (wheezy) ← 相当古いです
- CUPS 1.5.3
- dymo-cups-drivers-1.4.0.5
CUPS ドライバのインストールについて
私も以前にブログで触れたことがありますが、既に 5年程度経って情報が古くなっているので、他の方が書かれた新しい記事にリンクを張らせて頂きます。
これを御覧頂くと分かるように、Dymo LabelWriter を Linux から使うには、CUPS(Common UNIX Printing System)というソフトウェアと、特定のプリンタ(ここでは Dymo LabelWriter)用の CUPS ドライバが必要になります。
私は以前から、上記のトラブルは Dymo 用のドライバのバグではないかと勘ぐっていたのですが、実はそうではなかった(ギャフン)というのが、今回の記事の主題です。
問題の分析
私は CUPS についての知識がほとんどないので、どこから手を付けて良いか分からなかったのですが、以下のサイトを参考に、Dymo の CUPS ドライバが、ラスタイメージを LabelWriter 専用の page description language(PDL。懐かしい用語だ!)に変換した結果を盗み見る方法を見つけました。
つまり、ドライバのインストールされたホストで、次のようなコマンドを実行することで、印刷結果を USB から出力するのではなく、PDL のストリームをファイルに落とすことができるのです。
$ lpadmin -p dymo_debug -v file:/tmp/dymo_debug.dat -P /usr/share/cups/model/lw450t.ppd
ちなみに、ドライバ(バイナリ実行ファイル)の正体は、こんなところにあります。
/usr/lib/cups/filter/raster2dymolw
さて。上記のように dymo_debug(ダミー)プリンタをセットアップしたら、さっそく問題の画像を PDL に変換してみましょう。
lpr -P dymo_debug -o ppi=300 -o media=w72h154.1 /tmp/trouble.png
これにより、
/tmp/dymo_debug.dat
というファイルが出力されます。ファイル名は、上で lpadmin で指定したものです。
このファイルを hex ダンプすると、こんな結果になります。
00000000 1b 1b 1b 1b 1b 1b 1b 1b 1b 1b 1b 1b 1b 1b 1b 1b |................| * 00000130 1b 1b 1b 1b 1b 1b 1b 1b 1b 51 00 00 1b 42 00 1b |.........Q...B..| 00000140 68 1b 65 1b 4c 02 7d 1b 66 01 ac 1b 42 09 1b 44 |h.e.L.}.f...B..D| 00000150 03 16 01 5f 68 1b 42 09 1b 44 04 17 00 98 05 1b |..._h.B..D......| 00000160 42 08 1b 44 05 17 04 a0 01 1b 42 08 1b 44 06 17 |B..D......B..D..| 00000170 02 a5 06 1b 42 08 17 00 a9 04 1b 42 07 1b 44 07 |....B......B..D.| 00000180 17 06 ac 03 1b 42 07 17 05 af 01 1b 42 07 17 04 |.....B......B...| 00000190 b1 00 1b 42 07 17 03 8f 12 80 00 8e 1b 42 07 17 |...B.........B..| 000001a0 03 8b 1b 8b 1b 42 07 1b 44 08 17 02 89 21 89 06 |.....B..D....!..|
思わず深呼吸をしたくなりますが、このような作業は、私が昔から取り組んできた仕事に似ているので、昔取った杵柄(?)で、デコーダを書いてみます。参考にしたのは、冒頭で触れた技術マニュアル LabelWriter 450 Series Printers Technical Reference Manual と、Dymo CUPS ドライバ 1.4.0.5 のソースコード(特に、src/lw/LabelWriterDriver.cpp)です。
苦労して(半日ほどで)書いたコードが、こちらです。
Python 3 と Pillow ライブラリが必要です。実行すると、標準出力にこんなメッセージが得られます。
send_line_tab: 0 0 set_dot_tab: 0 text_speed_mode: set_print_density: NORMAL set_label_length: 637 (2.12 in) skip_n_lines: 172 set_dot_tab: 9 set_bytes_per_line: 3 transfer_print_data: 0x1 0x5f 0x68 set_dot_tab: 9 set_bytes_per_line: 4 transfer_compressed_print_data: 0x0 0x98 0x5 set_dot_tab: 8 set_bytes_per_line: 5 transfer_compressed_print_data: 0x4 0xa0 0x1 (続く)
最後に、デコードした画像が表示されます。(プリンタに対して出力されるデータは、この画像の左上から始まり、水平に走査して、右下で終わります。)
私は、何かしら問題の修正に貢献できるかと妄想していたので、(失礼ながら)非常にがっかりしました。画像を見ると分かるように、Dymo の CUPS ドライバは、正しくイメージを PDL に変換していたのです。つまり、問題は CUPS ドライバではなかった、ということです。
そうなると、問題は CUPS ライブラリそれ自身か、Dymo CUPS ドライバとのインテグレーションに依るものではないかという感じがしてきました。つまり、新しい Linux OS を Raspbery Pi OS にインストールし直して、CUPS を新しいものに置き換えない限り、トラブルシュートは完了しない訳です。
さすがにそれはしんどくなったので、私は小さなワークアラウンドを考えました。それは、オリジナル画像の右下(つまり、上記画像でいうところの右上)あたりに、小さな黒ピクセルを置いてみたらどうだろう、というものです。ImageMagick を調べて、日付印刷用のコードを次のように修正しました。
#!/bin/sh
export TZ
TZ=JST-9
d=`date +%Y/%m/%d`
t=`date +%H:%M`
convert -font Helvetica -size 530x210 -pointsize 80 -gravity West label:$d'\n'$t /tmp/printdatetime.png
# これを追加
mogrify -draw "point 529,209" /tmp/printdatetime.png
lpr -o ppi=300 -o media=w72h154.1 /tmp/printdatetime.png
rm /tmp/printdatetime.png
途中で、mogrify というコマンドで右下にドットを描いています。(なお、ここでの ImageMagick コマンドは、現在では legacy 版のものだそうですので、最新の ImageMagick では構文が違うかも知れません。)
これで、無事に次のようなラベルが得られました。右下に小さなドットが描かれているのが分かりますでしょうか。
パチパチパチ…。問題の根本解決にはなっていないのですが、今回は力尽きたので、ここまでとします。御清聴ありがとうございました。
おまけ
Dymo 社は、もう Linux 版の CUPS ドライバを更新する気がない(担当者が外れてしまった)ようですが、これを独自に保守している人たちがいらっしゃいます。バグの修正などもなさっているようです。実は、私が上記のデコード作業をする前にこちらを覗いてみて、私の抱えている問題の原因は Dymo CUPS ドライバのバグに違いない! と(勝手に)妄想したのですが、既に述べてきたように、そうではありませんでした。がっかり。。。