diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/gen.go golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/gen.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/gen.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/gen.go 2019-07-28 02:13:45.000000000 +0000 @@ -0,0 +1,524 @@ +// 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), "modeDecodeTable", + "// modeDecodeTable represents Table 1 and the End-of-Line code.\n") + write(w, build(whiteCodes[:], 0), "whiteDecodeTable", + "// whiteDecodeTable represents Tables 2 and 3 for a white run.\n") + write(w, build(blackCodes[:], 0), "blackDecodeTable", + "// blackDecodeTable represents Tables 2 and 3 for a black run.\n") + writeMaxCodeLength(w, modeCodes[:], whiteCodes[:], blackCodes[:]) + 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 decodeTable 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 decodeTable 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 modeDecodeTable, 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 writeMaxCodeLength(w *bytes.Buffer, codesList ...[]code) { + maxCodeLength := 0 + for _, codes := range codesList { + for _, code := range codes { + if n := len(code.str); maxCodeLength < n { + maxCodeLength = n + } + } + } + fmt.Fprintf(w, "const maxCodeLength = %d\n\n", maxCodeLength) +} + +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 -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/reader.go golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/reader.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/reader.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/reader.go 2019-07-28 02:13:45.000000000 +0000 @@ -0,0 +1,660 @@ +// 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" + "image" + "io" + "math/bits" +) + +var ( + errInvalidBounds = errors.New("ccitt: invalid bounds") + errInvalidCode = errors.New("ccitt: invalid code") + errInvalidMode = errors.New("ccitt: invalid mode") + errInvalidOffset = errors.New("ccitt: invalid offset") + errMissingEOL = errors.New("ccitt: missing End-of-Line") + errRunLengthOverflowsWidth = errors.New("ccitt: run length overflows width") + errRunLengthTooLong = errors.New("ccitt: run length too long") + errUnsupportedMode = errors.New("ccitt: unsupported mode") + errUnsupportedSubFormat = errors.New("ccitt: unsupported sub-format") + errUnsupportedWidth = errors.New("ccitt: unsupported width") +) + +// 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 +) + +// SubFormat represents that the CCITT format consists of a number of +// sub-formats. Decoding or encoding a CCITT data stream requires knowing the +// sub-format context. It is not represented in the data stream per se. +type SubFormat uint32 + +const ( + Group3 SubFormat = iota + Group4 +) + +// Options are optional parameters. +type Options struct { + // Align means that some variable-bit-width codes are byte-aligned. + Align bool + // Invert means that black is the 1 bit or 0xFF byte, and white is 0. + Invert bool +} + +// maxWidth is the maximum (inclusive) supported width. This is a limitation of +// this implementation, to guard against integer overflow, and not anything +// inherent to the CCITT format. +const maxWidth = 1 << 20 + +func invertBytes(b []byte) { + for i, c := range b { + b[i] = ^c + } +} + +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 is whether to process r's bytes LSB first or MSB first. + 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 +} + +// nextBitMaxNBits is the maximum possible value of bitReader.nBits after a +// bitReader.nextBit call, provided that bitReader.nBits was not more than this +// value before that call. +// +// Note that the decode function can unread bits, which can temporarily set the +// bitReader.nBits value above nextBitMaxNBits. +const nextBitMaxNBits = 31 + +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 >= 4 { + // Read 32 bits, even though b.bits is a uint64, since the decode + // function may need to unread up to maxCodeLength bits, putting + // them back in the remaining (64 - 32) bits. TestMaxCodeLength + // checks that the generated maxCodeLength constant fits. + // + // If changing the Uint32 call, also change nextBitMaxNBits. + b.bits = uint64(binary.LittleEndian.Uint32(b.bytes[b.br:])) + b.br += 4 + b.nBits = 32 + 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, decodeTable [][2]int16) (uint32, error) { + nBitsRead, bitsRead, state := uint32(0), uint32(0), int32(1) + for { + bit, err := b.nextBit() + if err != nil { + return 0, err + } + bitsRead |= bit << nBitsRead + nBitsRead++ + // The "&1" is redundant, but can eliminate a bounds check. + state = int32(decodeTable[state][bit&1]) + if state < 0 { + return uint32(^state), nil + } else if state == 0 { + // Unread the bits we've read, then return errInvalidCode. + b.bits = (b.bits << nBitsRead) | uint64(bitsRead) + b.nBits += nBitsRead + return 0, errInvalidCode + } + } +} + +type reader struct { + br bitReader + subFormat SubFormat + + // width is the image width in pixels. + width int + + // rowsRemaining starts at the image height in pixels, when the reader is + // driven through the io.Reader interface, and decrements to zero as rows + // are decoded. When driven through DecodeIntoGray, this field is unused. + rowsRemaining int + + // curr and prev hold the current and previous rows. Each element is either + // 0x00 (black) or 0xFF (white). + // + // prev may be nil, when processing the first row. + curr []byte + prev []byte + + // ri is the read index. curr[:ri] are those bytes of curr that have been + // passed along via the Read method. + // + // When the reader is driven through DecodeIntoGray, instead of through the + // io.Reader interface, this field is unused. + ri int + + // wi is the write index. curr[:wi] are those bytes of curr that have + // already been decoded via the decodeRow method. + // + // What this implementation calls wi is roughly equivalent to what the spec + // calls the a0 index. + wi int + + // These fields are copied from the *Options (which may be nil). + align bool + invert bool + + // atStartOfRow is whether we have just started the row. Some parts of the + // spec say to treat this situation as if "wi = -1". + atStartOfRow bool + + // penColorIsWhite is whether the next run is black or white. + penColorIsWhite bool + + // seenStartOfImage is whether we've called the startDecode method. + seenStartOfImage bool + + // readErr is a sticky error for the Read method. + readErr error +} + +func (z *reader) Read(p []byte) (int, error) { + if z.readErr != nil { + return 0, z.readErr + } + originalP := p + + for len(p) > 0 { + // Allocate buffers (and decode any start-of-image codes), if + // processing the first or second row. + if z.curr == nil { + if !z.seenStartOfImage { + if z.readErr = z.startDecode(); z.readErr != nil { + break + } + z.atStartOfRow = true + } + z.curr = make([]byte, z.width) + } + + // Decode the next row, if necessary. + if z.atStartOfRow { + if z.rowsRemaining <= 0 { + if z.readErr = z.finishDecode(); z.readErr != nil { + break + } + z.readErr = io.EOF + break + } + if z.readErr = z.decodeRow(); z.readErr != nil { + break + } + z.rowsRemaining-- + } + + // Pack from z.curr (1 byte per pixel) to p (1 bit per pixel), up to 8 + // elements per iteration. + i := 0 + for ; i < len(p); i++ { + numToPack := len(z.curr) - z.ri + if numToPack <= 0 { + break + } else if numToPack > 8 { + numToPack = 8 + } + + byteValue := byte(0) + for j := 0; j < numToPack; j++ { + byteValue |= (z.curr[z.ri] & 0x80) >> uint(j) + z.ri++ + } + p[i] = byteValue + } + p = p[i:] + + // Prepare to decode the next row, if necessary. + if z.ri == len(z.curr) { + z.ri, z.curr, z.prev = 0, z.prev, z.curr + z.atStartOfRow = true + } + } + + n := len(originalP) - len(p) + // TODO: when invert is true, should the end-of-row padding bits be 0 or 1? + if z.invert { + invertBytes(originalP[:n]) + } + return n, z.readErr +} + +func (z *reader) penColor() byte { + if z.penColorIsWhite { + return 0xFF + } + return 0x00 +} + +func (z *reader) startDecode() error { + switch z.subFormat { + case Group3: + if err := z.decodeEOL(); err != nil { + return err + } + + case Group4: + // No-op. + + default: + return errUnsupportedSubFormat + } + + z.seenStartOfImage = true + return nil +} + +func (z *reader) finishDecode() error { + numberOfEOLs := 0 + switch z.subFormat { + case Group3: + // The stream ends with a RTC (Return To Control) of 6 consecutive + // EOL's, but we should have already just seen an EOL, either in + // z.startDecode (for a zero-height image) or in z.decodeRow. + numberOfEOLs = 5 + + case Group4: + // The stream ends with two EOL's, the first of which is possibly + // byte-aligned. + numberOfEOLs = 2 + if err := z.decodeEOL(); err == nil { + numberOfEOLs-- + } else if err == errInvalidCode { + // Try again, this time starting from a byte boundary. + z.br.alignToByteBoundary() + } else { + return err + } + + default: + return errUnsupportedSubFormat + } + + for ; numberOfEOLs > 0; numberOfEOLs-- { + if err := z.decodeEOL(); err != nil { + return err + } + } + return nil +} + +func (z *reader) decodeEOL() error { + // TODO: EOL doesn't have to be in the modeDecodeTable. It could be in its + // own table, or we could just hard-code it, especially if we might need to + // cater for optional byte-alignment, or an arbitrary number (potentially + // more than 8) of 0-valued padding bits. + if mode, err := decode(&z.br, modeDecodeTable[:]); err != nil { + return err + } else if mode != modeEOL { + return errMissingEOL + } + return nil +} + +func (z *reader) decodeRow() error { + z.wi = 0 + z.atStartOfRow = true + z.penColorIsWhite = true + + switch z.subFormat { + case Group3: + for ; z.wi < len(z.curr); z.atStartOfRow = false { + if err := z.decodeRun(); err != nil { + return err + } + } + return z.decodeEOL() + + case Group4: + if z.align { + z.br.alignToByteBoundary() + } + + for ; z.wi < len(z.curr); z.atStartOfRow = false { + mode, err := decode(&z.br, modeDecodeTable[:]) + if err != nil { + return err + } + rm := readerMode{} + if mode < uint32(len(readerModes)) { + rm = readerModes[mode] + } + if rm.function == nil { + return errInvalidMode + } + if err := rm.function(z, rm.arg); err != nil { + return err + } + } + return nil + } + + return errUnsupportedSubFormat +} + +func (z *reader) decodeRun() error { + table := blackDecodeTable[:] + if z.penColorIsWhite { + table = whiteDecodeTable[:] + } + + total := 0 + for { + n, err := decode(&z.br, table) + if err != nil { + return err + } + if n > maxWidth { + panic("unreachable") + } + total += int(n) + if total > maxWidth { + return errRunLengthTooLong + } + // Anything 0x3F or below is a terminal code. + if n <= 0x3F { + break + } + } + + if total > (len(z.curr) - z.wi) { + return errRunLengthOverflowsWidth + } + dst := z.curr[z.wi : z.wi+total] + penColor := z.penColor() + for i := range dst { + dst[i] = penColor + } + z.wi += total + z.penColorIsWhite = !z.penColorIsWhite + + return nil +} + +// The various modes' semantics are based on determining a row of pixels' +// "changing elements": those pixels whose color differs from the one on its +// immediate left. +// +// The row above the first row is implicitly all white. Similarly, the column +// to the left of the first column is implicitly all white. +// +// For example, here's Figure 1 in "ITU-T Recommendation T.6", where the +// current and previous rows contain black (B) and white (w) pixels. The a? +// indexes point into curr, the b? indexes point into prev. +// +// b1 b2 +// v v +// prev: BBBBBwwwwwBBBwwwww +// curr: BBBwwwwwBBBBBBwwww +// ^ ^ ^ +// a0 a1 a2 +// +// a0 is the "reference element" or current decoder position, roughly +// equivalent to what this implementation calls reader.wi. +// +// a1 is the next changing element to the right of a0, on the "coding line" +// (the current row). +// +// a2 is the next changing element to the right of a1, again on curr. +// +// b1 is the first changing element on the "reference line" (the previous row) +// to the right of a0 and of opposite color to a0. +// +// b2 is the next changing element to the right of b1, again on prev. +// +// The various modes calculate a1 (and a2, for modeH): +// - modePass calculates that a1 is at or to the right of b2. +// - modeH calculates a1 and a2 without considering b1 or b2. +// - modeV* calculates a1 to be b1 plus an adjustment (between -3 and +3). + +const ( + findB1 = false + findB2 = true +) + +// findB finds either the b1 or b2 value. +func (z *reader) findB(whichB bool) int { + // The initial row is a special case. The previous row is implicitly all + // white, so that there are no changing pixel elements. We return b1 or b2 + // to be at the end of the row. + if len(z.prev) != len(z.curr) { + return len(z.curr) + } + + i := z.wi + + if z.atStartOfRow { + // a0 is implicitly at -1, on a white pixel. b1 is the first black + // pixel in the previous row. b2 is the first white pixel after that. + for ; (i < len(z.prev)) && (z.prev[i] == 0xFF); i++ { + } + if whichB == findB2 { + for ; (i < len(z.prev)) && (z.prev[i] == 0x00); i++ { + } + } + return i + } + + // As per figure 1 above, assume that the current pen color is white. + // First, walk past every contiguous black pixel in prev, starting at a0. + oppositeColor := ^z.penColor() + for ; (i < len(z.prev)) && (z.prev[i] == oppositeColor); i++ { + } + + // Then walk past every contiguous white pixel. + penColor := ^oppositeColor + for ; (i < len(z.prev)) && (z.prev[i] == penColor); i++ { + } + + // We're now at a black pixel (or at the end of the row). That's b1. + if whichB == findB2 { + // If we're looking for b2, walk past every contiguous black pixel + // again. + oppositeColor := ^penColor + for ; (i < len(z.prev)) && (z.prev[i] == oppositeColor); i++ { + } + } + + return i +} + +type readerMode struct { + function func(z *reader, arg int) error + arg int +} + +var readerModes = [...]readerMode{ + modePass: {function: readerModePass}, + modeH: {function: readerModeH}, + modeV0: {function: readerModeV, arg: +0}, + modeVR1: {function: readerModeV, arg: +1}, + modeVR2: {function: readerModeV, arg: +2}, + modeVR3: {function: readerModeV, arg: +3}, + modeVL1: {function: readerModeV, arg: -1}, + modeVL2: {function: readerModeV, arg: -2}, + modeVL3: {function: readerModeV, arg: -3}, + modeExt: {function: readerModeExt}, +} + +func readerModePass(z *reader, arg int) error { + b2 := z.findB(findB2) + if (b2 < z.wi) || (len(z.curr) < b2) { + return errInvalidOffset + } + dst := z.curr[z.wi:b2] + penColor := z.penColor() + for i := range dst { + dst[i] = penColor + } + z.wi = b2 + return nil +} + +func readerModeH(z *reader, arg int) error { + // The first iteration finds a1. The second finds a2. + for i := 0; i < 2; i++ { + if err := z.decodeRun(); err != nil { + return err + } + } + return nil +} + +func readerModeV(z *reader, arg int) error { + a1 := z.findB(findB1) + arg + if (a1 < z.wi) || (len(z.curr) < a1) { + return errInvalidOffset + } + dst := z.curr[z.wi:a1] + penColor := z.penColor() + for i := range dst { + dst[i] = penColor + } + z.wi = a1 + z.penColorIsWhite = !z.penColorIsWhite + return nil +} + +func readerModeExt(z *reader, arg int) error { + return errUnsupportedMode +} + +// DecodeIntoGray decodes the CCITT-formatted data in r into dst. +// +// It returns an error if dst's width and height don't match the implied width +// and height of CCITT-formatted data. +func DecodeIntoGray(dst *image.Gray, r io.Reader, order Order, sf SubFormat, opts *Options) error { + bounds := dst.Bounds() + if (bounds.Dx() < 0) || (bounds.Dy() < 0) { + return errInvalidBounds + } + if bounds.Dx() > maxWidth { + return errUnsupportedWidth + } + + z := reader{ + br: bitReader{r: r, order: order}, + subFormat: sf, + align: (opts != nil) && opts.Align, + invert: (opts != nil) && opts.Invert, + width: bounds.Dx(), + } + if err := z.startDecode(); err != nil { + return err + } + + width := bounds.Dx() + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + p := (y - bounds.Min.Y) * dst.Stride + z.curr = dst.Pix[p : p+width] + if err := z.decodeRow(); err != nil { + return err + } + z.curr, z.prev = nil, z.curr + } + + if err := z.finishDecode(); err != nil { + return err + } + + if z.invert { + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + p := (y - bounds.Min.Y) * dst.Stride + invertBytes(dst.Pix[p : p+width]) + } + } + + return nil +} + +// NewReader returns an io.Reader that decodes the CCITT-formatted data in r. +// The resultant byte stream is one bit per pixel (MSB first), with 1 meaning +// white and 0 meaning black. Each row in the result is byte-aligned. +func NewReader(r io.Reader, order Order, sf SubFormat, width int, height int, opts *Options) io.Reader { + readErr := error(nil) + if (width < 0) || (height < 0) { + readErr = errInvalidBounds + } else if width > maxWidth { + readErr = errUnsupportedWidth + } + + return &reader{ + br: bitReader{r: r, order: order}, + subFormat: sf, + align: (opts != nil) && opts.Align, + invert: (opts != nil) && opts.Invert, + width: width, + rowsRemaining: height, + readErr: readErr, + } +} diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/reader_test.go golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/reader_test.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/reader_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/reader_test.go 2019-07-28 02:13:45.000000000 +0000 @@ -0,0 +1,331 @@ +// 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" + "fmt" + "image" + "image/png" + "io" + "io/ioutil" + "os" + "path/filepath" + "reflect" + "testing" + "unsafe" +) + +func compareImages(t *testing.T, img0 image.Image, img1 image.Image) { + t.Helper() + + b0 := img0.Bounds() + b1 := img1.Bounds() + if b0 != b1 { + t.Fatalf("bounds differ: %v vs %v", b0, b1) + } + + for y := b0.Min.Y; y < b0.Max.Y; y++ { + for x := b0.Min.X; x < b0.Max.X; x++ { + c0 := img0.At(x, y) + c1 := img1.At(x, y) + if c0 != c1 { + t.Fatalf("pixel at (%d, %d) differs: %v vs %v", x, y, c0, c1) + } + } + } +} + +func decodePNG(fileName string) (image.Image, error) { + f, err := os.Open(fileName) + if err != nil { + return nil, err + } + defer f.Close() + return png.Decode(f) +} + +func TestMaxCodeLength(t *testing.T) { + br := bitReader{} + size := unsafe.Sizeof(br.bits) + size *= 8 // Convert from bytes to bits. + + // Check that the size of the bitReader.bits field is large enough to hold + // nextBitMaxNBits bits. + if size < nextBitMaxNBits { + t.Fatalf("size: got %d, want >= %d", size, nextBitMaxNBits) + } + + // Check that bitReader.nextBit will always leave enough spare bits in the + // bitReader.bits field such that the decode function can unread up to + // maxCodeLength bits. + if want := size - nextBitMaxNBits; maxCodeLength > want { + t.Fatalf("maxCodeLength: got %d, want <= %d", maxCodeLength, want) + } + + // The decode function also assumes that, when saving bits to possibly + // unread later, those bits fit inside a uint32. + if maxCodeLength > 32 { + t.Fatalf("maxCodeLength: got %d, want <= %d", maxCodeLength, 32) + } +} + +func testDecodeTable(t *testing.T, decodeTable [][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 in LSB order. + 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, decodeTable) + 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 TestModeDecodeTable(t *testing.T) { + testDecodeTable(t, modeDecodeTable[:], modeCodes, []uint32{ + modePass, + modeV0, + modeV0, + modeVL1, + modeVR3, + modeVL2, + modeExt, + modeVL1, + modeH, + modeVL1, + modeVL1, + modeEOL, + }) +} + +func TestWhiteDecodeTable(t *testing.T) { + testDecodeTable(t, whiteDecodeTable[:], whiteCodes, []uint32{ + 0, 1, 256, 7, 128, 3, 2560, + }) +} + +func TestBlackDecodeTable(t *testing.T) { + testDecodeTable(t, blackDecodeTable[:], blackCodes, []uint32{ + 63, 64, 63, 64, 64, 63, 22, 1088, 2048, 7, 6, 5, 4, 3, 2, 1, 0, + }) +} + +func TestDecodeInvalidCode(t *testing.T) { + // The bit stream is: + // 1 010 000000011011 + // Packing that LSB-first gives: + // 0b_1101_1000_0000_0101 + src := []byte{0x05, 0xD8} + + decodeTable := modeDecodeTable[:] + r := &bitReader{ + r: bytes.NewReader(src), + } + + // "1" decodes to the value 2. + if v, err := decode(r, decodeTable); v != 2 || err != nil { + t.Fatalf("decode #0: got (%v, %v), want (2, nil)", v, err) + } + + // "010" decodes to the value 6. + if v, err := decode(r, decodeTable); v != 6 || err != nil { + t.Fatalf("decode #0: got (%v, %v), want (6, nil)", v, err) + } + + // "00000001" is an invalid code. + if v, err := decode(r, decodeTable); v != 0 || err != errInvalidCode { + t.Fatalf("decode #0: got (%v, %v), want (0, %v)", v, err, errInvalidCode) + } + + // The bitReader should not have advanced after encountering an invalid + // code. The remaining bits should be "000000011011". + remaining := []byte(nil) + for { + bit, err := r.nextBit() + if err == io.EOF { + break + } else if err != nil { + t.Fatalf("nextBit: %v", err) + } + remaining = append(remaining, uint8('0'+bit)) + } + if got, want := string(remaining), "000000011011"; got != want { + t.Fatalf("remaining bits: got %q, want %q", got, want) + } +} + +func TestReadRegular(t *testing.T) { testRead(t, false) } +func TestReadInvert(t *testing.T) { testRead(t, true) } + +func testRead(t *testing.T, invert bool) { + t.Helper() + + const width, height = 153, 55 + opts := &Options{ + Invert: invert, + } + + got := "" + { + f, err := os.Open("testdata/bw-gopher.ccitt_group3") + if err != nil { + t.Fatalf("Open: %v", err) + } + defer f.Close() + gotBytes, err := ioutil.ReadAll(NewReader(f, MSB, Group3, width, height, opts)) + if err != nil { + t.Fatalf("ReadAll: %v", err) + } + got = string(gotBytes) + } + + want := "" + { + img, err := decodePNG("testdata/bw-gopher.png") + if err != nil { + t.Fatalf("decodePNG: %v", err) + } + gray, ok := img.(*image.Gray) + if !ok { + t.Fatalf("decodePNG: got %T, want *image.Gray", img) + } + bounds := gray.Bounds() + if w := bounds.Dx(); w != width { + t.Fatalf("width: got %d, want %d", w, width) + } + if h := bounds.Dy(); h != height { + t.Fatalf("height: got %d, want %d", h, height) + } + + // Prepare to extend each row's width to a multiple of 8, to simplify + // packing from 1 byte per pixel to 1 bit per pixel. + extended := make([]byte, (width+7)&^7) + + wantBytes := []byte(nil) + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + rowPix := gray.Pix[(y-bounds.Min.Y)*gray.Stride:] + rowPix = rowPix[:width] + copy(extended, rowPix) + + // Pack from 1 byte per pixel to 1 bit per pixel, MSB first. + byteValue := uint8(0) + for x, pixel := range extended { + byteValue |= (pixel & 0x80) >> uint(x&7) + if (x & 7) == 7 { + wantBytes = append(wantBytes, byteValue) + byteValue = 0 + } + } + } + if invert { + invertBytes(wantBytes) + } + want = string(wantBytes) + } + + // We expect a width of 153 pixels, which is 20 bytes per row (at 1 bit per + // pixel, plus 7 final bits of padding). Check that want is 20 * height + // bytes long, and if got != want, format them to split at every 20 bytes. + + if n := len(want); n != 20*height { + t.Fatalf("len(want): got %d, want %d", n, 20*height) + } + + format := func(s string) string { + b := []byte(nil) + for row := 0; len(s) >= 20; row++ { + b = append(b, fmt.Sprintf("row%02d: %02X\n", row, s[:20])...) + s = s[20:] + } + if len(s) > 0 { + b = append(b, fmt.Sprintf("%02X\n", s)...) + } + return string(b) + } + + if got != want { + t.Fatalf("got:\n%s\nwant:\n%s", format(got), format(want)) + } +} + +func TestDecodeIntoGray(t *testing.T) { + for _, tt := range []struct { + fileName string + sf SubFormat + w, h int + }{ + {"testdata/bw-gopher.ccitt_group3", Group3, 153, 55}, + {"testdata/bw-gopher.ccitt_group4", Group4, 153, 55}, + } { + t.Run(tt.fileName, func(t *testing.T) { + testDecodeIntoGray(t, tt.fileName, MSB, tt.sf, tt.w, tt.h, nil) + }) + } +} + +func testDecodeIntoGray(t *testing.T, fileName string, order Order, sf SubFormat, width int, height int, opts *Options) { + t.Helper() + + f, err := os.Open(filepath.FromSlash(fileName)) + if err != nil { + t.Fatalf("Open: %v", err) + } + defer f.Close() + + got := image.NewGray(image.Rect(0, 0, width, height)) + if err := DecodeIntoGray(got, f, order, sf, opts); err != nil { + t.Fatalf("DecodeIntoGray: %v", err) + } + + baseName := fileName[:len(fileName)-len(filepath.Ext(fileName))] + want, err := decodePNG(baseName + ".png") + if err != nil { + t.Fatal(err) + } + + compareImages(t, got, want) +} diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/table.go golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/table.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/table.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/table.go 2019-07-28 02:13:45.000000000 +0000 @@ -0,0 +1,740 @@ +// generated by "go run gen.go". DO NOT EDIT. + +package ccitt + +// Each decodeTable 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 decodeTable 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 modeDecodeTable, 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 + +// modeDecodeTable 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 modeDecodeTable = [...][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}, +} + +// whiteDecodeTable 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 whiteDecodeTable = [...][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}, +} + +// blackDecodeTable 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 blackDecodeTable = [...][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}, +} + +const maxCodeLength = 13 + +// 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 -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/table_test.go golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/table_test.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/table_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/table_test.go 2019-07-28 02:13:45.000000000 +0000 @@ -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 Binary files /tmp/tmpPYcZLE/kwAVadWSES/golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/testdata/bw-gopher.ccitt_group3 and /tmp/tmpPYcZLE/f_Qwz2ceYJ/golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/testdata/bw-gopher.ccitt_group3 differ Binary files /tmp/tmpPYcZLE/kwAVadWSES/golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/testdata/bw-gopher.ccitt_group4 and /tmp/tmpPYcZLE/f_Qwz2ceYJ/golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/testdata/bw-gopher.ccitt_group4 differ Binary files /tmp/tmpPYcZLE/kwAVadWSES/golang-golang-x-image-0.0~git20190321.3fc05d4/ccitt/testdata/bw-gopher.png and /tmp/tmpPYcZLE/f_Qwz2ceYJ/golang-golang-x-image-0.0~git20190703.d6a02ce/ccitt/testdata/bw-gopher.png differ diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/debian/changelog golang-golang-x-image-0.0~git20190703.d6a02ce/debian/changelog --- golang-golang-x-image-0.0~git20190321.3fc05d4/debian/changelog 2019-04-14 09:50:08.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/debian/changelog 2019-07-28 03:38:57.000000000 +0000 @@ -1,3 +1,26 @@ +golang-golang-x-image (0.0~git20190703.d6a02ce-1) unstable; urgency=medium + + * New upstream version 0.0~git20190703.d6a02ce + + -- Anthony Fok Sat, 27 Jul 2019 21:38:57 -0600 + +golang-golang-x-image (0.0~git20190321.3fc05d4+really0.0~git20190321.3fc05d4-1) unstable; urgency=medium + + * Revert to upstream version 0.0~git20190321.3fc05d4 now that Debian 10 + "buster" is released. See https://bugs.debian.org/928227 for background + information. + * Bump Standards-Version to 4.4.0 (no change) + + -- Anthony Fok Thu, 11 Jul 2019 23:35:15 -0600 + +golang-golang-x-image (0.0~git20190321.3fc05d4+really0.0~git20181116.cd38e80-1) unstable; urgency=medium + + * Revert all changes between 0.0~git20181116.cd38e80-1 + and 0.0~git20190321.3fc05d4-1, resulting in an absurd version number. + See https://bugs.debian.org/928227 for a rationale. + + -- Dr. Tobias Quathamer Sun, 02 Jun 2019 22:27:49 +0200 + golang-golang-x-image (0.0~git20190321.3fc05d4-1) unstable; urgency=medium * New upstream version 0.0~git20190321.3fc05d4 diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/debian/control golang-golang-x-image-0.0~git20190703.d6a02ce/debian/control --- golang-golang-x-image-0.0~git20190321.3fc05d4/debian/control 2019-04-14 09:50:05.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/debian/control 2019-07-28 03:36:27.000000000 +0000 @@ -9,7 +9,7 @@ dh-golang (>= 1.31~), golang-any, golang-golang-x-text-dev -Standards-Version: 4.3.0 +Standards-Version: 4.4.0 Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-golang-x-image Vcs-Git: https://salsa.debian.org/go-team/packages/golang-golang-x-image.git Homepage: https://golang.org/x/image/ diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/go.mod golang-golang-x-image-0.0~git20190703.d6a02ce/go.mod --- golang-golang-x-image-0.0~git20190321.3fc05d4/go.mod 2019-03-21 06:31:52.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/go.mod 2019-07-28 02:13:45.000000000 +0000 @@ -1,3 +1,5 @@ module golang.org/x/image +go 1.12 + require golang.org/x/text v0.3.0 Binary files /tmp/tmpPYcZLE/kwAVadWSES/golang-golang-x-image-0.0~git20190321.3fc05d4/testdata/bw-gopher_ccittGroup3.tiff and /tmp/tmpPYcZLE/f_Qwz2ceYJ/golang-golang-x-image-0.0~git20190703.d6a02ce/testdata/bw-gopher_ccittGroup3.tiff differ Binary files /tmp/tmpPYcZLE/kwAVadWSES/golang-golang-x-image-0.0~git20190321.3fc05d4/testdata/bw-gopher_ccittGroup4.tiff and /tmp/tmpPYcZLE/f_Qwz2ceYJ/golang-golang-x-image-0.0~git20190703.d6a02ce/testdata/bw-gopher_ccittGroup4.tiff differ Binary files /tmp/tmpPYcZLE/kwAVadWSES/golang-golang-x-image-0.0~git20190321.3fc05d4/testdata/bw-gopher.png and /tmp/tmpPYcZLE/f_Qwz2ceYJ/golang-golang-x-image-0.0~git20190703.d6a02ce/testdata/bw-gopher.png differ diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/tiff/consts.go golang-golang-x-image-0.0~git20190703.d6a02ce/tiff/consts.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/tiff/consts.go 2019-03-21 06:31:52.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/tiff/consts.go 2019-07-28 02:13:45.000000000 +0000 @@ -42,11 +42,16 @@ tCompression = 259 tPhotometricInterpretation = 262 + tFillOrder = 266 + tStripOffsets = 273 tSamplesPerPixel = 277 tRowsPerStrip = 278 tStripByteCounts = 279 + tT4Options = 292 // CCITT Group 3 options, a set of 32 flag bits. + tT6Options = 293 // CCITT Group 4 options, a set of 32 flag bits. + tTileWidth = 322 tTileLength = 323 tTileOffsets = 324 @@ -112,22 +117,33 @@ mRGB mRGBA mNRGBA + mCMYK ) // CompressionType describes the type of compression used in Options. type CompressionType int +// Constants for supported compression types. const ( Uncompressed CompressionType = iota Deflate + LZW + CCITTGroup3 + CCITTGroup4 ) // specValue returns the compression type constant from the TIFF spec that // is equivalent to c. func (c CompressionType) specValue() uint32 { switch c { + case LZW: + return cLZW case Deflate: return cDeflate + case CCITTGroup3: + return cG3 + case CCITTGroup4: + return cG4 } return cNone } diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/tiff/reader.go golang-golang-x-image-0.0~git20190703.d6a02ce/tiff/reader.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/tiff/reader.go 2019-03-21 06:31:52.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/tiff/reader.go 2019-07-28 02:13:45.000000000 +0000 @@ -17,6 +17,7 @@ "io/ioutil" "math" + "golang.org/x/image/ccitt" "golang.org/x/image/tiff/lzw" ) @@ -129,7 +130,10 @@ tTileOffsets, tTileByteCounts, tImageLength, - tImageWidth: + tImageWidth, + tFillOrder, + tT4Options, + tT6Options: val, err := d.ifdUint(p) if err != nil { return 0, err @@ -441,7 +445,8 @@ d.config.Height = int(d.firstVal(tImageLength)) if _, ok := d.features[tBitsPerSample]; !ok { - return nil, FormatError("BitsPerSample tag missing") + // Default is 1 per specification. + d.features[tBitsPerSample] = []uint{1} } d.bpp = d.firstVal(tBitsPerSample) switch d.bpp { @@ -539,6 +544,13 @@ return d.config, nil } +func ccittFillOrder(tiffFillOrder uint) ccitt.Order { + if tiffFillOrder == 2 { + return ccitt.LSB + } + return ccitt.MSB +} + // Decode reads a TIFF image from r and returns it as an image.Image. // The type of Image returned depends on the contents of the TIFF. func Decode(r io.Reader) (img image.Image, err error) { @@ -644,6 +656,16 @@ d.buf = make([]byte, n) _, err = d.r.ReadAt(d.buf, offset) } + case cG3: + inv := d.firstVal(tPhotometricInterpretation) == pWhiteIsZero + order := ccittFillOrder(d.firstVal(tFillOrder)) + r := ccitt.NewReader(io.NewSectionReader(d.r, offset, n), order, ccitt.Group3, blkW, blkH, &ccitt.Options{Invert: inv, Align: false}) + d.buf, err = ioutil.ReadAll(r) + case cG4: + inv := d.firstVal(tPhotometricInterpretation) == pWhiteIsZero + order := ccittFillOrder(d.firstVal(tFillOrder)) + r := ccitt.NewReader(io.NewSectionReader(d.r, offset, n), order, ccitt.Group4, blkW, blkH, &ccitt.Options{Invert: inv, Align: false}) + d.buf, err = ioutil.ReadAll(r) case cLZW: r := lzw.NewReader(io.NewSectionReader(d.r, offset, n), lzw.MSB, 8) d.buf, err = ioutil.ReadAll(r) diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/tiff/reader_test.go golang-golang-x-image-0.0~git20190703.d6a02ce/tiff/reader_test.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/tiff/reader_test.go 2019-03-21 06:31:52.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/tiff/reader_test.go 2019-07-28 02:13:45.000000000 +0000 @@ -127,6 +127,7 @@ } func compare(t *testing.T, img0, img1 image.Image) { + t.Helper() b0 := img0.Bounds() b1 := img1.Bounds() if b0.Dx() != b1.Dx() || b0.Dy() != b1.Dy() { @@ -192,6 +193,32 @@ compare(t, img0, img1) } +// TestDecodeCCITT tests that decoding a PNG image and a CCITT compressed TIFF +// image result in the same pixel data. +func TestDecodeCCITT(t *testing.T) { + // TODO Add more tests. + for _, fn := range []string{ + "bw-gopher", + } { + img0, err := load(fn + ".png") + if err != nil { + t.Fatal(err) + } + + img1, err := load(fn + "_ccittGroup3.tiff") + if err != nil { + t.Fatal(err) + } + compare(t, img0, img1) + + img2, err := load(fn + "_ccittGroup4.tiff") + if err != nil { + t.Fatal(err) + } + compare(t, img0, img2) + } +} + // TestDecodeTagOrder tests that a malformed image with unsorted IFD entries is // correctly rejected. func TestDecodeTagOrder(t *testing.T) { @@ -376,6 +403,7 @@ // benchmarkDecode benchmarks the decoding of an image. func benchmarkDecode(b *testing.B, filename string) { + b.Helper() b.StopTimer() contents, err := ioutil.ReadFile(testdataDir + filename) if err != nil { diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/tiff/writer_test.go golang-golang-x-image-0.0~git20190703.d6a02ce/tiff/writer_test.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/tiff/writer_test.go 2019-03-21 06:31:52.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/tiff/writer_test.go 2019-07-28 02:13:45.000000000 +0000 @@ -42,6 +42,7 @@ if err != nil { t.Fatal(err) } + out := new(bytes.Buffer) err = Encode(out, img, rt.opts) if err != nil { @@ -75,6 +76,7 @@ } func benchmarkEncode(b *testing.B, name string, pixelSize int) { + b.Helper() img, err := openImage(name) if err != nil { b.Fatal(err) diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/vector/acc_amd64.go golang-golang-x-image-0.0~git20190703.d6a02ce/vector/acc_amd64.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/vector/acc_amd64.go 2019-03-21 06:31:52.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/vector/acc_amd64.go 2019-07-28 02:13:45.000000000 +0000 @@ -10,9 +10,10 @@ func haveSSE4_1() bool -var haveFixedAccumulateSIMD = haveSSE4_1() - -const haveFloatingAccumulateSIMD = true +var ( + haveFixedAccumulateSIMD = haveSSE4_1() + haveFloatingAccumulateSIMD = haveSSE4_1() +) //go:noescape func fixedAccumulateOpOverSIMD(dst []uint8, src []uint32) diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/vector/acc_other.go golang-golang-x-image-0.0~git20190703.d6a02ce/vector/acc_other.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/vector/acc_other.go 2019-03-21 06:31:52.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/vector/acc_other.go 2019-07-28 02:13:45.000000000 +0000 @@ -6,8 +6,10 @@ package vector -const haveFixedAccumulateSIMD = false -const haveFloatingAccumulateSIMD = false +const ( + haveFixedAccumulateSIMD = false + haveFloatingAccumulateSIMD = false +) func fixedAccumulateOpOverSIMD(dst []uint8, src []uint32) {} func fixedAccumulateOpSrcSIMD(dst []uint8, src []uint32) {} diff -Nru golang-golang-x-image-0.0~git20190321.3fc05d4/vector/acc_test.go golang-golang-x-image-0.0~git20190703.d6a02ce/vector/acc_test.go --- golang-golang-x-image-0.0~git20190321.3fc05d4/vector/acc_test.go 2019-03-21 06:31:52.000000000 +0000 +++ golang-golang-x-image-0.0~git20190703.d6a02ce/vector/acc_test.go 2019-07-28 02:13:45.000000000 +0000 @@ -7,7 +7,9 @@ import ( "bytes" "fmt" + "math" "math/rand" + "runtime" "testing" ) @@ -235,7 +237,7 @@ t.Errorf("simd=%t, n=%d:\ngot: % x\nwant: % x", simd, n, got8, want8) } } else { - if !uint32sEqual(got32, want32) { + if !uint32sMatch(got32, want32) { t.Errorf("simd=%t, n=%d:\ngot: % x\nwant: % x", simd, n, got32, want32) } } @@ -243,25 +245,110 @@ } } -func uint32sEqual(xs, ys []uint32) bool { +// This package contains multiple implementations of the same algorithm, e.g. +// there are both SIMD and non-SIMD (vanilla) implementations on GOARCH=amd64. +// In general, the tests in this file check that the output is *exactly* the +// same, regardless of implementation. +// +// On GOARCH=wasm, float32 arithmetic is done with 64 bit precision. This is +// allowed by the Go specification: only explicit conversions to float32 have +// to round to 32 bit precision. However, the vanilla implementation therefore +// produces different output for GOARCH=wasm than on other GOARCHes. +// +// We therefore treat GOARCH=wasm as a special case, where the tests check that +// the output is only *approximately* the same (within a 0.1% tolerance). +// +// It's not that, on GOARCH=wasm, we produce the "wrong" answer. In fact, the +// computation is more, not less, accurate on GOARCH=wasm. It's that the golden +// output that the tests compare to were, for historical reasons, produced on +// GOARCH=amd64 and so done with less accuracy (where float32 arithmetic is +// performed entirely with 32 bits, not with 64 bits and then rounded back to +// 32 bits). Furthermore, on amd64, we still want to test that SIMD and +// non-SIMD produce exactly the same (albeit less accurate) output. The SIMD +// implementation in particular is limited by what the underlying hardware +// instructions provide, which often favors speed over accuracy. + +// approxEquals returns whether got is within 0.1% of want. +func approxEquals(got, want float64) bool { + const tolerance = 0.001 + return math.Abs(got-want) <= math.Abs(want)*tolerance +} + +// sixteen is used by TestFloat32ArithmeticWithinTolerance, below. It needs to +// be a package-level variable so that the compiler does not replace the +// calculation with a single constant. +var sixteen float32 = 16 + +// TestFloat32ArithmeticWithinTolerance checks that approxEquals' tolerance is +// sufficiently high so that the results of two separate ways of computing the +// arbitrary fraction 16 / 1122 are deemed "approximately equal" even if they +// aren't "exactly equal". +// +// We're not testing whether the computation on amd64 or wasm is "right" or +// "wrong". We're testing that we cope with them being different. +// +// On GOARCH=amd64, printing x and y gives: +// 0.0142602495543672 +// 0.014260249212384224 +// +// On GOARCH=wasm, printing x and y gives: +// 0.0142602495543672 +// 0.0142602495543672 +// +// The infinitely precise (mathematical) answer is: +// 0.014260249554367201426024955436720142602495543672recurring... +// See https://play.golang.org/p/RxzKSdD_suE +// +// This test establishes a lower bound on approxEquals' tolerance constant. +// Passing this one test (on all of the various supported GOARCH's) is a +// necessary but not a sufficient condition on that value. Other tests in this +// package that call uint32sMatch or float32sMatch (such as TestMakeFxInXxx, +// TestMakeFlInXxx or anything calling testAcc) also require a sufficiently +// large tolerance. But those tests are more complicated, and if there is a +// problem with the tolerance constant, debugging this test can be simpler. +func TestFloat32ArithmeticWithinTolerance(t *testing.T) { + x := float64(sixteen) / 1122 // Always use 64-bit division. + y := float64(sixteen / 1122) // Use 32- or 64-bit division (GOARCH dependent). + if !approxEquals(x, y) { + t.Errorf("x and y were not approximately equal:\nx = %v\ny = %v", x, y) + } +} + +func uint32sMatch(xs, ys []uint32) bool { if len(xs) != len(ys) { return false } - for i := range xs { - if xs[i] != ys[i] { - return false + if runtime.GOARCH == "wasm" { + for i := range xs { + if !approxEquals(float64(xs[i]), float64(ys[i])) { + return false + } + } + } else { + for i := range xs { + if xs[i] != ys[i] { + return false + } } } return true } -func float32sEqual(xs, ys []float32) bool { +func float32sMatch(xs, ys []float32) bool { if len(xs) != len(ys) { return false } - for i := range xs { - if xs[i] != ys[i] { - return false + if runtime.GOARCH == "wasm" { + for i := range xs { + if !approxEquals(float64(xs[i]), float64(ys[i])) { + return false + } + } + } else { + for i := range xs { + if xs[i] != ys[i] { + return false + } } } return true @@ -452,7 +539,7 @@ return b.String() } - if !uint32sEqual(fxIn16, hardCodedFxIn16) { + if !uint32sMatch(fxIn16, hardCodedFxIn16) { t.Errorf("height 16: got:%v\nwant:%v", dump(fxIn16), dump(hardCodedFxIn16)) } } @@ -469,7 +556,7 @@ return b.String() } - if !float32sEqual(flIn16, hardCodedFlIn16) { + if !float32sMatch(flIn16, hardCodedFlIn16) { t.Errorf("height 16: got:%v\nwant:%v", dump(flIn16), dump(hardCodedFlIn16)) } }