Skip to content

Commit 5743694

Browse files
committed
support CCITT fax 4 compression type
1 parent 4a6df05 commit 5743694

13 files changed

+1072
-15
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
examples/z_*

compress.go

+14-9
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@ import (
1010
"fmt"
1111
"io"
1212
"io/ioutil"
13+
14+
"github.com/chai2010/tiff/internal/fax"
1315
)
1416

15-
func (p TagValue_CompressionType) Decode(r io.Reader) (data []byte, err error) {
17+
func (p TagValue_CompressionType) Decode(r io.Reader, width, height int) (data []byte, err error) {
1618
switch p {
1719
case TagValue_CompressionType_None, TagValue_CompressionType_Nil:
1820
return p.decode_None(r)
1921
case TagValue_CompressionType_CCITT:
2022
return p.decode_CCITT(r)
2123
case TagValue_CompressionType_G3:
22-
return p.decode_G3(r)
24+
return p.decode_G3(r, width, height)
2325
case TagValue_CompressionType_G4:
24-
return p.decode_G4(r)
26+
return p.decode_G4(r, width, height)
2527
case TagValue_CompressionType_LZW:
2628
return p.decode_LZW(r)
2729
case TagValue_CompressionType_JPEGOld:
@@ -49,14 +51,17 @@ func (p TagValue_CompressionType) decode_CCITT(r io.Reader) (data []byte, err er
4951
return
5052
}
5153

52-
func (p TagValue_CompressionType) decode_G3(r io.Reader) (data []byte, err error) {
53-
err = fmt.Errorf("tiff: unsupport TagValue_CompressionType, %d", int(p))
54-
return
54+
func (p TagValue_CompressionType) decode_G3(r io.Reader, width, height int) (data []byte, err error) {
55+
return p.decode_G4(r, width, height)
5556
}
5657

57-
func (p TagValue_CompressionType) decode_G4(r io.Reader) (data []byte, err error) {
58-
err = fmt.Errorf("tiff: unsupport TagValue_CompressionType, %d", int(p))
59-
return
58+
func (p TagValue_CompressionType) decode_G4(r io.Reader, width, height int) (data []byte, err error) {
59+
br, ok := r.(io.ByteReader)
60+
if !ok {
61+
br = bufio.NewReader(r)
62+
}
63+
64+
return fax.DecodeG4Pixels(br, width, height)
6065
}
6166

6267
func (p TagValue_CompressionType) decode_LZW(r io.Reader) (data []byte, err error) {

decoder_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func TestUnpackBits(t *testing.T) {
5959
"\xaa\xaa\xaa\x80\x00\x2a\xaa\xaa\xaa\xaa\x80\x00\x2a\x22\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
6060
}}
6161
for _, u := range unpackBitsTests {
62-
buf, err := TagValue_CompressionType_PackBits.Decode(strings.NewReader(u.compressed))
62+
buf, err := TagValue_CompressionType_PackBits.Decode(strings.NewReader(u.compressed), 0, 0)
6363
if err != nil {
6464
t.Fatal(err)
6565
}

examples/tiffblock.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import (
1919

2020
var files = []string{
2121
"../testdata/video-001-tile-64x64.tiff",
22+
"../testdata/compress/compress_type_g4.tif",
23+
"../testdata/compress/red.tiff",
2224
}
2325

2426
func main() {
@@ -50,7 +52,7 @@ func main() {
5052

5153
for col := 0; col < blocksAcross; col++ {
5254
for row := 0; row < blocksDown; row++ {
53-
newname := fmt.Sprintf("%s-%02d-%02d-%02d-%02d.tiff", filepath.Base(name), i, j, col, row)
55+
newname := fmt.Sprintf("z_%s-%02d-%02d-%02d-%02d.tiff", filepath.Base(name), i, j, col, row)
5456

5557
m, err := p.DecodeImageBlock(i, j, col, row)
5658
if err != nil {
110 KB
Binary file not shown.

internal/fax/code_test.go

+234
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
package fax
2+
3+
// The code words from ITU-T Recommendation T.6 in base 2 notation.
4+
5+
const (
6+
terminatorCode = "000000000001000000000001" // EOFB
7+
passCode = "0001"
8+
horizontalCode = "001"
9+
)
10+
11+
var verticalCodes = map[int]string{
12+
0: "1",
13+
1: "011",
14+
2: "000011",
15+
3: "0000011",
16+
-1: "010",
17+
-2: "000010",
18+
-3: "0000010",
19+
}
20+
21+
// Table 2/T.6
22+
var whiteCodes = [...]string{
23+
"00110101",
24+
"000111",
25+
"0111",
26+
"1000",
27+
"1011",
28+
"1100",
29+
"1110",
30+
"1111",
31+
"10011",
32+
"10100",
33+
"00111",
34+
"01000",
35+
"001000",
36+
"000011",
37+
"110100",
38+
"110101",
39+
"101010",
40+
"101011",
41+
"0100111",
42+
"0001100",
43+
"0001000",
44+
"0010111",
45+
"0000011",
46+
"0000100",
47+
"0101000",
48+
"0101011",
49+
"0010011",
50+
"0100100",
51+
"0011000",
52+
"00000010",
53+
"00000011",
54+
"00011010",
55+
"00011011",
56+
"00010010",
57+
"00010011",
58+
"00010100",
59+
"00010101",
60+
"00010110",
61+
"00010111",
62+
"00101000",
63+
"00101001",
64+
"00101010",
65+
"00101011",
66+
"00101100",
67+
"00101101",
68+
"00000100",
69+
"00000101",
70+
"00001010",
71+
"00001011",
72+
"01010010",
73+
"01010011",
74+
"01010100",
75+
"01010101",
76+
"00100100",
77+
"00100101",
78+
"01011000",
79+
"01011001",
80+
"01011010",
81+
"01011011",
82+
"01001010",
83+
"01001011",
84+
"00110010",
85+
"00110011",
86+
"00110100",
87+
}
88+
89+
// Table 2/T.6
90+
var blackCodes = [...]string{
91+
"0000110111",
92+
"010",
93+
"11",
94+
"10",
95+
"011",
96+
"0011",
97+
"0010",
98+
"00011",
99+
"000101",
100+
"000100",
101+
"0000100",
102+
"0000101",
103+
"0000111",
104+
"00000100",
105+
"00000111",
106+
"000011000",
107+
"0000010111",
108+
"0000011000",
109+
"0000001000",
110+
"00001100111",
111+
"00001101000",
112+
"00001101100",
113+
"00000110111",
114+
"00000101000",
115+
"00000010111",
116+
"00000011000",
117+
"000011001010",
118+
"000011001011",
119+
"000011001100",
120+
"000011001101",
121+
"000001101000",
122+
"000001101001",
123+
"000001101010",
124+
"000001101011",
125+
"000011010010",
126+
"000011010011",
127+
"000011010100",
128+
"000011010101",
129+
"000011010110",
130+
"000011010111",
131+
"000001101100",
132+
"000001101101",
133+
"000011011010",
134+
"000011011011",
135+
"000001010100",
136+
"000001010101",
137+
"000001010110",
138+
"000001010111",
139+
"000001100100",
140+
"000001100101",
141+
"000001010010",
142+
"000001010011",
143+
"000000100100",
144+
"000000110111",
145+
"000000111000",
146+
"000000100111",
147+
"000000101000",
148+
"000001011000",
149+
"000001011001",
150+
"000000101011",
151+
"000000101100",
152+
"000001011010",
153+
"000001100110",
154+
"000001100111",
155+
}
156+
157+
// Table 3/T.6
158+
var whiteMakeUpCodes = [...]string{
159+
"11011",
160+
"10010",
161+
"010111",
162+
"0110111",
163+
"00110110",
164+
"00110111",
165+
"01100100",
166+
"01100101",
167+
"01101000",
168+
"01100111",
169+
"011001100",
170+
"011001101",
171+
"011010010",
172+
"011010011",
173+
"011010100",
174+
"011010101",
175+
"011010110",
176+
"011010111",
177+
"011011000",
178+
"011011001",
179+
"011011010",
180+
"011011011",
181+
"010011000",
182+
"010011001",
183+
"010011010",
184+
"011000",
185+
"010011011",
186+
}
187+
188+
// Table 3/T.6
189+
var blackMakeUpCodes = [...]string{
190+
"0000001111",
191+
"000011001000",
192+
"000011001001",
193+
"000001011011",
194+
"000000110011",
195+
"000000110100",
196+
"000000110101",
197+
"0000001101100",
198+
"0000001101101",
199+
"0000001001010",
200+
"0000001001011",
201+
"0000001001100",
202+
"0000001001101",
203+
"0000001110010",
204+
"0000001110011",
205+
"0000001110100",
206+
"0000001110101",
207+
"0000001110110",
208+
"0000001110111",
209+
"0000001010010",
210+
"0000001010011",
211+
"0000001010100",
212+
"0000001010101",
213+
"0000001011010",
214+
"0000001011011",
215+
"0000001100100",
216+
"0000001100101",
217+
}
218+
219+
// Table 3/T.6
220+
var sharedMakeUpCodes = [...]string{
221+
"00000001000",
222+
"00000001100",
223+
"00000001101",
224+
"000000010010",
225+
"000000010011",
226+
"000000010100",
227+
"000000010101",
228+
"000000010110",
229+
"000000010111",
230+
"000000011100",
231+
"000000011101",
232+
"000000011110",
233+
"000000011111",
234+
}

internal/fax/extension.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package fax
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
)
7+
8+
var uncompressedMode = errors.New("fax: uncompressed mode not supported")
9+
10+
func extension(d *decoder) error {
11+
extension := d.head >> 22
12+
extension &= 0x7
13+
handler := extensionTable[extension]
14+
if handler == nil {
15+
return fmt.Errorf("fax: unknown extension 0b%03b", extension)
16+
}
17+
if e := d.pop(10); e != nil {
18+
return e
19+
}
20+
return handler(d)
21+
}
22+
23+
var extensionTable = [8]func(d *decoder) error{
24+
nil,
25+
nil,
26+
nil,
27+
nil,
28+
nil,
29+
nil,
30+
nil,
31+
func(d *decoder) error {
32+
return uncompressedMode
33+
},
34+
}

0 commit comments

Comments
 (0)