OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [image/] [png/] [reader.go] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
// Package png implements a PNG image decoder and encoder.
6
//
7
// The PNG specification is at http://www.w3.org/TR/PNG/.
8
package png
9
 
10
import (
11
        "compress/zlib"
12
        "encoding/binary"
13
        "fmt"
14
        "hash"
15
        "hash/crc32"
16
        "image"
17
        "image/color"
18
        "io"
19
)
20
 
21
// Color type, as per the PNG spec.
22
const (
23
        ctGrayscale      = 0
24
        ctTrueColor      = 2
25
        ctPaletted       = 3
26
        ctGrayscaleAlpha = 4
27
        ctTrueColorAlpha = 6
28
)
29
 
30
// A cb is a combination of color type and bit depth.
31
const (
32
        cbInvalid = iota
33
        cbG1
34
        cbG2
35
        cbG4
36
        cbG8
37
        cbGA8
38
        cbTC8
39
        cbP1
40
        cbP2
41
        cbP4
42
        cbP8
43
        cbTCA8
44
        cbG16
45
        cbGA16
46
        cbTC16
47
        cbTCA16
48
)
49
 
50
// Filter type, as per the PNG spec.
51
const (
52
        ftNone    = 0
53
        ftSub     = 1
54
        ftUp      = 2
55
        ftAverage = 3
56
        ftPaeth   = 4
57
        nFilter   = 5
58
)
59
 
60
// Decoding stage.
61
// The PNG specification says that the IHDR, PLTE (if present), IDAT and IEND
62
// chunks must appear in that order. There may be multiple IDAT chunks, and
63
// IDAT chunks must be sequential (i.e. they may not have any other chunks
64
// between them).
65
// http://www.w3.org/TR/PNG/#5ChunkOrdering
66
const (
67
        dsStart = iota
68
        dsSeenIHDR
69
        dsSeenPLTE
70
        dsSeenIDAT
71
        dsSeenIEND
72
)
73
 
74
const pngHeader = "\x89PNG\r\n\x1a\n"
75
 
76
type decoder struct {
77
        r             io.Reader
78
        img           image.Image
79
        crc           hash.Hash32
80
        width, height int
81
        depth         int
82
        palette       color.Palette
83
        cb            int
84
        stage         int
85
        idatLength    uint32
86
        tmp           [3 * 256]byte
87
}
88
 
89
// A FormatError reports that the input is not a valid PNG.
90
type FormatError string
91
 
92
func (e FormatError) Error() string { return "png: invalid format: " + string(e) }
93
 
94
var chunkOrderError = FormatError("chunk out of order")
95
 
96
// An UnsupportedError reports that the input uses a valid but unimplemented PNG feature.
97
type UnsupportedError string
98
 
99
func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) }
100
 
101
func abs(x int) int {
102
        if x < 0 {
103
                return -x
104
        }
105
        return x
106
}
107
 
108
func min(a, b int) int {
109
        if a < b {
110
                return a
111
        }
112
        return b
113
}
114
 
