Source file src/pkg/image/jpeg/reader.go
1
2
3
4
5
6
7
8 package jpeg
9
10 import (
11 "bufio"
12 "image"
13 "image/color"
14 "io"
15 )
16
17
18
19
20
21 type FormatError string
22
23 func (e FormatError) Error() string { return "invalid JPEG format: " + string(e) }
24
25
26 type UnsupportedError string
27
28 func (e UnsupportedError) Error() string { return "unsupported JPEG feature: " + string(e) }
29
30
31 type component struct {
32 h int
33 v int
34 c uint8
35 tq uint8
36 }
37
38 const (
39 dcTable = 0
40 acTable = 1
41 maxTc = 1
42 maxTh = 3
43 maxTq = 3
44
45
46 nGrayComponent = 1
47
48 nColorComponent = 3
49
50
51
52
53 maxH = 2
54 maxV = 2
55 )
56
57 const (
58 soiMarker = 0xd8
59 eoiMarker = 0xd9
60 sof0Marker = 0xc0
61 sof2Marker = 0xc2
62 dhtMarker = 0xc4
63 dqtMarker = 0xdb
64 sosMarker = 0xda
65 driMarker = 0xdd
66 rst0Marker = 0xd0
67 rst7Marker = 0xd7
68 app0Marker = 0xe0
69 app15Marker = 0xef
70 comMarker = 0xfe
71 )
72
73
74
75
76 var unzig = [blockSize]int{
77 0, 1, 8, 16, 9, 2, 3, 10,
78 17, 24, 32, 25, 18, 11, 4, 5,
79 12, 19, 26, 33, 40, 48, 41, 34,
80 27, 20, 13, 6, 7, 14, 21, 28,
81 35, 42, 49, 56, 57, 50, 43, 36,
82 29, 22, 15, 23, 30, 37, 44, 51,
83 58, 59, 52, 45, 38, 31, 39, 46,
84 53, 60, 61, 54, 47, 55, 62, 63,
85 }
86
87
88 type Reader interface {
89 io.Reader
90 ReadByte() (c byte, err error)
91 }
92
93 type decoder struct {
94 r Reader
95 b bits
96 width, height int
97 img1 *image.Gray
98 img3 *image.YCbCr
99 ri int
100 nComp int
101 progressive bool
102 eobRun uint16
103 comp [nColorComponent]component
104 progCoeffs [nColorComponent][]block
105 huff [maxTc + 1][maxTh + 1]huffman
106 quant [maxTq + 1]block
107 tmp [1024]byte
108 }
109
110
111 func (d *decoder) ignore(n int) error {
112 for n > 0 {
113 m := len(d.tmp)
114 if m > n {
115 m = n
116 }
117 _, err := io.ReadFull(d.r, d.tmp[0:m])
118 if err != nil {
119 return err
120 }
121 n -= m
122 }
123 return nil
124 }
125
126
127 func (d *decoder) processSOF(n int) error {
128 switch n {
129 case 6 + 3*nGrayComponent:
130 d.nComp = nGrayComponent
131 case 6 + 3*nColorComponent:
132 d.nComp = nColorComponent
133 default:
134 return UnsupportedError("SOF has wrong length")
135 }
136 _, err := io.ReadFull(d.r, d.tmp[:n])
137 if err != nil {
138 return err
139 }
140
141 if d.tmp[0] != 8 {
142 return UnsupportedError("precision")
143 }
144 d.height = int(d.tmp[1])<<8 + int(d.tmp[2])
145 d.width = int(d.tmp[3])<<8 + int(d.tmp[4])
146 if int(d.tmp[5]) != d.nComp {
147 return UnsupportedError("SOF has wrong number of image components")
148 }
149 for i := 0; i < d.nComp; i++ {
150 d.comp[i].c = d.tmp[6+3*i]
151 d.comp[i].tq = d.tmp[8+3*i]
152 if d.nComp == nGrayComponent {
153
154
155
156
157
158
159
160
161
162
163
164 d.comp[i].h = 1
165 d.comp[i].v = 1
166 continue
167 }
168 hv := d.tmp[7+3*i]
169 d.comp[i].h = int(hv >> 4)
170 d.comp[i].v = int(hv & 0x0f)
171
172
173
174
175 if i == 0 {
176 if hv != 0x11 && hv != 0x21 && hv != 0x22 && hv != 0x12 {
177 return UnsupportedError("luma downsample ratio")
178 }
179 } else if hv != 0x11 {
180 return UnsupportedError("chroma downsample ratio")
181 }
182 }
183 return nil
184 }
185
186
187 func (d *decoder) processDQT(n int) error {
188 const qtLength = 1 + blockSize
189 for ; n >= qtLength; n -= qtLength {
190 _, err := io.ReadFull(d.r, d.tmp[0:qtLength])
191 if err != nil {
192 return err
193 }
194 pq := d.tmp[0] >> 4
195 if pq != 0 {
196 return UnsupportedError("bad Pq value")
197 }
198 tq := d.tmp[0] & 0x0f
199 if tq > maxTq {
200 return FormatError("bad Tq value")
201 }
202 for i := range d.quant[tq] {
203 d.quant[tq][i] = int32(d.tmp[i+1])
204 }
205 }
206 if n != 0 {
207 return FormatError("DQT has wrong length")
208 }
209 return nil
210 }
211
212
213 func (d *decoder) processDRI(n int) error {
214 if n != 2 {
215 return FormatError("DRI has wrong length")
216 }
217 _, err := io.ReadFull(d.r, d.tmp[0:2])
218 if err != nil {
219 return err
220 }
221 d.ri = int(d.tmp[0])<<8 + int(d.tmp[1])
222 return nil
223 }
224
225
226 func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
227 if rr, ok := r.(Reader); ok {
228 d.r = rr
229 } else {
230 d.r = bufio.NewReader(r)
231 }
232
233
234 _, err := io.ReadFull(d.r, d.tmp[0:2])
235 if err != nil {
236 return nil, err
237 }
238 if d.tmp[0] != 0xff || d.tmp[1] != soiMarker {
239 return nil, FormatError("missing SOI marker")
240 }
241
242
243 for {
244 _, err := io.ReadFull(d.r, d.tmp[0:2])
245 if err != nil {
246 return nil, err
247 }
248 for d.tmp[0] != 0xff {
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 d.tmp[0] = d.tmp[1]
270 d.tmp[1], err = d.r.ReadByte()
271 if err != nil {
272 return nil, err
273 }
274 }
275 marker := d.tmp[1]
276 if marker == 0 {
277
278 continue
279 }
280 for marker == 0xff {
281
282
283 marker, err = d.r.ReadByte()
284 if err != nil {
285 return nil, err
286 }
287 }
288 if marker == eoiMarker {
289 break
290 }
291 if rst0Marker <= marker && marker <= rst7Marker {
292
293
294
295
296
297
298 continue
299 }
300
301
302
303 _, err = io.ReadFull(d.r, d.tmp[0:2])
304 if err != nil {
305 return nil, err
306 }
307 n := int(d.tmp[0])<<8 + int(d.tmp[1]) - 2
308 if n < 0 {
309 return nil, FormatError("short segment length")
310 }
311
312 switch {
313 case marker == sof0Marker || marker == sof2Marker:
314 d.progressive = marker == sof2Marker
315 err = d.processSOF(n)
316 if configOnly {
317 return nil, err
318 }
319 case marker == dhtMarker:
320 err = d.processDHT(n)
321 case marker == dqtMarker:
322 err = d.processDQT(n)
323 case marker == sosMarker:
324 err = d.processSOS(n)
325 case marker == driMarker:
326 err = d.processDRI(n)
327 case app0Marker <= marker && marker <= app15Marker || marker == comMarker:
328 err = d.ignore(n)
329 default:
330 err = UnsupportedError("unknown marker")
331 }
332 if err != nil {
333 return nil, err
334 }
335 }
336 if d.img1 != nil {
337 return d.img1, nil
338 }
339 if d.img3 != nil {
340 return d.img3, nil
341 }
342 return nil, FormatError("missing SOS marker")
343 }
344
345
346 func Decode(r io.Reader) (image.Image, error) {
347 var d decoder
348 return d.decode(r, false)
349 }
350
351
352
353 func DecodeConfig(r io.Reader) (image.Config, error) {
354 var d decoder
355 if _, err := d.decode(r, true); err != nil {
356 return image.Config{}, err
357 }
358 switch d.nComp {
359 case nGrayComponent:
360 return image.Config{
361 ColorModel: color.GrayModel,
362 Width: d.width,
363 Height: d.height,
364 }, nil
365 case nColorComponent:
366 return image.Config{
367 ColorModel: color.YCbCrModel,
368 Width: d.width,
369 Height: d.height,
370 }, nil
371 }
372 return image.Config{}, FormatError("missing SOF marker")
373 }
374
375 func init() {
376 image.RegisterFormat("jpeg", "\xff\xd8", Decode, DecodeConfig)
377 }
View as plain text