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