ccitt: fix byte align and invert flag

Change-Id: I49955017deb8243b19dc1bb222ff8622ac3ff6af
Reviewed-on: https://go-review.googlesource.com/c/image/+/190677
Run-TryBot: Benny Siegert <bsiegert@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/ccitt/reader.go b/ccitt/reader.go
index 62986f9..680f8a6 100644
--- a/ccitt/reader.go
+++ b/ccitt/reader.go
@@ -269,6 +269,12 @@
 			}
 
 			byteValue := byte(0)
+			if z.invert {
+				// Set the end-of-row padding bits to 1 (if inverted) or 0. If inverted, the 1s
+				// are temporary, and will be flipped back to 0s by the invertBytes call below.
+				byteValue = 0xFF >> uint(numToPack)
+			}
+
 			for j := 0; j < numToPack; j++ {
 				byteValue |= (z.curr[z.ri] & 0x80) >> uint(j)
 				z.ri++
@@ -285,7 +291,6 @@
 	}
 
 	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])
 	}
@@ -369,6 +374,10 @@
 	z.atStartOfRow = true
 	z.penColorIsWhite = true
 
+	if z.align {
+		z.br.alignToByteBoundary()
+	}
+
 	switch z.subFormat {
 	case Group3:
 		for ; z.wi < len(z.curr); z.atStartOfRow = false {
@@ -379,10 +388,6 @@
 		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 {
diff --git a/ccitt/reader_test.go b/ccitt/reader_test.go
index c582f16..0224618 100644
--- a/ccitt/reader_test.go
+++ b/ccitt/reader_test.go
@@ -14,6 +14,7 @@
 	"os"
 	"path/filepath"
 	"reflect"
+	"strings"
 	"testing"
 	"unsafe"
 )
@@ -198,25 +199,23 @@
 	}
 }
 
-func TestReadRegular(t *testing.T) { testRead(t, false) }
-func TestReadInvert(t *testing.T)  { testRead(t, true) }
-
-func testRead(t *testing.T, invert bool) {
+func testRead(t *testing.T, fileName string, sf SubFormat, align, invert bool) {
 	t.Helper()
 
 	const width, height = 153, 55
 	opts := &Options{
+		Align:  align,
 		Invert: invert,
 	}
 
 	got := ""
 	{
-		f, err := os.Open("testdata/bw-gopher.ccitt_group3")
+		f, err := os.Open(fileName)
 		if err != nil {
 			t.Fatalf("Open: %v", err)
 		}
 		defer f.Close()
-		gotBytes, err := ioutil.ReadAll(NewReader(f, MSB, Group3, width, height, opts))
+		gotBytes, err := ioutil.ReadAll(NewReader(f, MSB, sf, width, height, opts))
 		if err != nil {
 			t.Fatalf("ReadAll: %v", err)
 		}
@@ -261,9 +260,6 @@
 				}
 			}
 		}
-		if invert {
-			invertBytes(wantBytes)
-		}
 		want = string(wantBytes)
 	}
 
@@ -292,6 +288,27 @@
 	}
 }
 
+func TestRead(t *testing.T) {
+	for _, fileName := range []string{
+		"testdata/bw-gopher.ccitt_group3",
+		"testdata/bw-gopher-aligned.ccitt_group3",
+		"testdata/bw-gopher-inverted.ccitt_group3",
+		"testdata/bw-gopher-inverted-aligned.ccitt_group3",
+		"testdata/bw-gopher.ccitt_group4",
+		"testdata/bw-gopher-aligned.ccitt_group4",
+		"testdata/bw-gopher-inverted.ccitt_group4",
+		"testdata/bw-gopher-inverted-aligned.ccitt_group4",
+	} {
+		subFormat := Group3
+		if strings.HasSuffix(fileName, "group4") {
+			subFormat = Group4
+		}
+		align := strings.Contains(fileName, "aligned")
+		invert := strings.Contains(fileName, "inverted")
+		testRead(t, fileName, subFormat, align, invert)
+	}
+}
+
 func TestDecodeIntoGray(t *testing.T) {
 	for _, tt := range []struct {
 		fileName string
diff --git a/ccitt/testdata/bw-gopher-aligned.ccitt_group3 b/ccitt/testdata/bw-gopher-aligned.ccitt_group3
new file mode 100644
index 0000000..cba6634
--- /dev/null
+++ b/ccitt/testdata/bw-gopher-aligned.ccitt_group3
Binary files differ
diff --git a/ccitt/testdata/bw-gopher-aligned.ccitt_group4 b/ccitt/testdata/bw-gopher-aligned.ccitt_group4
new file mode 100644
index 0000000..8ff8653
--- /dev/null
+++ b/ccitt/testdata/bw-gopher-aligned.ccitt_group4
Binary files differ
diff --git a/ccitt/testdata/bw-gopher-inverted-aligned.ccitt_group3 b/ccitt/testdata/bw-gopher-inverted-aligned.ccitt_group3
new file mode 100644
index 0000000..0c9c55a
--- /dev/null
+++ b/ccitt/testdata/bw-gopher-inverted-aligned.ccitt_group3
Binary files differ
diff --git a/ccitt/testdata/bw-gopher-inverted-aligned.ccitt_group4 b/ccitt/testdata/bw-gopher-inverted-aligned.ccitt_group4
new file mode 100644
index 0000000..263aafd
--- /dev/null
+++ b/ccitt/testdata/bw-gopher-inverted-aligned.ccitt_group4
Binary files differ
diff --git a/ccitt/testdata/bw-gopher-inverted.ccitt_group3 b/ccitt/testdata/bw-gopher-inverted.ccitt_group3
new file mode 100644
index 0000000..753bd09
--- /dev/null
+++ b/ccitt/testdata/bw-gopher-inverted.ccitt_group3
Binary files differ
diff --git a/ccitt/testdata/bw-gopher-inverted.ccitt_group4 b/ccitt/testdata/bw-gopher-inverted.ccitt_group4
new file mode 100644
index 0000000..a4b062a
--- /dev/null
+++ b/ccitt/testdata/bw-gopher-inverted.ccitt_group4
Binary files differ