Module: ZplRender::GraphicField
- Defined in:
- lib/zpl_render/graphic_field.rb
Overview
Decodes ZPL graphic data (^GF and ~DG) into a Canvas.
Supports:
- ASCII hex data, including Zebra's run-length compression scheme (G-Y repeat counts, g-z counts in multiples of 20, ',' zero-fill to end of row, '!' one-fill to end of row, ':' repeat previous row)
- :B64: (base64) and :Z64: (base64 + zlib deflate) wrapped data
- raw binary data (^GFB)
Class Method Summary collapse
-
.decode(data, bytes_per_row, total_bytes) ⇒ Object
bytes_per_row determines the pixel width (8 px per byte).
-
.decode_ascii_hex(data, bytes_per_row) ⇒ Object
Expand Zebra RLE ASCII hex into raw bytes.
- .decode_b64_z64(data) ⇒ Object
- .to_canvas(raw, bytes_per_row, rows) ⇒ Object
Class Method Details
.decode(data, bytes_per_row, total_bytes) ⇒ Object
bytes_per_row determines the pixel width (8 px per byte).
18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/zpl_render/graphic_field.rb', line 18 def decode(data, bytes_per_row, total_bytes) return Canvas.new(1, 1) if bytes_per_row.to_i < 1 || total_bytes.to_i < 1 rows = (total_bytes.to_f / bytes_per_row).ceil raw = if data =~ /\A:?([BZ])64:/ decode_b64_z64(data) elsif data.encoding == Encoding::BINARY && data =~ /[^0-9A-Fa-f,:!\sG-Yg-z]/n data # raw binary (^GFB) else decode_ascii_hex(data, bytes_per_row) end to_canvas(raw, bytes_per_row, rows) end |
.decode_ascii_hex(data, bytes_per_row) ⇒ Object
Expand Zebra RLE ASCII hex into raw bytes.
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 |
# File 'lib/zpl_render/graphic_field.rb', line 43 def decode_ascii_hex(data, bytes_per_row) nibbles_per_row = bytes_per_row * 2 out = [] row = [] prev_row = nil count = 0 i = 0 flush = lambda do row << 0 while row.length < nibbles_per_row out.concat(row[0, nibbles_per_row]) prev_row = row[0, nibbles_per_row] row = [] end while i < data.length ch = data[i] i += 1 case ch when /[0-9A-Fa-f]/ nib = ch.to_i(16) (count.zero? ? 1 : count).times { row << nib } count = 0 flush.call if row.length >= nibbles_per_row when "G".."Y" count += ch.ord - "G".ord + 1 when "g".."z" count += (ch.ord - "g".ord + 1) * 20 when "," row << 0 while row.length < nibbles_per_row flush.call count = 0 when "!" row << 0xF while row.length < nibbles_per_row flush.call count = 0 when ":" flush.call unless row.empty? if prev_row out.concat(prev_row) else out.concat(Array.new(nibbles_per_row, 0)) end count = 0 end # whitespace and anything else is ignored end flush.call unless row.empty? bytes = +"" out.each_slice(2) { |hi, lo| bytes << ((hi << 4) | (lo || 0)).chr } bytes.b end |
.decode_b64_z64(data) ⇒ Object
32 33 34 35 36 37 38 39 40 |
# File 'lib/zpl_render/graphic_field.rb', line 32 def decode_b64_z64(data) m = data.match(/\A:?([BZ])64:([A-Za-z0-9+\/=\s]*):?[0-9A-Fa-f]{0,4}\z/m) return "" unless m decoded = m[2].unpack1("m") # lenient base64, same as Base64.decode64 m[1] == "Z" ? Zlib::Inflate.inflate(decoded) : decoded rescue Zlib::Error "" end |
.to_canvas(raw, bytes_per_row, rows) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/zpl_render/graphic_field.rb', line 96 def to_canvas(raw, bytes_per_row, rows) width = bytes_per_row * 8 canvas = Canvas.new(width, [rows, 1].max) rows.times do |y| bytes_per_row.times do |bx| byte = raw.getbyte(y * bytes_per_row + bx) next if byte.nil? || byte.zero? 8.times do |bit| canvas.set(bx * 8 + bit, y) if (byte >> (7 - bit)) & 1 == 1 end end end canvas end |