. .

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.

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>