115
func (d *decoder) parseIHDR(length uint32) error {
116
        if length != 13 {
117
                return FormatError("bad IHDR length")
118
        }
119
        if _, err := io.ReadFull(d.r, d.tmp[:13]); err != nil {
120
                return err
121
        }
122
        d.crc.Write(d.tmp[:13])
123
        if d.tmp[10] != 0 || d.tmp[11] != 0 || d.tmp[12] != 0 {
124
                return UnsupportedError("compression, filter or interlace method")
125
        }
126
        w := int32(binary.BigEndian.Uint32(d.tmp[0:4]))
127
        h := int32(binary.BigEndian.Uint32(d.tmp[4:8]))
128
        if w < 0 || h < 0 {
129
                return FormatError("negative dimension")
130
        }
131
        nPixels := int64(w) * int64(h)
132
        if nPixels != int64(int(nPixels)) {
133
                return UnsupportedError("dimension overflow")
134
        }
135
        d.cb = cbInvalid
136
        d.depth = int(d.tmp[8])
137
        switch d.depth {
138
        case 1:
139
                switch d.tmp[9] {
140
                case ctGrayscale:
141
                        d.cb = cbG1
142
                case ctPaletted:
143
                        d.cb = cbP1
144
                }
145
        case 2:
146
                switch d.tmp[9] {
147
                case ctGrayscale:
148
                        d.cb = cbG2
149
                case ctPaletted:
150
                        d.cb = cbP2
151
                }
152
        case 4:
153
                switch d.tmp[9] {
154
                case ctGrayscale:
155
                        d.cb = cbG4
156
                case ctPaletted:
157
                        d.cb = cbP4
158
                }
159
        case 8:
160
                switch d.tmp[9] {
161
                case ctGrayscale:
162
                        d.cb = cbG8
163
                case ctTrueColor:
164
                        d.cb = cbTC8
165
                case ctPaletted:
166
                        d.cb = cbP8
167
                case ctGrayscaleAlpha:
168
                        d.cb = cbGA8
169
                case ctTrueColorAlpha:
170
                        d.cb = cbTCA8
171
                }
172
        case 16:
173
                switch d.tmp[9] {
174
                case ctGrayscale:
175
                        d.cb = cbG16
176
                case ctTrueColor:
177
                        d.cb = cbTC16
178
                case ctGrayscaleAlpha:
179
                        d.cb = cbGA16
180
                case ctTrueColorAlpha:
181
                        d.cb = cbTCA16
182
                }
183
        }
184
        if d.cb == cbInvalid {
185
                return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9]))
186
        }
187
        d.width, d.height = int(w), int(h)
188
        return d.verifyChecksum()
189
}
190
 
191
func (d *decoder) parsePLTE(length uint32) error {
192
        np := int(length / 3) // The number of palette entries.
193
        if length%3 != 0 || np <= 0 || np > 256 || np > 1<
194
                return FormatError("bad PLTE length")
195
        }
196
        n, err := io.ReadFull(d.r, d.tmp[:3*np])
197
        if err != nil {
198
                return err
199
        }
200
        d.crc.Write(d.tmp[:n])
201
        switch d.cb {
202
        case cbP1, cbP2, cbP4, cbP8:
203
                d.palette = color.Palette(make([]color.Color, np))
204
                for i := 0; i < np; i++ {
205
                        d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
206
                }
207
        case cbTC8, cbTCA8, cbTC16, cbTCA16:
208
                // As per the PNG spec, a PLTE chunk is optional (and for practical purposes,
209
                // ignorable) for the ctTrueColor and ctTrueColorAlpha color types (section 4.1.2).
210
        default:
211
                return FormatError("PLTE, color type mismatch")
212
        }
213
        return d.verifyChecksum()
214
}
215
 
216
func (d *decoder) parsetRNS(length uint32) error {
217
        if length > 256 {
218
                return FormatError("bad tRNS length")
219
        }
220
        n, err := io.ReadFull(d.r, d.tmp[:length])
221
        if err != nil {
222
                return err
223
        }
224
        d.crc.Write(d.tmp[:n])
225
        switch d.cb {
226
        case cbG8, cbG16:
227
                return UnsupportedError("grayscale transparency")
228
        case cbTC8, cbTC16:
229
                return UnsupportedError("truecolor transparency")
230
        case cbP1, cbP2, cbP4, cbP8:
231
                if n > len(d.palette) {
232
                        return FormatError("bad tRNS length")
233
                }
234
                for i := 0; i < n; i++ {
235
                        rgba := d.palette[i].(color.RGBA)
236
                        d.palette[i] = color.RGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
237
                }
238
        case cbGA8, cbGA16, cbTCA8, cbTCA16:
239
                return FormatError("tRNS, color type mismatch")
240
        }
241
        return d.verifyChecksum()
242
}
243
 
