Skip to content

Commit

Permalink
GS1 support
Browse files Browse the repository at this point in the history
  • Loading branch information
mtgrosser committed Feb 11, 2024
1 parent ba66b3b commit 9e230e0
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 50 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [0.2.0] - 2024-02-11

- Support GS1 DataMatrix

## [0.1.1] - 2021-09-02

- Fix PNG bgcolor
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ gemspec

gem 'rake', '~> 13.0'
gem 'minitest', '~> 5.0'
gem 'debug'
40 changes: 40 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
PATH
remote: .
specs:
dmtx (0.2.0)
builder
chunky_png

GEM
remote: https://rubygems.org/
specs:
builder (3.2.4)
chunky_png (1.4.0)
debug (1.9.1)
irb (~> 1.10)
reline (>= 0.3.8)
io-console (0.7.2)
irb (1.11.2)
rdoc
reline (>= 0.4.2)
minitest (5.22.2)
psych (5.1.2)
stringio
rake (13.1.0)
rdoc (6.6.2)
psych (>= 4.0.0)
reline (0.4.2)
io-console (~> 0.5)
stringio (3.1.0)

PLATFORMS
ruby

DEPENDENCIES
debug
dmtx!
minitest (~> 5.0)
rake (~> 13.0)

BUNDLED WITH
2.1.4
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ dmtx.width
dmtx.height
=> 16

dmtx.encoding
=> :ascii

dmtx.encoded_message
=> [68, 105, 118, 111, 108, 122, 33, 67, 98, 100, 112, 111,
62, 103, 49, 93, 99, 53, 117, 202, 250, 186, 232, 14]

# Generate SVG
dmtx.to_svg
=> "<svg xmlns= ..."
Expand All @@ -67,3 +74,9 @@ dmtx.to_i
# Binary representation
dmtx.to_i.to_s(2)
=> "1010101010101010101110101000001111010111111101101001101011101001100110010100111010111011111100111001011001001000100010000111010110110001101111001011001001101011110000011111110010101101101010111001101001000000111100101000110110101110011100101111111111111111"

# Choose encoding
Dmtx::DataMatrix.new('Chunky Bacon', encoding: :txt)

# GS1 DataMatrix
Dmtx::DataMatrix.new("\x1d01095011010209171719050810ABCD1234\x1d2110", encoding: :gs1)
2 changes: 1 addition & 1 deletion lib/dmtx.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require_relative 'dmtx/version'
require_relative 'dmtx/data_matrix'
require_relative 'dmtx/gs1_data_matrix'

module Dmtx
class Error < StandardError; end
class EncodingError < Error; end
end
67 changes: 51 additions & 16 deletions lib/dmtx/data_matrix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

module Dmtx
class DataMatrix
attr_reader :width, :height
attr_reader :width, :height, :encoded_message, :encoding

C40 = [230,
31, 0, 0,
Expand Down Expand Up @@ -43,16 +43,26 @@ class DataMatrix
64, 8, 0,
90, 9, 51,
255, 8, 0]

def initialize(msg, rect: false)

# See https://www.gs1.org/standards/gs1-datamatrix-guideline/25
FNC1 = 29
FNC1_CODEWORD = 232

DEFAULT_ENCODINGS = %i[ascii c40 txt x12 edifact base gs1].freeze
ENCODINGS = (%i[gs1] + DEFAULT_ENCODINGS).freeze

def initialize(msg, rect: false, encoding: nil)
@m = []
@width = 0
@height = 0
encode(msg, rect)
raise ArgumentError, "illegal encoding #{encoding.inspect}" if encoding && !ENCODINGS.include?(encoding)
@encoding, @encoded_message = encode_message(msg, encoding)
raise EncodingError, "illegal payload" unless @encoded_message
encode(@encoded_message, rect)
end

def inspect
"#<#{self.class.name}:0x#{object_id.to_s(16)} #{width}x#{height}>"
"#<#{self.class.name}:0x#{object_id.to_s(16)} #{width}x#{height}@#{encoding}>"
end

def to_i
Expand All @@ -76,7 +86,6 @@ def to_svg(dim: 256, pad: 2, bgcolor: nil, color: '#000')
y = height
while y > 0
y -= 1
d = 0
x = width
while x > 0
x -= 1
Expand Down Expand Up @@ -139,6 +148,23 @@ def ascii_encode(t)
end
result
end

def gs1_encode(t)
bytes, result = t.bytes, []
while c = bytes.shift
if !bytes.empty? && c > 47 && c < 58 && bytes.first > 47 && bytes.first < 58
result << (c - 48) * 10 + bytes.shift + 82
elsif c > 127
result << 235
result << ((c - 127) & 255)
elsif c == FNC1
result << FNC1_CODEWORD
else
result << c + 1
end
end
result
end

def base_encode(t)
bytes, result = t.bytes, [231]
Expand Down Expand Up @@ -204,18 +230,27 @@ def text_encode(t, s)
result.concat ascii_encode(bytes[(i - cc)..-1].to_a.pack('C*')) if cc > 0 || i < l
result
end

def encodings(msg)
{ ascii: ascii_encode(msg),
c40: text_encode(msg, C40),
txt: text_encode(msg, TEXT),
x12: text_encode(msg, X12),
edifact: edifact_encode(msg),
base: base_encode(msg) }

def c40_encode(t)
text_encode(t, C40)
end

def txt_encode(t)
text_encode(t, TEXT)
end

def x12_encode(t)
text_encode(t, X12)
end

def encode_message(msg, encoding)
(encoding ? [encoding] : DEFAULT_ENCODINGS)
.map { |name| [name, send("#{name}_encode", msg)] }
.reject { |_, encoded| encoded.empty? }
.min_by { |_, encoded| encoded.size }
end

def encode(text, rct)
enc = encodings(text).values.reject(&:empty?).min_by(&:size)
def encode(enc, rct)
el = enc.size
nc = nr = 1
j = -1
Expand Down
28 changes: 0 additions & 28 deletions lib/dmtx/gs1_data_matrix.rb

This file was deleted.

2 changes: 1 addition & 1 deletion lib/dmtx/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Dmtx
VERSION = '0.1.1'
VERSION = '0.2.0'
end
8 changes: 4 additions & 4 deletions test/dmtx_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ def test_generate_data_matrix_svg

def test_gs1_data_matrix_encodings
# See example 2 at https://www.gs1.org/standards/gs1-datamatrix-guideline/25#2-Encoding-data+2-3-Human-readable-interpretation-(HRI)
data = "#{Dmtx::GS1DataMatrix::FNC1}01095011010209171719050810ABCD1234#{Dmtx::GS1DataMatrix::FNC1}2110"
encodings = Dmtx::GS1DataMatrix.new(data).encodings(data)
assert_equal %i[asci], encodings.keys
assert_equal 232, encodings[:asci].first
data = "#{Dmtx::DataMatrix::FNC1.chr}01095011010209171719050810ABCD1234#{Dmtx::DataMatrix::FNC1.chr}2110"
dmtx = Dmtx::DataMatrix.new(data, encoding: :gs1)
assert_equal :gs1, dmtx.encoding
assert_equal 232, dmtx.encoded_message.first
end
end

0 comments on commit 9e230e0

Please sign in to comment.