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