244
// The Paeth filter function, as per the PNG specification.
245
func paeth(a, b, c uint8) uint8 {
246
        p := int(a) + int(b) - int(c)
247
        pa := abs(p - int(a))
248
        pb := abs(p - int(b))
249
        pc := abs(p - int(c))
250
        if pa <= pb && pa <= pc {
251
                return a
252
        } else if pb <= pc {
253
                return b
254
        }
255
        return c
256
}
257
 
258
// Read presents one or more IDAT chunks as one continuous stream (minus the
259
// intermediate chunk headers and footers). If the PNG data looked like:
260
//   ... len0 IDAT xxx crc0 len1 IDAT yy crc1 len2 IEND crc2
261
// then this reader presents xxxyy. For well-formed PNG data, the decoder state
262
// immediately before the first Read call is that d.r is positioned between the
263
// first IDAT and xxx, and the decoder state immediately after the last Read
264
// call is that d.r is positioned between yy and crc1.
265
func (d *decoder) Read(p []byte) (int, error) {
266
        if len(p) == 0 {
267
                return 0, nil
268
        }
269
        for d.idatLength == 0 {
270
                // We have exhausted an IDAT chunk. Verify the checksum of that chunk.
271
                if err := d.verifyChecksum(); err != nil {
272
                        return 0, err
273
                }
274
                // Read the length and chunk type of the next chunk, and check that
275
                // it is an IDAT chunk.
276
                if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil {
277
                        return 0, err
278
                }
279
                d.idatLength = binary.BigEndian.Uint32(d.tmp[:4])
280
                if string(d.tmp[4:8]) != "IDAT" {
281
                        return 0, FormatError("not enough pixel data")
282
                }
283
                d.crc.Reset()
284
                d.crc.Write(d.tmp[4:8])
285
        }
286
        if int(d.idatLength) < 0 {
287
                return 0, UnsupportedError("IDAT chunk length overflow")
288
        }
289
        n, err := d.r.Read(p[:min(len(p), int(d.idatLength))])
290
        d.crc.Write(p[:n])
291
        d.idatLength -= uint32(n)
292
        return n, err
293
}
294
 
