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