[今更誰得] PB-1000とFP-1100でグラフィック印刷 #カシオ #ポケコン


前回の記事の続きです。

mobileFF's blog: [今更誰得] PB-1000の印刷環境を作る #カシオ #ポケコン https://mobileff.blogspot.com/2021/10/pb-1000.html


カシオのポケコンPB-1000に、富士通アイソテックのFP-1100というレシートプリンタ(RS-232C接続)を繋いで、グラフィック印刷を試してみました。



とはいえ、どちらかというと話題的にはポケコンどうこうというより、単にESC/POS規格のコマンドを送信しただけという話なので、ポケコンネタと言えるかどうかはわかりませんがww

ESC/POSにはいくつかビットマップ画像を印刷するためのコマンドが用意されているのですが、中の人からみておそらく一番お手軽と思われる、「GS (L」コマンドで印刷してみました。

画像の大きさは256x256の2値画像(モノクロ2階調)です。

ESC/POS規格はエプソンがコマンドリファレンスを公開しているので、それを読めばある程度のことは試せるのですが、正直、わかりにくいというか、与える各パラメータの意味が理解しにくくて苦労しました。パラメータ指定のサンプルと説明くらい載せてくれても良いと思うのですが・・・印刷自体がうまくいった現時点でも、これ何の意味があるの?というパラメータが多いんですよね・・・

愚痴はともかく、手順ですが。

ざっくりいうと

① ビットマップデータを準備し、PB-1000に格納
② GS (L <機能112> でビットマップデータをプリンタに送信
③ GS (L <機能50> でプリントバッファに格納されたデータを印刷

という感じです。

① ビットマップデータを準備し、PB-1000に格納


以前、カシオのFP-40用にビットマップデータを作ったときのフォーマットは、カラム形式というかGPRINT形式というか、縦8ピクセルを1バイトとして、横に256バイト(256ピクセル)分のデータを作って、これを32セット(8ピクセルx32=256ピクセル)作るとできあがり、という感じでした。

ですが、今回はラスター形式のデータとなります。
カラム形式でもデータは渡せますが、FP-40のときとデータの並べ方が異なるため、結局は変換プログラムを作り直すことになるので、それならより直感的なラスター形式のほうが良いかな?ということでラスター形式のファイルにしてしまいます。

ラスター形式は横8ピクセルを1バイトとして、横にデータを並べていきますので、
1行(幅256ピクセル高さ1ピクセル)のデータ個数が32個、それを256行分ですから、32x256=8192バイト分のデータとなります。

加工が簡単なXPM形式の画像から、ラスター形式のビットマップデータ(文字列)を作成するJavaScriptプログラムを作りましたのでよろしければこちらからどうぞ。

XPMデータ(2値画像)をESC/POS印刷用ラスター形式イメージデータに変換
https://mobileff.blogspot.com/p/xpm2escpos.html

これを、PB-1000にRS232Cで転送します。PB-1000のメニューで[save]→[RS232C]→ボーレート等設定→[Enter]で受信開始します。

PB-1000側が受信状態になったら、PC側はPB-1000 Data Communicator32TeraTermなどでファイルを送信開始します。

PC側で送信が完了していても、PB-1000側で受信が完了しないことがありますが、そのときはBRKキーで強制終了すれば大丈夫なようです。

ちなみにPB-1000は拡張メモリRP-32を装着してもメインメモリは40KBしかないのですが、上述の方式で作成したビットマップデータは256x256だと16.8KBくらいある(ガチのバイナリデータにすればもっと小さくなるのですが・・・)ので、印刷用のプログラムも含めて20KBくらいは空きがないといけないので注意してください。

※それこそ、RS232Cポートが2系統搭載できれば、PCから受信しつつ、プリンタに出力、という方法も取れるかもしれないですがww

もしくは、PCから受信したデータを直接MD-100でFDに書き出して保存しておき、読み出しも直接FD上のファイルからということにすれば、メモリサイズ以上のデータも印刷できるかもしれないですね。

② GS (L <機能112> でビットマップデータをプリンタに送信


元データが用意出来たら、そのデータをプリンタに送信します。
ESC/POSのGS (Lの機能112がプリンタのバッファにイメージデータを転送するコマンドです。パラメータはこんな感じになります。

GS
  
(
  
L
  
pL
  
pH
  
m
  
fn
  
a
  
bx
  
by
  
c
  
xL
  
xH
  
yL
  
yH
  
d1...dk

各パラメータの詳細は以下のようになります。

(1) pL/pH

ビットマップデータを含めたパラメータの個数を設定します。256個を単位として、(256 x pH)個としてパラメータの個数を指定するのですが、端数(256で割ると余る数)があればpLで指定します。パラメータの個数はpL+(pH*256)となります。

例えば、

パラメータの個数が123個の場合・・・pL=123,pH=0
パラメータの個数が390個の場合・・・pL=134,pH=1

のようになります。

さて、ここで気をつけなければいけないのは、パラメータの個数というのは、ビットマップデータ(d1~dk)の数だけではなく、
その前にあるm~yHの個数も含む
というところです。これに気づけず中の人は最初ハマってましたw
(まあ、pLとpHでバイト数指定して、このあと何バイト読み込んだら打ち切り、っていうのは確かにシンプルで制御側としてはわかりやすいんでしょうけど・・・)

こいつらの個数は固定(今回の機能112では10個)なんだから指定に含めなくていいだろ~!って言いたくなりますが、これを忘れるとうまく印刷できません。

それと、ビットマップデータのパラメータの個数は、データは8ビット(高さ1 x 幅8)で1個ですから、256x256の画像の場合、横1列あたりのパラメータ数は256/8=32個です。高さも256ですから、
 
32個/行 x 256行 = 8192個

となり、さらに上記のパラメータ10個をプラスしますので、pL/pHの値は
pL=10,pH=32
となります。

(2) m,fn


mは固定で48です。
fnは機能112の実行なので112です。

(3) a

ビットマップデータの階調です。今回はモノクロ2階調なので48を指定します。

(4) bx,by

縦、横方向への表示倍率です。特に拡大が必要なければともに1(拡大縮小なし)にしておきます。

(5) c

色の指定です。モノクロの場合がどれなのかよくわからなくて、とりあえず49にしました。ちゃんと印刷できているのでこれでいいのだろうと思います。

(6) xL/xH

ビットマップデータの横幅です。これも基本はxH*256なんですが、256で割って余りがある場合はxLで端数を指定するわけですね。

今回のサンプルは256 x 256ピクセルなので、256で割っても当然余りは発生しません。
よって、xL=0,xH=1です。

(7) yL/yH

ビットマップデータの縦幅です。計算の考え方はxL/xHと同じです。
よって、yL=0,yH=1です。

(8) d1...dk

あとは、8192個のラスター形式のビットマップデータをひたすら送り込めば、機能112は終わりです。


③ GS (L <機能50> でプリントバッファに格納されたデータを印刷

ここまでが完了していればあとは簡単で、この<機能50>を指定するだけです。

fnで機能の番号を指定するのですが、2か50のどちらかを指定できるようなのですが、機能番号に合わせて50を指定しておきます。

と、こう書いてみますと、ごく大したことのないプログラムのように見えるのですが、いざ実行してみますと、8192個のデータをファイルから取り出しながら送信になるので、とにかくすごーく遅いです。

体感で10分前後かかったような気がします。
これで印刷できたーって喜んでもねぇ・・・っていう、まあ、完全に自己満足ですね。

プログラム例はこんな感じになります。

10000 ' ESC/POS PRINTER IMAGE PRINT
10100 PRINT "IMAGE PRINT TEST"
10110 PL=10:PH=32:A=48:BX=1:BY=1
10120 C=49:XL=0:XH=1:YL=0:YH=1
10130 ESC$=CHR$(27)
10140 GS$=CHR$(29)
10200 OPEN "COM0:7,N,8,1,N,N,N,B,N" AS #1
10210 'GS ( L (FN112): RASTER BIT IMAGE
10220 PRINT #1,GS$;"(L";CHR$(PL);CHR$(PH);CHR$(48);CHR$(112);CHR$(A);CHR$(BX);CHR$(BY);CHR$(C);CHR$(XL);CHR$(XH);CHR$(YL);CHR$(YH);
10250 LI=0:COUNT=PL
10300 OPEN "IMAGE.TXT" FOR INPUT AS #2
10400 IF (EOF(2))OR(COUNT=(PL+PH*256)) THEN 20000
10500 LINE INPUT #2,S$
10550 SLEN=LEN(S$)/2
10800 FOR I=1 TO SLEN
10900 PRINT #1,CHR$(VAL("&H"+MID$(S$,(I-1)*2+1,2)));
10950 COUNT=COUNT+1
11000 NEXT I
11010 PRINT RIGHT$(HEX$(LI),2);:LI=LI+1
11200 GOTO 10400
20000 'GS ( L (FN50): PRINT IMAGE
20100 PRINT #1,GS$;"(L";CHR$(2);CHR$(0);CHR$(48);CHR$(50);
20200 CLOSE #1
20300 CLOSE #2
20400 PRINT "COUNT:";COUNT;" LINE:";LI
		

※印刷イメージの表示には、PBロッキーさん(https://blog.pb-100.ga/)作の"hamura.css"(https://github.com/PB-100/hamura.css)を利用させていただいています。




現場からは以上です。




コメント