295
// decode decodes the IDAT data into an image.
296
func (d *decoder) decode() (image.Image, error) {
297
        r, err := zlib.NewReader(d)
298
        if err != nil {
299
                return nil, err
300
        }
301
        defer r.Close()
302
        bitsPerPixel := 0
303
        maxPalette := uint8(0)
304
        var (
305
                gray     *image.Gray
306
                rgba     *image.RGBA
307
                paletted *image.Paletted
308
                nrgba    *image.NRGBA
309
                gray16   *image.Gray16
310
                rgba64   *image.RGBA64
311
                nrgba64  *image.NRGBA64
312
                img      image.Image
313
        )
314
        switch d.cb {
315
        case cbG1, cbG2, cbG4, cbG8:
316
                bitsPerPixel = d.depth
317
                gray = image.NewGray(image.Rect(0, 0, d.width, d.height))
318
                img = gray
319
        case cbGA8:
320
                bitsPerPixel = 16
321
                nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
322
                img = nrgba
323
        case cbTC8:
324
                bitsPerPixel = 24
325
                rgba = image.NewRGBA(image.Rect(0, 0, d.width, d.height))
326
                img = rgba
327
        case cbP1, cbP2, cbP4, cbP8:
328
                bitsPerPixel = d.depth
329
                paletted = image.NewPaletted(image.Rect(0, 0, d.width, d.height), d.palette)
330
                img = paletted
331
                maxPalette = uint8(len(d.palette) - 1)
332
        case cbTCA8:
333
                bitsPerPixel = 32
334
                nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
335
                img = nrgba
336
        case cbG16:
337
                bitsPerPixel = 16
338
                gray16 = image.NewGray16(image.Rect(0, 0, d.width, d.height))
339
                img = gray16
340
        case cbGA16:
341
                bitsPerPixel = 32
342
                nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
343
                img = nrgba64
344
        case cbTC16:
345
                bitsPerPixel = 48
346
                rgba64 = image.NewRGBA64(image.Rect(0, 0, d.width, d.height))
347
                img = rgba64
348
        case cbTCA16:
349
                bitsPerPixel = 64
350
                nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
351
                img = nrgba64
352
        }
353
        bytesPerPixel := (bitsPerPixel + 7) / 8
354
 
355
        // cr and pr are the bytes for the current and previous row.
356
        // The +1 is for the per-row filter type, which is at cr[0].
357
        cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
358
        pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
359
 
360
        for y := 0; y < d.height; y++ {
361
                // Read the decompressed bytes.
362
                _, err := io.ReadFull(r, cr)
363
                if err != nil {
364
                        return nil, err
365
                }
366
 
367
                // Apply the filter.
368
                cdat := cr[1:]
369
                pdat := pr[1:]
370
                switch cr[0] {
371
                case ftNone:
372
                        // No-op.
373
                case ftSub:
374
                        for i := bytesPerPixel; i < len(cdat); i++ {
375
                                cdat[i] += cdat[i-bytesPerPixel]
376
                        }
377
                case ftUp:
378
                        for i := 0; i < len(cdat); i++ {
379
                                cdat[i] += pdat[i]
380
                        }
381
                case ftAverage:
382
                        for i := 0; i < bytesPerPixel; i++ {
383
                                cdat[i] += pdat[i] / 2
384
                        }
385
                        for i := bytesPerPixel; i < len(cdat); i++ {
386
                                cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
387
                        }
388
                case ftPaeth:
389
                        for i := 0; i < bytesPerPixel; i++ {
390
                                cdat[i] += paeth(0, pdat[i], 0)
391
                        }
392
                        for i := bytesPerPixel; i < len(cdat); i++ {
393
                                cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel])
394
                        }
395
                default:
396
                        return nil, FormatError("bad filter type")
397
                }
398
 
399
                // Convert from bytes to colors.
400
                switch d.cb {
401
                case cbG1:
402
                        for x := 0; x < d.width; x += 8 {
403
                                b := cdat[x/8]
404
                                for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
405
                                        gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
406
                                        b <<= 1
407
                                }
408
                        }
409
                case cbG2:
410
                        for x := 0; x < d.width; x += 4 {
411
                                b := cdat[x/4]
412
                                for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
413
                                        gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
414
                                        b <<= 2
415
                                }
416
                        }
417
                case cbG4:
418
                        for x := 0; x < d.width; x += 2 {
419
                                b := cdat[x/2]
420
                                for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
421
                                        gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
422
                                        b <<= 4
423
                                }
424
                        }
425
                case cbG8:
426
                        for x := 0; x < d.width; x++ {
427
                                gray.SetGray(x, y, color.Gray{cdat[x]})
428
                        }
429
                case cbGA8:
430
                        for x := 0; x < d.width; x++ {
431
                                ycol := cdat[2*x+0]
432
                                nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
433
                        }
434
                case cbTC8:
435
                        for x := 0; x < d.width; x++ {
436
                                rgba.SetRGBA(x, y, color.RGBA{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
437
                        }
438
                case cbP1:
439
                        for x := 0; x < d.width; x += 8 {
440
                                b := cdat[x/8]
441
                                for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
442
                                        idx := b >> 7
443
                                        if idx > maxPalette {
444
                                                return nil, FormatError("palette index out of range")
445
                                        }
446
                                        paletted.SetColorIndex(x+x2, y, idx)
447
                                        b <<= 1
448
                                }
449
                        }
450
                case cbP2:
451
                        for x := 0; x < d.width; x += 4 {
452
                                b := cdat[x/4]
453
                                for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
454
                                        idx := b >> 6
455
                                        if idx > maxPalette {
456
                                                return nil, FormatError("palette index out of range")
457
                                        }
458
                                        paletted.SetColorIndex(x+x2, y, idx)
459
                                        b <<= 2
460
                                }
461
                        }
