-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdecoder.go
145 lines (129 loc) · 3.39 KB
/
decoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package tiff
import (
"compress/zlib"
"fmt"
"image"
"io"
"io/ioutil"
"github.com/mdouchement/hdr/hdrcolor"
"golang.org/x/image/tiff/lzw"
)
// Debug activates debug prints on stdout.
var Debug = false
type decoder struct {
*idf
config image.Config
mode imageMode
bpp uint
// decode decodes the raw data of an image.
// It reads from d.buf and writes the strip or tile into dst.
decode func(dst image.Image, xmin, ymin, xmax, ymax int) error
buf []byte
off int // Current offset in buf.
v uint32 // Buffer value for reading with arbitrary bit depths.
nbits uint // Remaining number of bits in v.
}
func newDecoder(r io.Reader) (*decoder, error) {
idf, err := newIDF(newReaderAt(r))
if err != nil {
return nil, err
}
if Debug {
fmt.Println(idf)
}
d := &decoder{
idf: idf,
}
d.config.Width = int(d.firstVal(tImageWidth))
d.config.Height = int(d.firstVal(tImageLength))
if _, ok := d.features[tBitsPerSample]; !ok {
return nil, FormatError("BitsPerSample tag missing")
}
d.bpp = d.firstVal(tBitsPerSample)
// Determine the image mode.
switch d.firstVal(tPhotometricInterpretation) {
case pWhiteIsZero:
fallthrough
case pBlackIsZero:
fallthrough
case pPaletted:
fallthrough
case pTransMask:
fallthrough
case pCMYK:
// All LDR modes are droped.
return nil, UnsupportedError("color model, use Golang's lib for LDR images")
case pRGB:
d.mode = mRGB
d.decode = d.decodeRGB
d.config.ColorModel = hdrcolor.RGBModel
case pLogL:
d.mode = mLogL
d.decode = d.decodeLogL
d.config.ColorModel = hdrcolor.XYZModel
case pLogLuv:
d.mode = mLogLuv
d.decode = d.decodeLogLuv
d.config.ColorModel = hdrcolor.XYZModel
case pColorFilterArray:
d.mode = mColorFilterArray
d.decode = d.decodeColorFilterArray
d.config.ColorModel = hdrcolor.XYZModel
default:
return nil, UnsupportedError("color model")
}
return d, nil
}
// readBits reads n bits from the internal buffer starting at the current offset.
func (d *decoder) readBits(n uint) uint32 {
for d.nbits < n {
d.v <<= 8
d.v |= uint32(d.buf[d.off])
d.off++
d.nbits += 8
}
d.nbits -= n
rv := d.v >> d.nbits
d.v &^= rv << d.nbits
return rv
}
// flushBits discards the unread bits in the buffer used by readBits.
// It is used at the end of a line.
func (d *decoder) flushBits() {
d.v = 0
d.nbits = 0
}
// decompress decompress a Strip.
func (d *decoder) decompress(offset, n int64, blockWidth, blockHeight int) (err error) {
switch d.firstVal(tCompression) {
// According to the spec, Compression does not have a default value,
// but some tools interpret a missing Compression value as none so we do
// the same.
case cNone, 0:
if b, ok := d.r.(*buffer); ok {
d.buf, err = b.Slice(int(offset), int(n))
} else {
d.buf = make([]byte, n)
_, err = d.r.ReadAt(d.buf, offset)
}
case cLZW:
r := lzw.NewReader(io.NewSectionReader(d.r, offset, n), lzw.MSB, 8)
d.buf, err = ioutil.ReadAll(r)
r.Close()
case cDeflate, cDeflateOld:
var r io.ReadCloser
r, err = zlib.NewReader(io.NewSectionReader(d.r, offset, n))
if err != nil {
return
}
d.buf, err = ioutil.ReadAll(r)
r.Close()
case cPackBits:
d.buf, err = unpackBits(io.NewSectionReader(d.r, offset, n))
case cSGILogRLE:
d.buf, err = unRLE(io.NewSectionReader(d.r, offset, n), d.mode, blockWidth, blockHeight)
default:
err = UnsupportedError(fmt.Sprintf("compression value %d", d.firstVal(tCompression)))
}
return
}