pass args as one or multiple arguments delimited by spaces
[Printer-Zebra.git] / ZPL2pbm.pl
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use autodie;
5 use Data::Dump qw(dump);
6
7 # convert Zebra label printer ZPL to pbm image
8
9 my $command;
10 while(<DATA>) {
11         chomp;
12         my ( $cmd, $desc ) = split(/\s/,$_,2);
13         $command->{$cmd} = $desc;
14 }
15
16 my $file = shift @ARGV || die "usage: $0 dump.zpl > dump.pbm";
17
18 open(my $in, '<', $file);
19
20 our $line = '';
21 sub slurp_line {
22         $line .= <$in> unless length $line > 3;
23 }
24 slurp_line;
25
26 while( $line ) {
27         $line =~ s/[\r\n]+$// && warn "## removed CR/LF\n";
28         warn "# line ",dump($line),$/ if length($line) < 80 or $ENV{DEBUG};
29         if ( $line =~ s/~DG(\w+:)?(.+)// ) {
30                 my ( $name, $t,$w ) = split(/,/,$2,4);
31
32                 warn "# ~DG$1 => [$name] t=$t w=$w\n";
33
34                 my $data = <$in>;
35
36                 my $out;
37                 # ZPL decompress
38                 my $repeat = 0;
39                 foreach my $p ( 0 .. length($data) - 1 ) {
40                         my $c = substr($data,$p,1);
41                         if ( $c eq ',' ) {
42                                 my $l = ( $w * 2 ) - length($out) % ( $w * 2 );
43                                 $l = $w * 2 if $l == 0;
44                                 warn "# $p ZERO-to-EOL $c [$l]\n";
45                                 $out .= "0" x $l;
46                         } elsif ( $c eq '!' ) {
47                                 my $l = ( $w * 2 ) - length($out) % ( $w * 2 );
48                                 $l = $w * 2 if $l == 0;
49                                 warn "# $p ONE-to-EOL $c [$l]\n";
50                                 $out .= "F" x $l;
51                         } elsif ( $c eq ':' ) {
52                                 $out .= length($out) > $w ? substr($out,-$w*2) : "00" x $w;
53                                 warn "# $p repeat last line\n";
54                         } elsif ( $c eq 'z' ) {
55                                 $repeat += 400;
56                         } elsif ( $c ge 'g' && $c le 'y' ) {
57                                 $repeat += 20 * ( ord($c) - ord('f') );
58                         } elsif ( $c ge 'G' && $c le 'Y' ) {
59                                 $repeat += ord($c) - ord('F');
60                         } elsif ( $c =~ m/[0-9A-F]/i ) {
61                                 if ( $repeat ) {
62                                         warn "# $p $repeat $c\n";
63                                         $out .= $c x $repeat;
64                                         $repeat = 0;
65                                 } else {
66                                         warn "# $p hex $c\n";
67                                         $out .= $c;
68                                 }
69                         } else {
70                                 warn "ABORT: offset $p data [$c]";
71                                 $line = $c . substr($data,$p);
72                                 slurp_line;
73                                 last;
74                         }
75
76                         warn "## $repeat [$c] out = ",length($out),$/;
77                 }
78
79                 my $bitmap = pack('H*', $out);
80                 warn "# graphics of ",length($data)," bytes ZPL decompressed to ",length($out)," hex and ", length($bitmap), " bytes bitmap\n";
81                 my $pw = $w * 8;
82                 my $ph = int(length($bitmap) / $w);
83                 print "P4\n$pw $ph\n", substr($bitmap,0,$ph*$w);
84
85         } elsif ( $line =~ s/^([~\^][^~\^\r\n]*)// ) {
86                 my $cmd = substr($1,0,3);
87                 if ( my $desc = $command->{$cmd} ) {
88                         warn "ZPL: $1\t$desc\n";
89                 } else {
90                         warn "UNKNOWN: ",dump($1),$/;
91                 }
92                 $line =~ s/^[\r\n]+// && warn "## removed CR/LF\n";
93         } else {
94                 my $unknown = $1 if $line =~ s/^(.)//; # printer seems to ignore invalid chars
95                 warn "IGNORE: ",dump($unknown);
96         }
97
98         slurp_line;
99 }
100
101 __DATA__
102 ^A Scalable/Bitmapped Font
103 ^A@ Use Font Name to Call Font
104 ^B1 Code 11 Bar Code
105 ^B2 Interleaved 2 of 5 Bar Code
106 ^B3 Code 39 Bar Code
107 ^B4 Code 49 Bar Code
108 ^B5 Planet Code bar code
109 ^B7 PDF417 Bar Code
110 ^B8 EAN-8 Bar Code
111 ^B9 UPC-E Bar Code
112 ^BA Code 93 Bar Code
113 ^BB CODABLOCK Bar Code
114 ^BC Code 128 Bar Code (Subsets A, B, and C)
115 ^BD UPS MaxiCode Bar Code
116 ^BE EAN-13 Bar Code
117 ^BF Micro-PDF417 Bar Code
118 ^BI Industrial 2 of 5 Bar Codes
119 ^BJ Standard 2 of 5 Bar Code
120 ^BK ANSI Codabar Bar Code
121 ^BL LOGMARS Bar Code
122 ^BM MSI Bar Code
123 ^BO Aztec Bar Code Parameters
124 ^BP Plessey Bar Code
125 ^BQ QR Code Bar Code
126 ^BR RSS (Reduced Space Symbology) Bar Code
127 ^BS UPC/EAN Extensions
128 ^BT TLC39 bar code
129 ^BU UPC-A Bar Code
130 ^BX Data Matrix Bar Code
131 ^BY Bar Code Field Default
132 ^BZ POSTNET Bar Code
133 ^CC Change Carets
134 ~CC Change Carets
135 ^CD Change Delimiter
136 ~CD Change Delimiter
137 ^CF Change Alphanumeric Default Font
138 ^CI Change International Font
139 ^CM Change Memory Letter Designation
140 ^CO Cache On
141 ^CT Change Tilde
142 ~CT Change Tilde
143 ^CV Code Validation
144 ^CW Font Identifier
145 ~DB Download Bitmap Font
146 ~DE Download Encoding
147 ^DF Download Format
148 ~DG Download Graphics
149 ~DN Abort Download Graphic
150 ~DS Download Scalable Font
151 ~DT Download TrueType Font
152 ~DU Download Unbounded TrueType Font
153 ~DY Download Graphics
154 ~EG Erase Download Graphics
155 ^FB Field Block
156 ^FC Field Clock (for Real-Time Clock)
157 ^FD Field Data
158 ^FH Field Hexadecimal Indicator
159 ^FM Multiple Field Origin Locations
160 ^FN Field Number
161 ^FO Field Origin
162 ^FP Field Parameter
163 ^FR Field Reverse Print
164 ^FS Field Separator
165 ^FT Field Typeset
166 ^FV Field Variable
167 ^FW Field Orientation
168 ^FX Comment
169 ^GB Graphic Box
170 ^GC Graphic Circle
171 ^GD Graphic Diagonal Line
172 ^GE Graphic Ellipse
173 ^GF Graphic Field
174 ^GS Graphic Symbol
175 ~HB Battery Status
176 ~HD Head Temperature Information
177 ^HF Graphic Symbol
178 ^HG Host Graphic
179 ^HH Configuration Label Return
180 ~HI Host Identification
181 ~HM Host RAM Status
182 ~HS Host Status Return
183 ~HU Return ZebraNet Alert Configuration
184 ^HV Host Verification
185 ^HW Host Directory List
186 ^HY Upload Graphics
187 ^HZ Display Description Information
188 ^ID Object Delete
189 ^IL Image Load
190 ^IM Image Move
191 ^IS Image Save
192 ~JA Cancel All
193 ^JB Initialize Flash Memory
194 ~JB Reset Optional Memory
195 ~JC Set Media Sensor Calibration
196 ~JD Enable Communications Diagnostics
197 ~JE Disable Diagnostics
198 ~JF Set Battery Condition
199 ~JG Graphing Sensor Calibration
200 ^JJ Set Auxiliary Port
201 ~JL Set Label Length
202 ^JM Set Dots per Millimeter
203 ~JN Head Test Fatal
204 ~JO Head Test Non fatal
205 ~JP Pause and Cancel Format
206 ~JR Power On Reset
207 ^JS Sensor Select
208 ~JS Change Backfeed Sequence
209 ^JT Head Test Interval
210 ^JU Configuration Update
211 ^JW Set Ribbon Tension
212 ~JX Cancel Current Partially Input Format
213 ^JZ Reprint After Error
214 ~KB Kill Battery (Battery Discharge Mode)
215 ^KD Select Date and Time Format (for Real Time Clock)
216 ^KL Define Language
217 ^KN Define Printer Name
218 ^KP Define Password
219 ^LH Label Home
220 ^LL Label Length
221 ^LR Label Reverse Print
222 ^LS Label Shift
223 ^LT Label Top
224 ^MC Map Clear
225 ^MD Media Darkness
226 ^MF Media Feed
227 ^ML Maximum Label Length
228 ^MM Print Mode
229 ^MN Media Tracking
230 ^MP Mode Protection
231 ^MT Media Type
232 ^MU Set Units of Measurement
233 ^MW Modify Head Cold Warning
234 ~NC Network Connect
235 ^NI Network ID Number
236 ~NR Set All Network Printers Transparent
237 ^NS Change Networking Settings
238 ~NT Set Currently Connected Printer Transparent
239 ^PF Slew Given Number of Dot Rows
240 ^PH Slew to Home Position
241 ~PH Slew to Home Position
242 ^PM Printing Mirror Image of Label
243 ^PO Print Orientation
244 ^PP Programmable Pause
245 ~PP Programmable Pause
246 ^PQ Print Quantity
247 ^PR Print Rate
248 ~PR Applicator Reprint
249 ~PS Print Start
250 ^PW Print Width
251 ~RO Reset Advanced Counter
252 ^SC Set Serial Communications
253 ~SD Set Darkness
254 ^SE Select Encoding
255 ^SF Serialization Field (with a Standard ^FD String)
256 ^SL Set Mode and Language (for Real-Time Clock)
257 ^SN Serialization Data
258 ^SO Set Offset (for Real-Time Clock)
259 ^SP Start Print
260 ^SQ Halt ZebraNet Alert
261 ^SR Set Printhead Resistance
262 ^SS Set Media Sensors
263 ^ST Set Date and Time (for Real-Time Clock)
264 ^SX Set ZebraNet Alert
265 ^SZ Set ZPL
266 ~TA Tear-off Adjust Position
267 ^TO Transfer Object
268 ~WC Print Configuration Label
269 ^WD Print Directory Label
270 ^XA Start Format
271 ^XB Suppress Backfeed
272 ^XF Recall Format
273 ^XG Recall Graphic
274 ^XZ End Format
275 ^ZZ Printer Sleep