Barcodes mit PostScript und PHP
Hier beschreibe ich eine mögliche Weise, 3-aus-9 – Barcodes über php als PostScript-Dateien direkt drucken zu lassen.
Grundlage hierfür war die Anforderung, Seriennummern als Barcodes auf Labels zu drucken.
Die in diesem Beispiel vorkommenden Positionen des Textes oder der Barcodes müssen wahrscheinlich an die eigenen Anforderungen angepasst werden.
Grundsätzlich wird eine Funktion in PHP geschrieben, in der der Text für die Postscript-Datei festgelegt wird.
Da PostScript ebenfalls über Funktionen und deren Aufrufe verfügt, stelle ich folgende als Grundlage dar.
Zuerst die Funktion, die die eigentliche Berechnung des Barcodes 3-aus-9 vornimmt.
Dann die Funktion, die den Barcode generiert und ausgibt.
%%Creator: CODE 3-of-9 GENERATOR sysalyser.de %%DocumentPaperSizes: A4 %%EndComments %%EndProlog /code39 { 0 begin /options exch def /useropts options def /barcode exch def /includecheck false def /includetext false def /includecheckintext false def /textfont /Courier def /textsize 20 def /textpos -22 def /height 0.7 def options { token false eq {exit} if dup length string cvs (=) search true eq {cvlit exch pop exch def} {cvlit true def} ifelse } loop /textfont textfont cvlit def /textsize textsize cvr def /textpos textpos cvr def /height height cvr def /encs [ (1113313111) (3113111131) (1133111131) (3133111111) (1113311131) (3113311111) (1133311111) (1113113131) (3113113111) (1133113111) (3111131131) (1131131131) (3131131111) (1111331131) (3111331111) (1131331111) (1111133131) (3111133111) (1131133111) (1111333111) (3111111331) (1131111331) (3131111311) (1111311331) (3111311311) (1131311311) (1111113331) (3111113311) (1131113311) (1111313311) (3311111131) (1331111131) (3331111111) (1311311131) (3311311111) (1331311111) (1311113131) (3311113111) (1331113111) (1313131111) (1313111311) (1311131311) (1113131311) (1311313111) ] def /barchars (0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*) def /barlen barcode length def includecheck { /sbs barlen 10 mul 30 add string def /txt barlen 3 add array def } { /sbs barlen 10 mul 20 add string def /txt barlen 2 add array def } ifelse /checksum 0 def sbs 0 encs 43 get putinterval txt 0 [(*) 0 textpos textfont textsize] put 0 1 barlen 1 sub { /i exch def barcode i 1 getinterval barchars exch search pop length /indx exch def pop pop /enc encs indx get def sbs i 10 mul 10 add enc putinterval txt i 1 add [barcode i 1 getinterval i 1 add 16 mul textpos textfont textsize] put /checksum checksum indx add def } for includecheck { /checksum checksum 43 mod def sbs barlen 10 mul 10 add encs checksum get putinterval includecheckintext { txt barlen 1 add [barchars checksum 1 getinterval barlen 1 add 16 mul textpos textfont textsize] put } { txt barlen 1 add [() barlen 1 add 16 mul textpos textfont textsize] put } ifelse sbs barlen 10 mul 20 add encs 43 get putinterval txt barlen 2 add [(*) barlen 2 add 16 mul textpos textfont textsize] put } { sbs barlen 10 mul 10 add encs 43 get putinterval txt barlen 1 add [(*) barlen 1 add 16 mul textpos textfont textsize] put } ifelse /retval 2 dict def retval (sbs) [sbs {48 sub} forall] put retval (bhs) [sbs length 1 add 2 idiv {height} repeat] put retval (bbs) [sbs length 1 add 2 idiv {0} repeat] put includetext { retval (txt) txt put } if retval (opt) useropts put retval end } bind def /code39 load 0 1 dict put
/barcode { 0 begin /args exch def /sbs [] def /bhs [] def /bbs [] def /txt [] def /barcolor (unset) def /textcolor (unset) def /bordercolor (unset) def /backgroundcolor (unset) def /inkspread 0.5 def /width 5.5 def /barratio 1 def /spaceratio 1 def /showborder false def /borderleft 3 def /borderright 3 def /bordertop 3 def /borderbottom 15 def /borderwidth 0.5 def /guardwhitespace false def /guardleftpos 0 def /guardleftypos 0 def /guardrightpos 0 def /guardrightypos 0 def /guardwidth 6 def /guardheight 7 def args {exch cvlit exch def} forall opt { token false eq {exit} if dup length string cvs (=) search true eq {cvlit exch pop exch def} {cvlit true def} ifelse } loop /barcolor barcolor cvlit def /textcolor textcolor cvlit def /bordercolor bordercolor cvlit def /backgroundcolor backgroundcolor cvlit def /inkspread inkspread cvr def /width width cvr def /barratio barratio cvr def /spaceratio spaceratio cvr def /borderleft borderleft cvr def /borderright borderright cvr def /bordertop bordertop cvr def /borderbottom borderbottom cvr def /borderwidth borderwidth cvr def /guardleftpos guardleftpos cvr def /guardleftypos guardleftypos cvr def /guardrightpos guardrightpos cvr def /guardrightypos guardrightypos cvr def /guardwidth guardwidth cvr def /guardheight guardheight cvr def /bars sbs length 1 add 2 idiv array def /x 0.00 def /maxh 0 def 0 1 sbs length 1 add 2 idiv 2 mul 2 sub { /i exch def i 2 mod 0 eq { /d sbs i get barratio mul barratio sub 1 add def /h bhs i 2 idiv get 72 mul def /c d 2 div x add def /y bbs i 2 idiv get 72 mul def /w d inkspread sub def bars i 2 idiv [h c y w] put h maxh gt {/maxh h def} if } { /d sbs i get spaceratio mul spaceratio sub 1 add def } ifelse /x x d add def } for gsave currentpoint translate width 0 ne { width 72 mul x div 1 scale } if newpath borderleft neg borderbottom neg moveto x borderleft add borderright add 0 rlineto 0 maxh borderbottom add bordertop add rlineto x borderleft add borderright add neg 0 rlineto 0 maxh borderbottom add bordertop add neg rlineto closepath backgroundcolor (unset) ne { gsave (< >) dup 1 backgroundcolor putinterval cvx exec {255 div} forall setrgbcolor fill grestore } if showborder { gsave bordercolor (unset) ne { (< >) dup 1 bordercolor putinterval cvx exec {255 div} forall setrgbcolor } if borderwidth setlinewidth stroke grestore } if gsave barcolor (unset) ne { (< >) dup 1 barcolor putinterval cvx exec {255 div} forall setrgbcolor } if bars { {} forall newpath setlinewidth moveto 0 exch rlineto stroke } forall grestore textcolor (unset) ne { (< >) dup 1 textcolor putinterval cvx exec {255 div} forall setrgbcolor } if /s 0 def /f () def txt { {} forall 2 copy s ne exch f ne or { 2 copy /s exch def /f exch def exch findfont exch scalefont setfont } { pop pop } ifelse moveto show } forall guardwhitespace { 0.75 setlinewidth guardleftpos 0 ne { newpath guardleftpos neg guardwidth add guardleftypos guardwidth 2 div add moveto guardwidth neg guardheight -2 div rlineto guardwidth guardheight -2 div rlineto stroke } if guardrightpos 0 ne { newpath guardrightpos x add guardwidth sub guardrightypos guardheight 2 div add moveto guardwidth guardheight -2 div rlineto guardwidth neg guardheight -2 div rlineto stroke } if } if grestore end } bind def
Als eigentlicher Punkt zählt natürlich die Ausgabe des Barcodes und des Textes, falls erforderlich.
Diese Angaben liegen außerhalb der genannten Funktionen und stellen die eigentliche Ausgabe dar.
Wie der Drucker die Ausgaben vornehmen soll, geben die Funktionen wider.
Die Variablen ($qwertz) kommen aus php…
/barcode load 0 1 dict put 11 600 moveto ('.($serialnumber).') (includetext) code39 barcode /Helvetica findfont 20 scalefont setfont 292 700 moveto (MusterFirma XY) show /Helvetica findfont 10 scalefont setfont 249 682 moveto (Musterstr. 23 # D-12345 Musterdorf) show 300 670 moveto (Tel. (+49) 1234 / 56789) show /Helvetica findfont 12 scalefont setfont 13 760 moveto ('.($artikel).') show 13 745 moveto ('.($matchcode).') show 13 730 moveto (Version '.($version).') show 1 setlinewidth 200 663 moveto 407 663 lineto stroke showpage
Da dies nur ein Beispiel ist, das bei Verwendung entsprechend angepasst werden soll, gehe ich nur auf wesentliche Punkte ein.
Der Befehl „moveto“ verschiebt die aktuelle Pixel-Position auf den angegebenen Wert.
Der Text (ob durch eine Variable in PHP oder statisch) in Klammern wird ausgegeben.
Mit „/Helvetica findfont 20 scalefont setfont“ wird eine Schriftart bestimmt. Diese muss natürlich dem System bekannt sein oder in PostScript dem Drucker bekannt gemacht werden. (Der Barcode selbst ist auch „nur“ eine Schriftart.)
Mit der Angabe „407 663 lineto“ können Linien angegeben werden, die durch „setlinewidth“ bestimmt wurden.
Da ich hier nicht auf die Syntax von PHP eingehe, gehe ich davon aus, dass die Generierung von Barcodes über diesen Code eigenständig klar wird:
<?PHP function print_labels ($serialnumber, $matchcode, $artikel, $version, $printer = '192_168_1_40') { $printtext = '%!PS-Adobe-2.0 %%Creator: BDE STOLFIG GMBH PRINTING SYSTEM %%DocumentPaperSizes: A4 %%EndComments %%EndProlog /code39 { 0 begin /options exch def /useropts options def /barcode exch def /includecheck false def /includetext false def /includecheckintext false def /textfont /Courier def /textsize 20 def /textpos -22 def /height 0.7 def options { token false eq {exit} if dup length string cvs (=) search true eq {cvlit exch pop exch def} {cvlit true def} ifelse } loop /textfont textfont cvlit def /textsize textsize cvr def /textpos textpos cvr def /height height cvr def /encs [ (1113313111) (3113111131) (1133111131) (3133111111) (1113311131) (3113311111) (1133311111) (1113113131) (3113113111) (1133113111) (3111131131) (1131131131) (3131131111) (1111331131) (3111331111) (1131331111) (1111133131) (3111133111) (1131133111) (1111333111) (3111111331) (1131111331) (3131111311) (1111311331) (3111311311) (1131311311) (1111113331) (3111113311) (1131113311) (1111313311) (3311111131) (1331111131) (3331111111) (1311311131) (3311311111) (1331311111) (1311113131) (3311113111) (1331113111) (1313131111) (1313111311) (1311131311) (1113131311) (1311313111) ] def /barchars (0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*) def /barlen barcode length def includecheck { /sbs barlen 10 mul 30 add string def /txt barlen 3 add array def } { /sbs barlen 10 mul 20 add string def /txt barlen 2 add array def } ifelse /checksum 0 def sbs 0 encs 43 get putinterval txt 0 [(*) 0 textpos textfont textsize] put 0 1 barlen 1 sub { /i exch def barcode i 1 getinterval barchars exch search pop length /indx exch def pop pop /enc encs indx get def sbs i 10 mul 10 add enc putinterval txt i 1 add [barcode i 1 getinterval i 1 add 16 mul textpos textfont textsize] put /checksum checksum indx add def } for includecheck { /checksum checksum 43 mod def sbs barlen 10 mul 10 add encs checksum get putinterval includecheckintext { txt barlen 1 add [barchars checksum 1 getinterval barlen 1 add 16 mul textpos textfont textsize] put } { txt barlen 1 add [() barlen 1 add 16 mul textpos textfont textsize] put } ifelse sbs barlen 10 mul 20 add encs 43 get putinterval txt barlen 2 add [(*) barlen 2 add 16 mul textpos textfont textsize] put } { sbs barlen 10 mul 10 add encs 43 get putinterval txt barlen 1 add [(*) barlen 1 add 16 mul textpos textfont textsize] put } ifelse /retval 2 dict def retval (sbs) [sbs {48 sub} forall] put retval (bhs) [sbs length 1 add 2 idiv {height} repeat] put retval (bbs) [sbs length 1 add 2 idiv {0} repeat] put includetext { retval (txt) txt put } if retval (opt) useropts put retval end } bind def /code39 load 0 1 dict put /barcode { 0 begin /args exch def /sbs [] def /bhs [] def /bbs [] def /txt [] def /barcolor (unset) def /textcolor (unset) def /bordercolor (unset) def /backgroundcolor (unset) def /inkspread 0.5 def /width 5.5 def /barratio 1 def /spaceratio 1 def /showborder false def /borderleft 3 def /borderright 3 def /bordertop 3 def /borderbottom 15 def /borderwidth 0.5 def /guardwhitespace false def /guardleftpos 0 def /guardleftypos 0 def /guardrightpos 0 def /guardrightypos 0 def /guardwidth 6 def /guardheight 7 def args {exch cvlit exch def} forall opt { token false eq {exit} if dup length string cvs (=) search true eq {cvlit exch pop exch def} {cvlit true def} ifelse } loop /barcolor barcolor cvlit def /textcolor textcolor cvlit def /bordercolor bordercolor cvlit def /backgroundcolor backgroundcolor cvlit def /inkspread inkspread cvr def /width width cvr def /barratio barratio cvr def /spaceratio spaceratio cvr def /borderleft borderleft cvr def /borderright borderright cvr def /bordertop bordertop cvr def /borderbottom borderbottom cvr def /borderwidth borderwidth cvr def /guardleftpos guardleftpos cvr def /guardleftypos guardleftypos cvr def /guardrightpos guardrightpos cvr def /guardrightypos guardrightypos cvr def /guardwidth guardwidth cvr def /guardheight guardheight cvr def /bars sbs length 1 add 2 idiv array def /x 0.00 def /maxh 0 def 0 1 sbs length 1 add 2 idiv 2 mul 2 sub { /i exch def i 2 mod 0 eq { /d sbs i get barratio mul barratio sub 1 add def /h bhs i 2 idiv get 72 mul def /c d 2 div x add def /y bbs i 2 idiv get 72 mul def /w d inkspread sub def bars i 2 idiv [h c y w] put h maxh gt {/maxh h def} if } { /d sbs i get spaceratio mul spaceratio sub 1 add def } ifelse /x x d add def } for gsave currentpoint translate width 0 ne { width 72 mul x div 1 scale } if newpath borderleft neg borderbottom neg moveto x borderleft add borderright add 0 rlineto 0 maxh borderbottom add bordertop add rlineto x borderleft add borderright add neg 0 rlineto 0 maxh borderbottom add bordertop add neg rlineto closepath backgroundcolor (unset) ne { gsave (< >) dup 1 backgroundcolor putinterval cvx exec {255 div} forall setrgbcolor fill grestore } if showborder { gsave bordercolor (unset) ne { (< >) dup 1 bordercolor putinterval cvx exec {255 div} forall setrgbcolor } if borderwidth setlinewidth stroke grestore } if gsave barcolor (unset) ne { (< >) dup 1 barcolor putinterval cvx exec {255 div} forall setrgbcolor } if bars { {} forall newpath setlinewidth moveto 0 exch rlineto stroke } forall grestore textcolor (unset) ne { (< >) dup 1 textcolor putinterval cvx exec {255 div} forall setrgbcolor } if /s 0 def /f () def txt { {} forall 2 copy s ne exch f ne or { 2 copy /s exch def /f exch def exch findfont exch scalefont setfont } { pop pop } ifelse moveto show } forall guardwhitespace { 0.75 setlinewidth guardleftpos 0 ne { newpath guardleftpos neg guardwidth add guardleftypos guardwidth 2 div add moveto guardwidth neg guardheight -2 div rlineto guardwidth guardheight -2 div rlineto stroke } if guardrightpos 0 ne { newpath guardrightpos x add guardwidth sub guardrightypos guardheight 2 div add moveto guardwidth guardheight -2 div rlineto guardwidth neg guardheight -2 div rlineto stroke } if } if grestore end } bind def /barcode load 0 1 dict put 11 600 moveto ('.($serialnumber).') (includetext) code39 barcode /Helvetica findfont 20 scalefont setfont 292 700 moveto (MusterFirma XY) show /Helvetica findfont 10 scalefont setfont 249 682 moveto (Musterstr. 23 # 12345 Musterdorf) show 300 670 moveto (Tel. (+49) 1234 / 56789) show /Helvetica findfont 12 scalefont setfont 13 760 moveto ('.($artikel).') show 13 745 moveto ('.($matchcode).') show 13 730 moveto (Version '.($version).') show 1 setlinewidth 200 663 moveto 407 663 lineto stroke showpage '; if (FALSE !== ($printfile = fopen("./include/tmp/print/{$serialnumber}.ps", "w"))) { fwrite($printfile, $printtext); fclose($printfile); } exec("/usr/bin/lpr -P {$printer} ./include/tmp/print/{$serialnumber}.ps"); } ?>
Das Kommando „lpr“ druckt hier zum Beispiel auf dem in cups bekannten Drucker „192_168_1_40″ den Barcode auf ein Label aus.