462
                case cbP4:
463
                        for x := 0; x < d.width; x += 2 {
464
                                b := cdat[x/2]
465
                                for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
466
                                        idx := b >> 4
467
                                        if idx > maxPalette {
468
                                                return nil, FormatError("palette index out of range")
469
                                        }
470
                                        paletted.SetColorIndex(x+x2, y, idx)
471
                                        b <<= 4
472
                                }
473
                        }
474
                case cbP8:
475
                        for x := 0; x < d.width; x++ {
476
                                if cdat[x] > maxPalette {
477
                                        return nil, FormatError("palette index out of range")
478
                                }
479
                                paletted.SetColorIndex(x, y, cdat[x])
480
                        }
481
                case cbTCA8:
482
                        for x := 0; x < d.width; x++ {
483
                                nrgba.SetNRGBA(x, y, color.NRGBA{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
484
                        }
485
                case cbG16:
486
                        for x := 0; x < d.width; x++ {
487
                                ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
488
                                gray16.SetGray16(x, y, color.Gray16{ycol})
489
                        }
490
                case cbGA16:
491
                        for x := 0; x < d.width; x++ {
492
                                ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
493
                                acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
494
                                nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
495
                        }
496
                case cbTC16:
497
                        for x := 0; x < d.width; x++ {
498
                                rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
499
                                gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
500
                                bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
501
                                rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
502
                        }
503
                case cbTCA16:
504
                        for x := 0; x < d.width; x++ {
505
                                rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
506
                                gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
507
                                bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
508
                                acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
509
                                nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
510
                        }
511
                }
512
 
513
                // The current row for y is the previous row for y+1.
514
                pr, cr = cr, pr
515
        }
516
 
517
        // Check for EOF, to verify the zlib checksum.
518
        n, err := r.Read(pr[:1])
519
        if err != io.EOF {
520
                return nil, FormatError(err.Error())
521
        }
522
        if n != 0 || d.idatLength != 0 {
523
                return nil, FormatError("too much pixel data")
524
        }
525
 
526
        return img, nil
527
}
528
 
529
func (d *decoder) parseIDAT(length uint32) (err error) {
530
        d.idatLength = length
531
        d.img, err = d.decode()
532
        if err != nil {
533
                return err
534
        }
535
        return d.verifyChecksum()
536
}
537
 
538
func (d *decoder) parseIEND(length uint32) error {
539
        if length != 0 {
540
                return FormatError("bad IEND length")
541
        }
542
        return d.verifyChecksum()
543
}
544
 
545
func (d *decoder) parseChunk() error {
546
        // Read the length and chunk type.
547
        n, err := io.ReadFull(d.r, d.tmp[:8])
548
        if err != nil {
549
                return err
550
        }
551
        length := binary.BigEndian.Uint32(d.tmp[:4])
552
        d.crc.Reset()
553
        d.crc.Write(d.tmp[4:8])
554
 
555
        // Read the chunk data.
556
        switch string(d.tmp[4:8]) {
557
        case "IHDR":
558
                if d.stage != dsStart {
559
                        return chunkOrderError
560
                }
561
                d.stage = dsSeenIHDR
562
                return d.parseIHDR(length)
563
        case "PLTE":
564
                if d.stage != dsSeenIHDR {
565
                        return chunkOrderError
566
                }
567
                d.stage = dsSeenPLTE
568
                return d.parsePLTE(length)
569
        case "tRNS":
570
                if d.stage != dsSeenPLTE {
571
                        return chunkOrderError
572
                }
573
                return d.parsetRNS(length)
574
        case "IDAT":
575
                if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.cb == cbP8 && d.stage == dsSeenIHDR) {
576
                        return chunkOrderError
577
                }
578
                d.stage = dsSeenIDAT
579
                return d.parseIDAT(length)
580
        case "IEND":
581
                if d.stage != dsSeenIDAT {
582
                        return chunkOrderError
583
                }
584
                d.stage = dsSeenIEND
585
                return d.parseIEND(length)
586
        }
