ccitt: new package for CCITT images
This initial commit only provides a decoder that generates modes and run
lengths from a bit stream. Future commits will add more features.
Updates golang/go#19443
Change-Id: I7bba1226a69a83e636e407e4d72ffd5630562e6b
Reviewed-on: https://go-review.googlesource.com/c/image/+/174979
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
Run-TryBot: Benny Siegert <bsiegert@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/ccitt/gen.go b/ccitt/gen.go
new file mode 100644
index 0000000..2972acd
--- /dev/null
+++ b/ccitt/gen.go
@@ -0,0 +1,511 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "log"
+ "os"
+)
+
+var debug = flag.Bool("debug", false, "")
+
+func main() {
+ flag.Parse()
+
+ // Generate table.go.
+ {
+ w := &bytes.Buffer{}
+ w.WriteString(header)
+ w.WriteString(headerComment)
+ write(w, build(modeCodes[:], 0), "modeTable",
+ "// modeTable represents Table 1 and the End-of-Line code.\n")
+ write(w, build(whiteCodes[:], 0), "whiteTable",
+ "// whiteTable represents Tables 2 and 3 for a white run.\n")
+ write(w, build(blackCodes[:], 0), "blackTable",
+ "// blackTable represents Tables 2 and 3 for a black run.\n")
+ finish(w, "table.go")
+ }
+
+ // Generate table_test.go.
+ {
+ w := &bytes.Buffer{}
+ w.WriteString(header)
+ finish(w, "table_test.go")
+ }
+}
+
+const header = `// generated by "go run gen.go". DO NOT EDIT.
+
+package ccitt
+
+`
+
+const headerComment = `
+// Each table is represented by an array of [2]int16's: a binary tree. Each
+// array element (other than element 0, which means invalid) is a branch node
+// in that tree. The root node is always element 1 (the second element).
+//
+// To walk the tree, look at the next bit in the bit stream, using it to select
+// the first or second element of the [2]int16. If that int16 is 0, we have an
+// invalid code. If it is positive, go to that branch node. If it is negative,
+// then we have a leaf node, whose value is the bitwise complement (the ^
+// operator) of that int16.
+//
+// Comments above each table also show the same structure visually. The "b123"
+// lines show the 123'rd branch node. The "=XXXXX" lines show an invalid code.
+// The "=v1234" lines show a leaf node with value 1234. When reading the bit
+// stream, a 0 or 1 bit means to go up or down, as you move left to right.
+//
+// For example, in modeTable, branch node b005 is three steps up from the root
+// node, meaning that we have already seen "000". If the next bit is "0" then
+// we move to branch node b006. Otherwise, the next bit is "1", and we move to
+// the leaf node v0000 (also known as the modePass constant). Indeed, the bits
+// that encode modePass are "0001".
+//
+// Tables 1, 2 and 3 come from the "ITU-T Recommendation T.6: FACSIMILE CODING
+// SCHEMES AND CODING CONTROL FUNCTIONS FOR GROUP 4 FACSIMILE APPARATUS"
+// specification:
+//
+// https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.6-198811-I!!PDF-E&type=items
+
+
+`
+
+type node struct {
+ children [2]*node
+ val uint32
+ branchIndex int32
+}
+
+func (n *node) isBranch() bool {
+ return (n != nil) && ((n.children[0] != nil) || (n.children[1] != nil))
+}
+
+func (n *node) String() string {
+ if n == nil {
+ return "0"
+ }
+ if n.branchIndex > 0 {
+ return fmt.Sprintf("%d", n.branchIndex)
+ }
+ return fmt.Sprintf("^%d", n.val)
+}
+
+func build(codes []code, prefixLen int) *node {
+ if len(codes) == 0 {
+ return nil
+ }
+
+ if prefixLen == len(codes[0].str) {
+ if len(codes) != 1 {
+ panic("ambiguous codes")
+ }
+ return &node{
+ val: codes[0].val,
+ }
+ }
+
+ childrenCodes := [2][]code{}
+ for _, code := range codes {
+ bit := code.str[prefixLen] & 1
+ childrenCodes[bit] = append(childrenCodes[bit], code)
+ }
+ return &node{
+ children: [2]*node{
+ build(childrenCodes[0], prefixLen+1),
+ build(childrenCodes[1], prefixLen+1),
+ },
+ }
+}
+
+func write(w *bytes.Buffer, root *node, varName string, comment string) {
+ assignBranchIndexes(root)
+
+ w.WriteString(comment)
+ w.WriteString("//\n")
+ writeComment(w, root, " ", false)
+ fmt.Fprintf(w, "var %s = [...][2]int16{\n", varName)
+ fmt.Fprintf(w, "0: {0, 0},\n")
+
+ // Walk the tree in breadth-first order.
+ for queue := []*node{root}; len(queue) > 0; {
+ n := queue[0]
+ queue = queue[1:]
+
+ if n.isBranch() {
+ fmt.Fprintf(w, "%d: {%v, %v},\n", n.branchIndex, n.children[0], n.children[1])
+ queue = append(queue, n.children[0], n.children[1])
+ }
+ }
+
+ fmt.Fprintf(w, "}\n\n")
+}
+
+func assignBranchIndexes(root *node) {
+ // 0 is reserved for an invalid value.
+ branchIndex := int32(1)
+
+ // Walk the tree in breadth-first order.
+ for queue := []*node{root}; len(queue) > 0; {
+ n := queue[0]
+ queue = queue[1:]
+
+ if n.isBranch() {
+ n.branchIndex = branchIndex
+ branchIndex++
+ queue = append(queue, n.children[0], n.children[1])
+ }
+ }
+}
+
+func writeComment(w *bytes.Buffer, n *node, prefix string, down bool) {
+ if n.isBranch() {
+ prefixUp := prefix[:len(prefix)-2] + " | "
+ prefixDown := prefix + "| "
+ if down {
+ prefixUp, prefixDown = prefixDown, prefixUp
+ }
+
+ writeComment(w, n.children[0], prefixUp, false)
+ defer writeComment(w, n.children[1], prefixDown, true)
+
+ fmt.Fprintf(w, "// b%03d ", n.branchIndex)
+ } else {
+ fmt.Fprintf(w, "// ")
+ }
+
+ w.WriteString(prefix[:len(prefix)-2])
+
+ if n == nil {
+ fmt.Fprintf(w, "+=XXXXX\n")
+ return
+ }
+ if !n.isBranch() {
+ fmt.Fprintf(w, "+=v%04d\n", n.val)
+ return
+ }
+ w.WriteString("+-+\n")
+}
+
+func finish(w *bytes.Buffer, filename string) {
+ copyPaste(w, filename)
+ if *debug {
+ os.Stdout.Write(w.Bytes())
+ return
+ }
+ out, err := format.Source(w.Bytes())
+ if err != nil {
+ log.Fatalf("format.Source: %v", err)
+ }
+ if err := ioutil.WriteFile(filename, out, 0660); err != nil {
+ log.Fatalf("ioutil.WriteFile: %v", err)
+ }
+}
+
+func copyPaste(w *bytes.Buffer, filename string) {
+ b, err := ioutil.ReadFile("gen.go")
+ if err != nil {
+ log.Fatalf("ioutil.ReadFile: %v", err)
+ }
+ begin := []byte("\n// COPY PASTE " + filename + " BEGIN\n\n")
+ end := []byte("\n// COPY PASTE " + filename + " END\n\n")
+
+ for len(b) > 0 {
+ i := bytes.Index(b, begin)
+ if i < 0 {
+ break
+ }
+ b = b[i:]
+
+ j := bytes.Index(b, end)
+ if j < 0 {
+ break
+ }
+ j += len(end)
+
+ w.Write(b[:j])
+ b = b[j:]
+ }
+}
+
+// COPY PASTE table.go BEGIN
+
+const (
+ modePass = iota // Pass
+ modeH // Horizontal
+ modeV0 // Vertical-0
+ modeVR1 // Vertical-Right-1
+ modeVR2 // Vertical-Right-2
+ modeVR3 // Vertical-Right-3
+ modeVL1 // Vertical-Left-1
+ modeVL2 // Vertical-Left-2
+ modeVL3 // Vertical-Left-3
+ modeExt // Extension
+ modeEOL // End-of-Line
+)
+
+// COPY PASTE table.go END
+
+// The data that is the rest of this file is taken from Tables 1, 2 and 3 from
+// the "ITU-T Recommendation T.6" spec.
+
+// COPY PASTE table_test.go BEGIN
+
+type code struct {
+ val uint32
+ str string
+}
+
+var modeCodes = []code{
+ {modePass, "0001"},
+ {modeH, "001"},
+ {modeV0, "1"},
+ {modeVR1, "011"},
+ {modeVR2, "000011"},
+ {modeVR3, "0000011"},
+ {modeVL1, "010"},
+ {modeVL2, "000010"},
+ {modeVL3, "0000010"},
+ {modeExt, "0000001"},
+
+ // End-of-Line is not in Table 1, but we look for it at the same time that
+ // we look for other mode codes.
+ {modeEOL, "000000000001"},
+}
+
+var whiteCodes = []code{
+ // Terminating codes (0-63).
+ {0x0000, "00110101"},
+ {0x0001, "000111"},
+ {0x0002, "0111"},
+ {0x0003, "1000"},
+ {0x0004, "1011"},
+ {0x0005, "1100"},
+ {0x0006, "1110"},
+ {0x0007, "1111"},
+ {0x0008, "10011"},
+ {0x0009, "10100"},
+ {0x000A, "00111"},
+ {0x000B, "01000"},
+ {0x000C, "001000"},
+ {0x000D, "000011"},
+ {0x000E, "110100"},
+ {0x000F, "110101"},
+ {0x0010, "101010"},
+ {0x0011, "101011"},
+ {0x0012, "0100111"},
+ {0x0013, "0001100"},
+ {0x0014, "0001000"},
+ {0x0015, "0010111"},
+ {0x0016, "0000011"},
+ {0x0017, "0000100"},
+ {0x0018, "0101000"},
+ {0x0019, "0101011"},
+ {0x001A, "0010011"},
+ {0x001B, "0100100"},
+ {0x001C, "0011000"},
+ {0x001D, "00000010"},
+ {0x001E, "00000011"},
+ {0x001F, "00011010"},
+ {0x0020, "00011011"},
+ {0x0021, "00010010"},
+ {0x0022, "00010011"},
+ {0x0023, "00010100"},
+ {0x0024, "00010101"},
+ {0x0025, "00010110"},
+ {0x0026, "00010111"},
+ {0x0027, "00101000"},
+ {0x0028, "00101001"},
+ {0x0029, "00101010"},
+ {0x002A, "00101011"},
+ {0x002B, "00101100"},
+ {0x002C, "00101101"},
+ {0x002D, "00000100"},
+ {0x002E, "00000101"},
+ {0x002F, "00001010"},
+ {0x0030, "00001011"},
+ {0x0031, "01010010"},
+ {0x0032, "01010011"},
+ {0x0033, "01010100"},
+ {0x0034, "01010101"},
+ {0x0035, "00100100"},
+ {0x0036, "00100101"},
+ {0x0037, "01011000"},
+ {0x0038, "01011001"},
+ {0x0039, "01011010"},
+ {0x003A, "01011011"},
+ {0x003B, "01001010"},
+ {0x003C, "01001011"},
+ {0x003D, "00110010"},
+ {0x003E, "00110011"},
+ {0x003F, "00110100"},
+
+ // Make-up codes between 64 and 1728.
+ {0x0040, "11011"},
+ {0x0080, "10010"},
+ {0x00C0, "010111"},
+ {0x0100, "0110111"},
+ {0x0140, "00110110"},
+ {0x0180, "00110111"},
+ {0x01C0, "01100100"},
+ {0x0200, "01100101"},
+ {0x0240, "01101000"},
+ {0x0280, "01100111"},
+ {0x02C0, "011001100"},
+ {0x0300, "011001101"},
+ {0x0340, "011010010"},
+ {0x0380, "011010011"},
+ {0x03C0, "011010100"},
+ {0x0400, "011010101"},
+ {0x0440, "011010110"},
+ {0x0480, "011010111"},
+ {0x04C0, "011011000"},
+ {0x0500, "011011001"},
+ {0x0540, "011011010"},
+ {0x0580, "011011011"},
+ {0x05C0, "010011000"},
+ {0x0600, "010011001"},
+ {0x0640, "010011010"},
+ {0x0680, "011000"},
+ {0x06C0, "010011011"},
+
+ // Make-up codes between 1792 and 2560.
+ {0x0700, "00000001000"},
+ {0x0740, "00000001100"},
+ {0x0780, "00000001101"},
+ {0x07C0, "000000010010"},
+ {0x0800, "000000010011"},
+ {0x0840, "000000010100"},
+ {0x0880, "000000010101"},
+ {0x08C0, "000000010110"},
+ {0x0900, "000000010111"},
+ {0x0940, "000000011100"},
+ {0x0980, "000000011101"},
+ {0x09C0, "000000011110"},
+ {0x0A00, "000000011111"},
+}
+
+var blackCodes = []code{
+ // Terminating codes (0-63).
+ {0x0000, "0000110111"},
+ {0x0001, "010"},
+ {0x0002, "11"},
+ {0x0003, "10"},
+ {0x0004, "011"},
+ {0x0005, "0011"},
+ {0x0006, "0010"},
+ {0x0007, "00011"},
+ {0x0008, "000101"},
+ {0x0009, "000100"},
+ {0x000A, "0000100"},
+ {0x000B, "0000101"},
+ {0x000C, "0000111"},
+ {0x000D, "00000100"},
+ {0x000E, "00000111"},
+ {0x000F, "000011000"},
+ {0x0010, "0000010111"},
+ {0x0011, "0000011000"},
+ {0x0012, "0000001000"},
+ {0x0013, "00001100111"},
+ {0x0014, "00001101000"},
+ {0x0015, "00001101100"},
+ {0x0016, "00000110111"},
+ {0x0017, "00000101000"},
+ {0x0018, "00000010111"},
+ {0x0019, "00000011000"},
+ {0x001A, "000011001010"},
+ {0x001B, "000011001011"},
+ {0x001C, "000011001100"},
+ {0x001D, "000011001101"},
+ {0x001E, "000001101000"},
+ {0x001F, "000001101001"},
+ {0x0020, "000001101010"},
+ {0x0021, "000001101011"},
+ {0x0022, "000011010010"},
+ {0x0023, "000011010011"},
+ {0x0024, "000011010100"},
+ {0x0025, "000011010101"},
+ {0x0026, "000011010110"},
+ {0x0027, "000011010111"},
+ {0x0028, "000001101100"},
+ {0x0029, "000001101101"},
+ {0x002A, "000011011010"},
+ {0x002B, "000011011011"},
+ {0x002C, "000001010100"},
+ {0x002D, "000001010101"},
+ {0x002E, "000001010110"},
+ {0x002F, "000001010111"},
+ {0x0030, "000001100100"},
+ {0x0031, "000001100101"},
+ {0x0032, "000001010010"},
+ {0x0033, "000001010011"},
+ {0x0034, "000000100100"},
+ {0x0035, "000000110111"},
+ {0x0036, "000000111000"},
+ {0x0037, "000000100111"},
+ {0x0038, "000000101000"},
+ {0x0039, "000001011000"},
+ {0x003A, "000001011001"},
+ {0x003B, "000000101011"},
+ {0x003C, "000000101100"},
+ {0x003D, "000001011010"},
+ {0x003E, "000001100110"},
+ {0x003F, "000001100111"},
+
+ // Make-up codes between 64 and 1728.
+ {0x0040, "0000001111"},
+ {0x0080, "000011001000"},
+ {0x00C0, "000011001001"},
+ {0x0100, "000001011011"},
+ {0x0140, "000000110011"},
+ {0x0180, "000000110100"},
+ {0x01C0, "000000110101"},
+ {0x0200, "0000001101100"},
+ {0x0240, "0000001101101"},
+ {0x0280, "0000001001010"},
+ {0x02C0, "0000001001011"},
+ {0x0300, "0000001001100"},
+ {0x0340, "0000001001101"},
+ {0x0380, "0000001110010"},
+ {0x03C0, "0000001110011"},
+ {0x0400, "0000001110100"},
+ {0x0440, "0000001110101"},
+ {0x0480, "0000001110110"},
+ {0x04C0, "0000001110111"},
+ {0x0500, "0000001010010"},
+ {0x0540, "0000001010011"},
+ {0x0580, "0000001010100"},
+ {0x05C0, "0000001010101"},
+ {0x0600, "0000001011010"},
+ {0x0640, "0000001011011"},
+ {0x0680, "0000001100100"},
+ {0x06C0, "0000001100101"},
+
+ // Make-up codes between 1792 and 2560.
+ {0x0700, "00000001000"},
+ {0x0740, "00000001100"},
+ {0x0780, "00000001101"},
+ {0x07C0, "000000010010"},
+ {0x0800, "000000010011"},
+ {0x0840, "000000010100"},
+ {0x0880, "000000010101"},
+ {0x08C0, "000000010110"},
+ {0x0900, "000000010111"},
+ {0x0940, "000000011100"},
+ {0x0980, "000000011101"},
+ {0x09C0, "000000011110"},
+ {0x0A00, "000000011111"},
+}
+
+// COPY PASTE table_test.go END
+
+// This final comment makes the "END" above be followed by "\n\n".
diff --git a/ccitt/reader.go b/ccitt/reader.go
new file mode 100644
index 0000000..ad5f2fa
--- /dev/null
+++ b/ccitt/reader.go
@@ -0,0 +1,110 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:generate go run gen.go
+
+// Package ccitt implements a CCITT (fax) image decoder.
+package ccitt
+
+import (
+ "encoding/binary"
+ "errors"
+ "io"
+ "math/bits"
+)
+
+var (
+ errInvalidCode = errors.New("ccitt: invalid code")
+)
+
+// Order specifies the bit ordering in a CCITT data stream.
+type Order uint32
+
+const (
+ // LSB means Least Significant Bits first.
+ LSB Order = iota
+ // MSB means Most Significant Bits first.
+ MSB
+)
+
+type bitReader struct {
+ r io.Reader
+
+ // readErr is the error returned from the most recent r.Read call. As the
+ // io.Reader documentation says, when r.Read returns (n, err), "always
+ // process the n > 0 bytes returned before considering the error err".
+ readErr error
+
+ order Order
+
+ // The low nBits bits of the bits field hold upcoming bits in LSB order.
+ bits uint64
+ nBits uint32
+
+ // bytes[br:bw] holds bytes read from r but not yet loaded into bits.
+ br uint32
+ bw uint32
+ bytes [1024]uint8
+}
+
+func (b *bitReader) alignToByteBoundary() {
+ n := b.nBits & 7
+ b.bits >>= n
+ b.nBits -= n
+}
+
+func (b *bitReader) nextBit() (uint32, error) {
+ for {
+ if b.nBits > 0 {
+ bit := uint32(b.bits) & 1
+ b.bits >>= 1
+ b.nBits--
+ return bit, nil
+ }
+
+ if available := b.bw - b.br; available >= 8 {
+ b.bits = binary.LittleEndian.Uint64(b.bytes[b.br:])
+ b.br += 8
+ b.nBits = 64
+ continue
+ } else if available > 0 {
+ b.bits = uint64(b.bytes[b.br])
+ b.br++
+ b.nBits = 8
+ continue
+ }
+
+ if b.readErr != nil {
+ return 0, b.readErr
+ }
+
+ n, err := b.r.Read(b.bytes[:])
+ b.br = 0
+ b.bw = uint32(n)
+ b.readErr = err
+
+ if b.order != LSB {
+ written := b.bytes[:b.bw]
+ for i, x := range written {
+ written[i] = bits.Reverse8(x)
+ }
+ }
+ }
+}
+
+func decode(b *bitReader, table [][2]int16) (uint32, error) {
+ for state := int32(1); ; {
+ bit, err := b.nextBit()
+ if err != nil {
+ return 0, err
+ }
+ // The "&1" is redundant, but can eliminate a bounds check.
+ state = int32(table[state][bit&1])
+ if state < 0 {
+ return uint32(^state), nil
+ } else if state == 0 {
+ return 0, errInvalidCode
+ }
+ }
+}
diff --git a/ccitt/reader_test.go b/ccitt/reader_test.go
new file mode 100644
index 0000000..f6b47d8
--- /dev/null
+++ b/ccitt/reader_test.go
@@ -0,0 +1,95 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ccitt
+
+import (
+ "bytes"
+ "reflect"
+ "testing"
+)
+
+func testTable(t *testing.T, table [][2]int16, codes []code, values []uint32) {
+ // Build a map from values to codes.
+ m := map[uint32]string{}
+ for _, code := range codes {
+ m[code.val] = code.str
+ }
+
+ // Build the encoded form of those values.
+ enc := []byte(nil)
+ bits := uint8(0)
+ nBits := uint32(0)
+ for _, v := range values {
+ code := m[v]
+ if code == "" {
+ panic("unmapped code")
+ }
+ for _, c := range code {
+ bits |= uint8(c&1) << nBits
+ nBits++
+ if nBits == 8 {
+ enc = append(enc, bits)
+ bits = 0
+ nBits = 0
+ }
+ }
+ }
+ if nBits > 0 {
+ enc = append(enc, bits)
+ }
+
+ // Decode that encoded form.
+ got := []uint32(nil)
+ r := &bitReader{
+ r: bytes.NewReader(enc),
+ }
+ finalValue := values[len(values)-1]
+ for {
+ v, err := decode(r, table)
+ if err != nil {
+ t.Fatalf("after got=%d: %v", got, err)
+ }
+ got = append(got, v)
+ if v == finalValue {
+ break
+ }
+ }
+
+ // Check that the round-tripped values were unchanged.
+ if !reflect.DeepEqual(got, values) {
+ t.Fatalf("\ngot: %v\nwant: %v", got, values)
+ }
+}
+
+func TestModeTable(t *testing.T) {
+ testTable(t, modeTable[:], modeCodes, []uint32{
+ modePass,
+ modeV0,
+ modeV0,
+ modeVL1,
+ modeVR3,
+ modeVL2,
+ modeExt,
+ modeVL1,
+ modeH,
+ modeVL1,
+ modeVL1,
+ modeEOL,
+ })
+}
+
+func TestWhiteTable(t *testing.T) {
+ testTable(t, whiteTable[:], whiteCodes, []uint32{
+ 0, 1, 256, 7, 128, 3, 2560,
+ })
+}
+
+func TestBlackTable(t *testing.T) {
+ testTable(t, blackTable[:], blackCodes, []uint32{
+ 63, 64, 63, 64, 64, 63, 22, 1088, 2048, 7, 6, 5, 4, 3, 2, 1, 0,
+ })
+}
+
+// TODO: more tests.
diff --git a/ccitt/table.go b/ccitt/table.go
new file mode 100644
index 0000000..266dfcf
--- /dev/null
+++ b/ccitt/table.go
@@ -0,0 +1,738 @@
+// generated by "go run gen.go". DO NOT EDIT.
+
+package ccitt
+
+// Each table is represented by an array of [2]int16's: a binary tree. Each
+// array element (other than element 0, which means invalid) is a branch node
+// in that tree. The root node is always element 1 (the second element).
+//
+// To walk the tree, look at the next bit in the bit stream, using it to select
+// the first or second element of the [2]int16. If that int16 is 0, we have an
+// invalid code. If it is positive, go to that branch node. If it is negative,
+// then we have a leaf node, whose value is the bitwise complement (the ^
+// operator) of that int16.
+//
+// Comments above each table also show the same structure visually. The "b123"
+// lines show the 123'rd branch node. The "=XXXXX" lines show an invalid code.
+// The "=v1234" lines show a leaf node with value 1234. When reading the bit
+// stream, a 0 or 1 bit means to go up or down, as you move left to right.
+//
+// For example, in modeTable, branch node b005 is three steps up from the root
+// node, meaning that we have already seen "000". If the next bit is "0" then
+// we move to branch node b006. Otherwise, the next bit is "1", and we move to
+// the leaf node v0000 (also known as the modePass constant). Indeed, the bits
+// that encode modePass are "0001".
+//
+// Tables 1, 2 and 3 come from the "ITU-T Recommendation T.6: FACSIMILE CODING
+// SCHEMES AND CODING CONTROL FUNCTIONS FOR GROUP 4 FACSIMILE APPARATUS"
+// specification:
+//
+// https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.6-198811-I!!PDF-E&type=items
+
+// modeTable represents Table 1 and the End-of-Line code.
+//
+// +=XXXXX
+// b015 +-+
+// | +=v0010
+// b014 +-+
+// | +=XXXXX
+// b013 +-+
+// | +=XXXXX
+// b012 +-+
+// | +=XXXXX
+// b011 +-+
+// | +=XXXXX
+// b009 +-+
+// | +=v0009
+// b007 +-+
+// | | +=v0008
+// b010 | +-+
+// | +=v0005
+// b006 +-+
+// | | +=v0007
+// b008 | +-+
+// | +=v0004
+// b005 +-+
+// | +=v0000
+// b003 +-+
+// | +=v0001
+// b002 +-+
+// | | +=v0006
+// b004 | +-+
+// | +=v0003
+// b001 +-+
+// +=v0002
+var modeTable = [...][2]int16{
+ 0: {0, 0},
+ 1: {2, ^2},
+ 2: {3, 4},
+ 3: {5, ^1},
+ 4: {^6, ^3},
+ 5: {6, ^0},
+ 6: {7, 8},
+ 7: {9, 10},
+ 8: {^7, ^4},
+ 9: {11, ^9},
+ 10: {^8, ^5},
+ 11: {12, 0},
+ 12: {13, 0},
+ 13: {14, 0},
+ 14: {15, 0},
+ 15: {0, ^10},
+}
+
+// whiteTable represents Tables 2 and 3 for a white run.
+//
+// +=XXXXX
+// b059 +-+
+// | | +=v1792
+// b096 | | +-+
+// | | | | +=v1984
+// b100 | | | +-+
+// | | | +=v2048
+// b094 | | +-+
+// | | | | +=v2112
+// b101 | | | | +-+
+// | | | | | +=v2176
+// b097 | | | +-+
+// | | | | +=v2240
+// b102 | | | +-+
+// | | | +=v2304
+// b085 | +-+
+// | | +=v1856
+// b098 | | +-+
+// | | | +=v1920
+// b095 | +-+
+// | | +=v2368
+// b103 | | +-+
+// | | | +=v2432
+// b099 | +-+
+// | | +=v2496
+// b104 | +-+
+// | +=v2560
+// b040 +-+
+// | | +=v0029
+// b060 | +-+
+// | +=v0030
+// b026 +-+
+// | | +=v0045
+// b061 | | +-+
+// | | | +=v0046
+// b041 | +-+
+// | +=v0022
+// b016 +-+
+// | | +=v0023
+// b042 | | +-+
+// | | | | +=v0047
+// b062 | | | +-+
+// | | | +=v0048
+// b027 | +-+
+// | +=v0013
+// b008 +-+
+// | | +=v0020
+// b043 | | +-+
+// | | | | +=v0033
+// b063 | | | +-+
+// | | | +=v0034
+// b028 | | +-+
+// | | | | +=v0035
+// b064 | | | | +-+
+// | | | | | +=v0036
+// b044 | | | +-+
+// | | | | +=v0037
+// b065 | | | +-+
+// | | | +=v0038
+// b017 | +-+
+// | | +=v0019
+// b045 | | +-+
+// | | | | +=v0031
+// b066 | | | +-+
+// | | | +=v0032
+// b029 | +-+
+// | +=v0001
+// b004 +-+
+// | | +=v0012
+// b030 | | +-+
+// | | | | +=v0053
+// b067 | | | | +-+
+// | | | | | +=v0054
+// b046 | | | +-+
+// | | | +=v0026
+// b018 | | +-+
+// | | | | +=v0039
+// b068 | | | | +-+
+// | | | | | +=v0040
+// b047 | | | | +-+
+// | | | | | | +=v0041
+// b069 | | | | | +-+
+// | | | | | +=v0042
+// b031 | | | +-+
+// | | | | +=v0043
+// b070 | | | | +-+
+// | | | | | +=v0044
+// b048 | | | +-+
+// | | | +=v0021
+// b009 | +-+
+// | | +=v0028
+// b049 | | +-+
+// | | | | +=v0061
+// b071 | | | +-+
+// | | | +=v0062
+// b032 | | +-+
+// | | | | +=v0063
+// b072 | | | | +-+
+// | | | | | +=v0000
+// b050 | | | +-+
+// | | | | +=v0320
+// b073 | | | +-+
+// | | | +=v0384
+// b019 | +-+
+// | +=v0010
+// b002 +-+
+// | | +=v0011
+// b020 | | +-+
+// | | | | +=v0027
+// b051 | | | | +-+
+// | | | | | | +=v0059
+// b074 | | | | | +-+
+// | | | | | +=v0060
+// b033 | | | +-+
+// | | | | +=v1472
+// b086 | | | | +-+
+// | | | | | +=v1536
+// b075 | | | | +-+
+// | | | | | | +=v1600
+// b087 | | | | | +-+
+// | | | | | +=v1728
+// b052 | | | +-+
+// | | | +=v0018
+// b010 | | +-+
+// | | | | +=v0024
+// b053 | | | | +-+
+// | | | | | | +=v0049
+// b076 | | | | | +-+
+// | | | | | +=v0050
+// b034 | | | | +-+
+// | | | | | | +=v0051
+// b077 | | | | | | +-+
+// | | | | | | | +=v0052
+// b054 | | | | | +-+
+// | | | | | +=v0025
+// b021 | | | +-+
+// | | | | +=v0055
+// b078 | | | | +-+
+// | | | | | +=v0056
+// b055 | | | | +-+
+// | | | | | | +=v0057
+// b079 | | | | | +-+
+// | | | | | +=v0058
+// b035 | | | +-+
+// | | | +=v0192
+// b005 | +-+
+// | | +=v1664
+// b036 | | +-+
+// | | | | +=v0448
+// b080 | | | | +-+
+// | | | | | +=v0512
+// b056 | | | +-+
+// | | | | +=v0704
+// b088 | | | | +-+
+// | | | | | +=v0768
+// b081 | | | +-+
+// | | | +=v0640
+// b022 | | +-+
+// | | | | +=v0576
+// b082 | | | | +-+
+// | | | | | | +=v0832
+// b089 | | | | | +-+
+// | | | | | +=v0896
+// b057 | | | | +-+
+// | | | | | | +=v0960
+// b090 | | | | | | +-+
+// | | | | | | | +=v1024
+// b083 | | | | | +-+
+// | | | | | | +=v1088
+// b091 | | | | | +-+
+// | | | | | +=v1152
+// b037 | | | +-+
+// | | | | +=v1216
+// b092 | | | | +-+
+// | | | | | +=v1280
+// b084 | | | | +-+
+// | | | | | | +=v1344
+// b093 | | | | | +-+
+// | | | | | +=v1408
+// b058 | | | +-+
+// | | | +=v0256
+// b011 | +-+
+// | +=v0002
+// b001 +-+
+// | +=v0003
+// b012 | +-+
+// | | | +=v0128
+// b023 | | +-+
+// | | +=v0008
+// b006 | +-+
+// | | | +=v0009
+// b024 | | | +-+
+// | | | | | +=v0016
+// b038 | | | | +-+
+// | | | | +=v0017
+// b013 | | +-+
+// | | +=v0004
+// b003 +-+
+// | +=v0005
+// b014 | +-+
+// | | | +=v0014
+// b039 | | | +-+
+// | | | | +=v0015
+// b025 | | +-+
+// | | +=v0064
+// b007 +-+
+// | +=v0006
+// b015 +-+
+// +=v0007
+var whiteTable = [...][2]int16{
+ 0: {0, 0},
+ 1: {2, 3},
+ 2: {4, 5},
+ 3: {6, 7},
+ 4: {8, 9},
+ 5: {10, 11},
+ 6: {12, 13},
+ 7: {14, 15},
+ 8: {16, 17},
+ 9: {18, 19},
+ 10: {20, 21},
+ 11: {22, ^2},
+ 12: {^3, 23},
+ 13: {24, ^4},
+ 14: {^5, 25},
+ 15: {^6, ^7},
+ 16: {26, 27},
+ 17: {28, 29},
+ 18: {30, 31},
+ 19: {32, ^10},
+ 20: {^11, 33},
+ 21: {34, 35},
+ 22: {36, 37},
+ 23: {^128, ^8},
+ 24: {^9, 38},
+ 25: {39, ^64},
+ 26: {40, 41},
+ 27: {42, ^13},
+ 28: {43, 44},
+ 29: {45, ^1},
+ 30: {^12, 46},
+ 31: {47, 48},
+ 32: {49, 50},
+ 33: {51, 52},
+ 34: {53, 54},
+ 35: {55, ^192},
+ 36: {^1664, 56},
+ 37: {57, 58},
+ 38: {^16, ^17},
+ 39: {^14, ^15},
+ 40: {59, 60},
+ 41: {61, ^22},
+ 42: {^23, 62},
+ 43: {^20, 63},
+ 44: {64, 65},
+ 45: {^19, 66},
+ 46: {67, ^26},
+ 47: {68, 69},
+ 48: {70, ^21},
+ 49: {^28, 71},
+ 50: {72, 73},
+ 51: {^27, 74},
+ 52: {75, ^18},
+ 53: {^24, 76},
+ 54: {77, ^25},
+ 55: {78, 79},
+ 56: {80, 81},
+ 57: {82, 83},
+ 58: {84, ^256},
+ 59: {0, 85},
+ 60: {^29, ^30},
+ 61: {^45, ^46},
+ 62: {^47, ^48},
+ 63: {^33, ^34},
+ 64: {^35, ^36},
+ 65: {^37, ^38},
+ 66: {^31, ^32},
+ 67: {^53, ^54},
+ 68: {^39, ^40},
+ 69: {^41, ^42},
+ 70: {^43, ^44},
+ 71: {^61, ^62},
+ 72: {^63, ^0},
+ 73: {^320, ^384},
+ 74: {^59, ^60},
+ 75: {86, 87},
+ 76: {^49, ^50},
+ 77: {^51, ^52},
+ 78: {^55, ^56},
+ 79: {^57, ^58},
+ 80: {^448, ^512},
+ 81: {88, ^640},
+ 82: {^576, 89},
+ 83: {90, 91},
+ 84: {92, 93},
+ 85: {94, 95},
+ 86: {^1472, ^1536},
+ 87: {^1600, ^1728},
+ 88: {^704, ^768},
+ 89: {^832, ^896},
+ 90: {^960, ^1024},
+ 91: {^1088, ^1152},
+ 92: {^1216, ^1280},
+ 93: {^1344, ^1408},
+ 94: {96, 97},
+ 95: {98, 99},
+ 96: {^1792, 100},
+ 97: {101, 102},
+ 98: {^1856, ^1920},
+ 99: {103, 104},
+ 100: {^1984, ^2048},
+ 101: {^2112, ^2176},
+ 102: {^2240, ^2304},
+ 103: {^2368, ^2432},
+ 104: {^2496, ^2560},
+}
+
+// blackTable represents Tables 2 and 3 for a black run.
+//
+// +=XXXXX
+// b017 +-+
+// | | +=v1792
+// b042 | | +-+
+// | | | | +=v1984
+// b063 | | | +-+
+// | | | +=v2048
+// b029 | | +-+
+// | | | | +=v2112
+// b064 | | | | +-+
+// | | | | | +=v2176
+// b043 | | | +-+
+// | | | | +=v2240
+// b065 | | | +-+
+// | | | +=v2304
+// b022 | +-+
+// | | +=v1856
+// b044 | | +-+
+// | | | +=v1920
+// b030 | +-+
+// | | +=v2368
+// b066 | | +-+
+// | | | +=v2432
+// b045 | +-+
+// | | +=v2496
+// b067 | +-+
+// | +=v2560
+// b013 +-+
+// | | +=v0018
+// b031 | | +-+
+// | | | | +=v0052
+// b068 | | | | +-+
+// | | | | | | +=v0640
+// b095 | | | | | +-+
+// | | | | | +=v0704
+// b046 | | | +-+
+// | | | | +=v0768
+// b096 | | | | +-+
+// | | | | | +=v0832
+// b069 | | | +-+
+// | | | +=v0055
+// b023 | | +-+
+// | | | | +=v0056
+// b070 | | | | +-+
+// | | | | | | +=v1280
+// b097 | | | | | +-+
+// | | | | | +=v1344
+// b047 | | | | +-+
+// | | | | | | +=v1408
+// b098 | | | | | | +-+
+// | | | | | | | +=v1472
+// b071 | | | | | +-+
+// | | | | | +=v0059
+// b032 | | | +-+
+// | | | | +=v0060
+// b072 | | | | +-+
+// | | | | | | +=v1536
+// b099 | | | | | +-+
+// | | | | | +=v1600
+// b048 | | | +-+
+// | | | +=v0024
+// b018 | +-+
+// | | +=v0025
+// b049 | | +-+
+// | | | | +=v1664
+// b100 | | | | +-+
+// | | | | | +=v1728
+// b073 | | | +-+
+// | | | +=v0320
+// b033 | | +-+
+// | | | | +=v0384
+// b074 | | | | +-+
+// | | | | | +=v0448
+// b050 | | | +-+
+// | | | | +=v0512
+// b101 | | | | +-+
+// | | | | | +=v0576
+// b075 | | | +-+
+// | | | +=v0053
+// b024 | +-+
+// | | +=v0054
+// b076 | | +-+
+// | | | | +=v0896
+// b102 | | | +-+
+// | | | +=v0960
+// b051 | | +-+
+// | | | | +=v1024
+// b103 | | | | +-+
+// | | | | | +=v1088
+// b077 | | | +-+
+// | | | | +=v1152
+// b104 | | | +-+
+// | | | +=v1216
+// b034 | +-+
+// | +=v0064
+// b010 +-+
+// | | +=v0013
+// b019 | | +-+
+// | | | | +=v0023
+// b052 | | | | +-+
+// | | | | | | +=v0050
+// b078 | | | | | +-+
+// | | | | | +=v0051
+// b035 | | | | +-+
+// | | | | | | +=v0044
+// b079 | | | | | | +-+
+// | | | | | | | +=v0045
+// b053 | | | | | +-+
+// | | | | | | +=v0046
+// b080 | | | | | +-+
+// | | | | | +=v0047
+// b025 | | | +-+
+// | | | | +=v0057
+// b081 | | | | +-+
+// | | | | | +=v0058
+// b054 | | | | +-+
+// | | | | | | +=v0061
+// b082 | | | | | +-+
+// | | | | | +=v0256
+// b036 | | | +-+
+// | | | +=v0016
+// b014 | +-+
+// | | +=v0017
+// b037 | | +-+
+// | | | | +=v0048
+// b083 | | | | +-+
+// | | | | | +=v0049
+// b055 | | | +-+
+// | | | | +=v0062
+// b084 | | | +-+
+// | | | +=v0063
+// b026 | | +-+
+// | | | | +=v0030
+// b085 | | | | +-+
+// | | | | | +=v0031
+// b056 | | | | +-+
+// | | | | | | +=v0032
+// b086 | | | | | +-+
+// | | | | | +=v0033
+// b038 | | | +-+
+// | | | | +=v0040
+// b087 | | | | +-+
+// | | | | | +=v0041
+// b057 | | | +-+
+// | | | +=v0022
+// b020 | +-+
+// | +=v0014
+// b008 +-+
+// | | +=v0010
+// b015 | | +-+
+// | | | +=v0011
+// b011 | +-+
+// | | +=v0015
+// b027 | | +-+
+// | | | | +=v0128
+// b088 | | | | +-+
+// | | | | | +=v0192
+// b058 | | | | +-+
+// | | | | | | +=v0026
+// b089 | | | | | +-+
+// | | | | | +=v0027
+// b039 | | | +-+
+// | | | | +=v0028
+// b090 | | | | +-+
+// | | | | | +=v0029
+// b059 | | | +-+
+// | | | +=v0019
+// b021 | | +-+
+// | | | | +=v0020
+// b060 | | | | +-+
+// | | | | | | +=v0034
+// b091 | | | | | +-+
+// | | | | | +=v0035
+// b040 | | | | +-+
+// | | | | | | +=v0036
+// b092 | | | | | | +-+
+// | | | | | | | +=v0037
+// b061 | | | | | +-+
+// | | | | | | +=v0038
+// b093 | | | | | +-+
+// | | | | | +=v0039
+// b028 | | | +-+
+// | | | | +=v0021
+// b062 | | | | +-+
+// | | | | | | +=v0042
+// b094 | | | | | +-+
+// | | | | | +=v0043
+// b041 | | | +-+
+// | | | +=v0000
+// b016 | +-+
+// | +=v0012
+// b006 +-+
+// | | +=v0009
+// b012 | | +-+
+// | | | +=v0008
+// b009 | +-+
+// | +=v0007
+// b004 +-+
+// | | +=v0006
+// b007 | +-+
+// | +=v0005
+// b002 +-+
+// | | +=v0001
+// b005 | +-+
+// | +=v0004
+// b001 +-+
+// | +=v0003
+// b003 +-+
+// +=v0002
+var blackTable = [...][2]int16{
+ 0: {0, 0},
+ 1: {2, 3},
+ 2: {4, 5},
+ 3: {^3, ^2},
+ 4: {6, 7},
+ 5: {^1, ^4},
+ 6: {8, 9},
+ 7: {^6, ^5},
+ 8: {10, 11},
+ 9: {12, ^7},
+ 10: {13, 14},
+ 11: {15, 16},
+ 12: {^9, ^8},
+ 13: {17, 18},
+ 14: {19, 20},
+ 15: {^10, ^11},
+ 16: {21, ^12},
+ 17: {0, 22},
+ 18: {23, 24},
+ 19: {^13, 25},
+ 20: {26, ^14},
+ 21: {27, 28},
+ 22: {29, 30},
+ 23: {31, 32},
+ 24: {33, 34},
+ 25: {35, 36},
+ 26: {37, 38},
+ 27: {^15, 39},
+ 28: {40, 41},
+ 29: {42, 43},
+ 30: {44, 45},
+ 31: {^18, 46},
+ 32: {47, 48},
+ 33: {49, 50},
+ 34: {51, ^64},
+ 35: {52, 53},
+ 36: {54, ^16},
+ 37: {^17, 55},
+ 38: {56, 57},
+ 39: {58, 59},
+ 40: {60, 61},
+ 41: {62, ^0},
+ 42: {^1792, 63},
+ 43: {64, 65},
+ 44: {^1856, ^1920},
+ 45: {66, 67},
+ 46: {68, 69},
+ 47: {70, 71},
+ 48: {72, ^24},
+ 49: {^25, 73},
+ 50: {74, 75},
+ 51: {76, 77},
+ 52: {^23, 78},
+ 53: {79, 80},
+ 54: {81, 82},
+ 55: {83, 84},
+ 56: {85, 86},
+ 57: {87, ^22},
+ 58: {88, 89},
+ 59: {90, ^19},
+ 60: {^20, 91},
+ 61: {92, 93},
+ 62: {^21, 94},
+ 63: {^1984, ^2048},
+ 64: {^2112, ^2176},
+ 65: {^2240, ^2304},
+ 66: {^2368, ^2432},
+ 67: {^2496, ^2560},
+ 68: {^52, 95},
+ 69: {96, ^55},
+ 70: {^56, 97},
+ 71: {98, ^59},
+ 72: {^60, 99},
+ 73: {100, ^320},
+ 74: {^384, ^448},
+ 75: {101, ^53},
+ 76: {^54, 102},
+ 77: {103, 104},
+ 78: {^50, ^51},
+ 79: {^44, ^45},
+ 80: {^46, ^47},
+ 81: {^57, ^58},
+ 82: {^61, ^256},
+ 83: {^48, ^49},
+ 84: {^62, ^63},
+ 85: {^30, ^31},
+ 86: {^32, ^33},
+ 87: {^40, ^41},
+ 88: {^128, ^192},
+ 89: {^26, ^27},
+ 90: {^28, ^29},
+ 91: {^34, ^35},
+ 92: {^36, ^37},
+ 93: {^38, ^39},
+ 94: {^42, ^43},
+ 95: {^640, ^704},
+ 96: {^768, ^832},
+ 97: {^1280, ^1344},
+ 98: {^1408, ^1472},
+ 99: {^1536, ^1600},
+ 100: {^1664, ^1728},
+ 101: {^512, ^576},
+ 102: {^896, ^960},
+ 103: {^1024, ^1088},
+ 104: {^1152, ^1216},
+}
+
+// COPY PASTE table.go BEGIN
+
+const (
+ modePass = iota // Pass
+ modeH // Horizontal
+ modeV0 // Vertical-0
+ modeVR1 // Vertical-Right-1
+ modeVR2 // Vertical-Right-2
+ modeVR3 // Vertical-Right-3
+ modeVL1 // Vertical-Left-1
+ modeVL2 // Vertical-Left-2
+ modeVL3 // Vertical-Left-3
+ modeExt // Extension
+ modeEOL // End-of-Line
+)
+
+// COPY PASTE table.go END
diff --git a/ccitt/table_test.go b/ccitt/table_test.go
new file mode 100644
index 0000000..f37077a
--- /dev/null
+++ b/ccitt/table_test.go
@@ -0,0 +1,253 @@
+// generated by "go run gen.go". DO NOT EDIT.
+
+package ccitt
+
+// COPY PASTE table_test.go BEGIN
+
+type code struct {
+ val uint32
+ str string
+}
+
+var modeCodes = []code{
+ {modePass, "0001"},
+ {modeH, "001"},
+ {modeV0, "1"},
+ {modeVR1, "011"},
+ {modeVR2, "000011"},
+ {modeVR3, "0000011"},
+ {modeVL1, "010"},
+ {modeVL2, "000010"},
+ {modeVL3, "0000010"},
+ {modeExt, "0000001"},
+
+ // End-of-Line is not in Table 1, but we look for it at the same time that
+ // we look for other mode codes.
+ {modeEOL, "000000000001"},
+}
+
+var whiteCodes = []code{
+ // Terminating codes (0-63).
+ {0x0000, "00110101"},
+ {0x0001, "000111"},
+ {0x0002, "0111"},
+ {0x0003, "1000"},
+ {0x0004, "1011"},
+ {0x0005, "1100"},
+ {0x0006, "1110"},
+ {0x0007, "1111"},
+ {0x0008, "10011"},
+ {0x0009, "10100"},
+ {0x000A, "00111"},
+ {0x000B, "01000"},
+ {0x000C, "001000"},
+ {0x000D, "000011"},
+ {0x000E, "110100"},
+ {0x000F, "110101"},
+ {0x0010, "101010"},
+ {0x0011, "101011"},
+ {0x0012, "0100111"},
+ {0x0013, "0001100"},
+ {0x0014, "0001000"},
+ {0x0015, "0010111"},
+ {0x0016, "0000011"},
+ {0x0017, "0000100"},
+ {0x0018, "0101000"},
+ {0x0019, "0101011"},
+ {0x001A, "0010011"},
+ {0x001B, "0100100"},
+ {0x001C, "0011000"},
+ {0x001D, "00000010"},
+ {0x001E, "00000011"},
+ {0x001F, "00011010"},
+ {0x0020, "00011011"},
+ {0x0021, "00010010"},
+ {0x0022, "00010011"},
+ {0x0023, "00010100"},
+ {0x0024, "00010101"},
+ {0x0025, "00010110"},
+ {0x0026, "00010111"},
+ {0x0027, "00101000"},
+ {0x0028, "00101001"},
+ {0x0029, "00101010"},
+ {0x002A, "00101011"},
+ {0x002B, "00101100"},
+ {0x002C, "00101101"},
+ {0x002D, "00000100"},
+ {0x002E, "00000101"},
+ {0x002F, "00001010"},
+ {0x0030, "00001011"},
+ {0x0031, "01010010"},
+ {0x0032, "01010011"},
+ {0x0033, "01010100"},
+ {0x0034, "01010101"},
+ {0x0035, "00100100"},
+ {0x0036, "00100101"},
+ {0x0037, "01011000"},
+ {0x0038, "01011001"},
+ {0x0039, "01011010"},
+ {0x003A, "01011011"},
+ {0x003B, "01001010"},
+ {0x003C, "01001011"},
+ {0x003D, "00110010"},
+ {0x003E, "00110011"},
+ {0x003F, "00110100"},
+
+ // Make-up codes between 64 and 1728.
+ {0x0040, "11011"},
+ {0x0080, "10010"},
+ {0x00C0, "010111"},
+ {0x0100, "0110111"},
+ {0x0140, "00110110"},
+ {0x0180, "00110111"},
+ {0x01C0, "01100100"},
+ {0x0200, "01100101"},
+ {0x0240, "01101000"},
+ {0x0280, "01100111"},
+ {0x02C0, "011001100"},
+ {0x0300, "011001101"},
+ {0x0340, "011010010"},
+ {0x0380, "011010011"},
+ {0x03C0, "011010100"},
+ {0x0400, "011010101"},
+ {0x0440, "011010110"},
+ {0x0480, "011010111"},
+ {0x04C0, "011011000"},
+ {0x0500, "011011001"},
+ {0x0540, "011011010"},
+ {0x0580, "011011011"},
+ {0x05C0, "010011000"},
+ {0x0600, "010011001"},
+ {0x0640, "010011010"},
+ {0x0680, "011000"},
+ {0x06C0, "010011011"},
+
+ // Make-up codes between 1792 and 2560.
+ {0x0700, "00000001000"},
+ {0x0740, "00000001100"},
+ {0x0780, "00000001101"},
+ {0x07C0, "000000010010"},
+ {0x0800, "000000010011"},
+ {0x0840, "000000010100"},
+ {0x0880, "000000010101"},
+ {0x08C0, "000000010110"},
+ {0x0900, "000000010111"},
+ {0x0940, "000000011100"},
+ {0x0980, "000000011101"},
+ {0x09C0, "000000011110"},
+ {0x0A00, "000000011111"},
+}
+
+var blackCodes = []code{
+ // Terminating codes (0-63).
+ {0x0000, "0000110111"},
+ {0x0001, "010"},
+ {0x0002, "11"},
+ {0x0003, "10"},
+ {0x0004, "011"},
+ {0x0005, "0011"},
+ {0x0006, "0010"},
+ {0x0007, "00011"},
+ {0x0008, "000101"},
+ {0x0009, "000100"},
+ {0x000A, "0000100"},
+ {0x000B, "0000101"},
+ {0x000C, "0000111"},
+ {0x000D, "00000100"},
+ {0x000E, "00000111"},
+ {0x000F, "000011000"},
+ {0x0010, "0000010111"},
+ {0x0011, "0000011000"},
+ {0x0012, "0000001000"},
+ {0x0013, "00001100111"},
+ {0x0014, "00001101000"},
+ {0x0015, "00001101100"},
+ {0x0016, "00000110111"},
+ {0x0017, "00000101000"},
+ {0x0018, "00000010111"},
+ {0x0019, "00000011000"},
+ {0x001A, "000011001010"},
+ {0x001B, "000011001011"},
+ {0x001C, "000011001100"},
+ {0x001D, "000011001101"},
+ {0x001E, "000001101000"},
+ {0x001F, "000001101001"},
+ {0x0020, "000001101010"},
+ {0x0021, "000001101011"},
+ {0x0022, "000011010010"},
+ {0x0023, "000011010011"},
+ {0x0024, "000011010100"},
+ {0x0025, "000011010101"},
+ {0x0026, "000011010110"},
+ {0x0027, "000011010111"},
+ {0x0028, "000001101100"},
+ {0x0029, "000001101101"},
+ {0x002A, "000011011010"},
+ {0x002B, "000011011011"},
+ {0x002C, "000001010100"},
+ {0x002D, "000001010101"},
+ {0x002E, "000001010110"},
+ {0x002F, "000001010111"},
+ {0x0030, "000001100100"},
+ {0x0031, "000001100101"},
+ {0x0032, "000001010010"},
+ {0x0033, "000001010011"},
+ {0x0034, "000000100100"},
+ {0x0035, "000000110111"},
+ {0x0036, "000000111000"},
+ {0x0037, "000000100111"},
+ {0x0038, "000000101000"},
+ {0x0039, "000001011000"},
+ {0x003A, "000001011001"},
+ {0x003B, "000000101011"},
+ {0x003C, "000000101100"},
+ {0x003D, "000001011010"},
+ {0x003E, "000001100110"},
+ {0x003F, "000001100111"},
+
+ // Make-up codes between 64 and 1728.
+ {0x0040, "0000001111"},
+ {0x0080, "000011001000"},
+ {0x00C0, "000011001001"},
+ {0x0100, "000001011011"},
+ {0x0140, "000000110011"},
+ {0x0180, "000000110100"},
+ {0x01C0, "000000110101"},
+ {0x0200, "0000001101100"},
+ {0x0240, "0000001101101"},
+ {0x0280, "0000001001010"},
+ {0x02C0, "0000001001011"},
+ {0x0300, "0000001001100"},
+ {0x0340, "0000001001101"},
+ {0x0380, "0000001110010"},
+ {0x03C0, "0000001110011"},
+ {0x0400, "0000001110100"},
+ {0x0440, "0000001110101"},
+ {0x0480, "0000001110110"},
+ {0x04C0, "0000001110111"},
+ {0x0500, "0000001010010"},
+ {0x0540, "0000001010011"},
+ {0x0580, "0000001010100"},
+ {0x05C0, "0000001010101"},
+ {0x0600, "0000001011010"},
+ {0x0640, "0000001011011"},
+ {0x0680, "0000001100100"},
+ {0x06C0, "0000001100101"},
+
+ // Make-up codes between 1792 and 2560.
+ {0x0700, "00000001000"},
+ {0x0740, "00000001100"},
+ {0x0780, "00000001101"},
+ {0x07C0, "000000010010"},
+ {0x0800, "000000010011"},
+ {0x0840, "000000010100"},
+ {0x0880, "000000010101"},
+ {0x08C0, "000000010110"},
+ {0x0900, "000000010111"},
+ {0x0940, "000000011100"},
+ {0x0980, "000000011101"},
+ {0x09C0, "000000011110"},
+ {0x0A00, "000000011111"},
+}
+
+// COPY PASTE table_test.go END