Skip to content

Commit

Permalink
datamatrix: GS1 DataMatrix support added
Browse files Browse the repository at this point in the history
This supports generating a compliant GS1 DataMatrix when the FNC1
character is used as a start character in the barcode.

The FNC1 character may also be used as a separator between GS1 element
strings that do not have a pre-defined length.

From the GS1 DataMatrix guidelines:

	2.2.1 Function 1 Symbol Character (FNC1)

	By definition in ISO/IEC 16022 GS1 DataMatrix uses a special
	start sequence to differentiate GS1 DataMatrix from other
	ISO/IEC Data Matrix symbols. This is achieved by using the
	Function 1 Symbol Character (FNC1) in the first position of
	the data encoded. It enables scanners to process the
	information according to the GS1 System Rules.

	The FNC1 (codeword 232) has two separate uses in GS1 DataMatrix:

	■ Start character.

	■ Separator character to separate element strings that are not
	  in the predefined list

See: https://www.gs1.org/standards/gs1-datamatrix-guideline/25
  • Loading branch information
danielwhite committed Aug 30, 2024
1 parent ca3e24f commit 649f269
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
30 changes: 30 additions & 0 deletions datamatrix/datamatrix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,33 @@ func Test_Issue12(t *testing.T) {
}
}
}

func Test_GS1DataMatrix(t *testing.T) {
// Example 2 from the GS1 DataMatrix Guideline.
//
// (01)09501101020917(17)190508(10)ABCD1234(21)10
//
// See: https://www.gs1.org/standards/gs1-datamatrix-guideline/25#2-Encoding-data+2-3-Human-readable-interpretation-(HRI)
data := new(bytes.Buffer)
data.WriteByte(FNC1) // Start Character
data.WriteString("0109501101020917") // AI (01)
data.WriteString("17190508") // AI (17)
data.WriteString("10ABCD1234") // AI (10) does not have pre-defined length
data.WriteByte(FNC1) // Separator Character
data.WriteString("2110") // AI (20)

// Codewords from decoding example 2 with "dmtxread -c".
wantedData := []byte{
FNC1, // FNC1
131, 139, 180, 141, 131, 132, 139, 147,
147, 149, 135, 138,
140, 66, 67, 68, 69, 142, 164,
232, // FNC1
151, 140,
}

realData := encodeText(data.String())
if bytes.Compare(realData, wantedData) != 0 {
t.Errorf("GS1 DataMatrix encoding failed\nwant: %v\ngot: %v\n", wantedData, realData)
}
}
11 changes: 11 additions & 0 deletions datamatrix/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import (
"github.com/boombuler/barcode"
)

// FNC1 is the codeword for the Function 1 Symbol Character to
// differentiate a GS1 DataMatrix from other Data Matrix symbols.
//
// It is used as both a start character and a separator of GS1 element
// strings.
const FNC1 byte = 232

// Encode returns a Datamatrix barcode for the given content and color scheme
func EncodeWithColor(content string, color barcode.ColorScheme) (barcode.Barcode, error) {
data := encodeText(content)
Expand Down Expand Up @@ -48,6 +55,8 @@ func encodeText(content string) []byte {
var result []byte
input := []byte(content)

isGS1 := len(input) > 0 && input[0] == FNC1

for i := 0; i < len(input); {
c := input[i]
i++
Expand All @@ -58,6 +67,8 @@ func encodeText(content string) []byte {
i++
cw := byte(((c-'0')*10 + (c2 - '0')) + 130)
result = append(result, cw)
} else if isGS1 && c == FNC1 {
result = append(result, c)
} else if c > 127 {
// not correct... needs to be redone later...
result = append(result, 235, c-127)
Expand Down

0 comments on commit 649f269

Please sign in to comment.