587
        // Ignore this chunk (of a known length).
588
        var ignored [4096]byte
589
        for length > 0 {
590
                n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
591
                if err != nil {
592
                        return err
593
                }
594
                d.crc.Write(ignored[:n])
595
                length -= uint32(n)
596
        }
597
        return d.verifyChecksum()
598
}
599
 
600
func (d *decoder) verifyChecksum() error {
601
        if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
602
                return err
603
        }
604
        if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
605
                return FormatError("invalid checksum")
606
        }
607
        return nil
608
}
609
 
610
func (d *decoder) checkHeader() error {
611
        _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
612
        if err != nil {
613
                return err
614
        }
615
        if string(d.tmp[:len(pngHeader)]) != pngHeader {
616
                return FormatError("not a PNG file")
617
        }
618
        return nil
619
}
620
 
621
// Decode reads a PNG image from r and returns it as an image.Image.
622
// The type of Image returned depends on the PNG contents.
623
func Decode(r io.Reader) (image.Image, error) {
624
        d := &decoder{
625
                r:   r,
626
                crc: crc32.NewIEEE(),
627
        }
628
        if err := d.checkHeader(); err != nil {
629
                if err == io.EOF {
630
                        err = io.ErrUnexpectedEOF
631
                }
632
                return nil, err
633
        }
634
        for d.stage != dsSeenIEND {
635
                if err := d.parseChunk(); err != nil {
636
                        if err == io.EOF {
637
                                err = io.ErrUnexpectedEOF
638
                        }
639
                        return nil, err
640
                }
641
        }
642
        return d.img, nil
643
}
644
 
645
// DecodeConfig returns the color model and dimensions of a PNG image without
646
// decoding the entire image.
647
func DecodeConfig(r io.Reader) (image.Config, error) {
648
        d := &decoder{
649
                r:   r,
650
                crc: crc32.NewIEEE(),
651
        }
652
        if err := d.checkHeader(); err != nil {
653
                if err == io.EOF {
654
                        err = io.ErrUnexpectedEOF
655
                }
656
                return image.Config{}, err
657
        }
658
        for {
659
                if err := d.parseChunk(); err != nil {
660
                        if err == io.EOF {
661
                                err = io.ErrUnexpectedEOF
662
                        }
663
                        return image.Config{}, err
664
                }
665
                if d.stage == dsSeenIHDR && d.cb != cbP8 {
666
                        break
667
                }
668
                if d.stage == dsSeenPLTE && d.cb == cbP8 {
669
                        break
670
                }
671
        }
672
        var cm color.Model
673
        switch d.cb {
674
        case cbG1, cbG2, cbG4, cbG8:
675
                cm = color.GrayModel
676
        case cbGA8:
677
                cm = color.NRGBAModel
678
        case cbTC8:
679
                cm = color.RGBAModel
680
        case cbP1, cbP2, cbP4, cbP8:
681
                cm = d.palette
682
        case cbTCA8:
683
                cm = color.NRGBAModel
684
        case cbG16:
685
                cm = color.Gray16Model
686
        case cbGA16:
687
                cm = color.NRGBA64Model
688
        case cbTC16:
689
                cm = color.RGBA64Model
690
        case cbTCA16:
691
                cm = color.NRGBA64Model
692
        }
693
        return image.Config{
694
                ColorModel: cm,
695
                Width:      d.width,
696
                Height:     d.height,
697
        }, nil
698
}
699
 
700
func init() {
701
        image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
702
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.