Home | History | Annotate | Download | only in png
      1 // 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
      6 
      7 import (
      8 	"bufio"
      9 	"compress/zlib"
     10 	"hash/crc32"
     11 	"image"
     12 	"image/color"
     13 	"io"
     14 	"strconv"
     15 )
     16 
     17 // Encoder configures encoding PNG images.
     18 type Encoder struct {
     19 	CompressionLevel CompressionLevel
     20 
     21 	// BufferPool optionally specifies a buffer pool to get temporary
     22 	// EncoderBuffers when encoding an image.
     23 	BufferPool EncoderBufferPool
     24 }
     25 
     26 // EncoderBufferPool is an interface for getting and returning temporary
     27 // instances of the EncoderBuffer struct. This can be used to reuse buffers
     28 // when encoding multiple images.
     29 type EncoderBufferPool interface {
     30 	Get() *EncoderBuffer
     31 	Put(*EncoderBuffer)
     32 }
     33 
     34 // EncoderBuffer holds the buffers used for encoding PNG images.
     35 type EncoderBuffer encoder
     36 
     37 type encoder struct {
     38 	enc     *Encoder
     39 	w       io.Writer
     40 	m       image.Image
     41 	cb      int
     42 	err     error
     43 	header  [8]byte
     44 	footer  [4]byte
     45 	tmp     [4 * 256]byte
     46 	cr      [nFilter][]uint8
     47 	pr      []uint8
     48 	zw      *zlib.Writer
     49 	zwLevel int
     50 	bw      *bufio.Writer
     51 }
     52 
     53 type CompressionLevel int
     54 
     55 const (
     56 	DefaultCompression CompressionLevel = 0
     57 	NoCompression      CompressionLevel = -1
     58 	BestSpeed          CompressionLevel = -2
     59 	BestCompression    CompressionLevel = -3
     60 
     61 	// Positive CompressionLevel values are reserved to mean a numeric zlib
     62 	// compression level, although that is not implemented yet.
     63 )
     64 
     65 // Big-endian.
     66 func writeUint32(b []uint8, u uint32) {
     67 	b[0] = uint8(u >> 24)
     68 	b[1] = uint8(u >> 16)
     69 	b[2] = uint8(u >> 8)
     70 	b[3] = uint8(u >> 0)
     71 }
     72 
     73 type opaquer interface {
     74 	Opaque() bool
     75 }
     76 
     77 // Returns whether or not the image is fully opaque.
     78 func opaque(m image.Image) bool {
     79 	if o, ok := m.(opaquer); ok {
     80 		return o.Opaque()
     81 	}
     82 	b := m.Bounds()
     83 	for y := b.Min.Y; y < b.Max.Y; y++ {
     84 		for x := b.Min.X; x < b.Max.X; x++ {
     85 			_, _, _, a := m.At(x, y).RGBA()
     86 			if a != 0xffff {
     87 				return false
     88 			}
     89 		}
     90 	}
     91 	return true
     92 }
     93 
     94 // The absolute value of a byte interpreted as a signed int8.
     95 func abs8(d uint8) int {
     96 	if d < 128 {
     97 		return int(d)
     98 	}
     99 	return 256 - int(d)
    100 }
    101 
    102 func (e *encoder) writeChunk(b []byte, name string) {
    103 	if e.err != nil {
    104 		return
    105 	}
    106 	n := uint32(len(b))
    107 	if int(n) != len(b) {
    108 		e.err = UnsupportedError(name + " chunk is too large: " + strconv.Itoa(len(b)))
    109 		return
    110 	}
    111 	writeUint32(e.header[:4], n)
    112 	e.header[4] = name[0]
    113 	e.header[5] = name[1]
    114 	e.header[6] = name[2]
    115 	e.header[7] = name[3]
    116 	crc := crc32.NewIEEE()
    117 	crc.Write(e.header[4:8])
    118 	crc.Write(b)
    119 	writeUint32(e.footer[:4], crc.Sum32())
    120 
    121 	_, e.err = e.w.Write(e.header[:8])
    122 	if e.err != nil {
    123 		return
    124 	}
    125 	_, e.err = e.w.Write(b)
    126 	if e.err != nil {
    127 		return
    128 	}
    129 	_, e.err = e.w.Write(e.footer[:4])
    130 }
    131 
    132 func (e *encoder) writeIHDR() {
    133 	b := e.m.Bounds()
    134 	writeUint32(e.tmp[0:4], uint32(b.Dx()))
    135 	writeUint32(e.tmp[4:8], uint32(b.Dy()))
    136 	// Set bit depth and color type.
    137 	switch e.cb {
    138 	case cbG8:
    139 		e.tmp[8] = 8
    140 		e.tmp[9] = ctGrayscale
    141 	case cbTC8:
    142 		e.tmp[8] = 8
    143 		e.tmp[9] = ctTrueColor
    144 	case cbP8:
    145 		e.tmp[8] = 8
    146 		e.tmp[9] = ctPaletted
    147 	case cbTCA8:
    148 		e.tmp[8] = 8
    149 		e.tmp[9] = ctTrueColorAlpha
    150 	case cbG16:
    151 		e.tmp[8] = 16
    152 		e.tmp[9] = ctGrayscale
    153 	case cbTC16:
    154 		e.tmp[8] = 16
    155 		e.tmp[9] = ctTrueColor
    156 	case cbTCA16:
    157 		e.tmp[8] = 16
    158 		e.tmp[9] = ctTrueColorAlpha
    159 	}
    160 	e.tmp[10] = 0 // default compression method
    161 	e.tmp[11] = 0 // default filter method
    162 	e.tmp[12] = 0 // non-interlaced
    163 	e.writeChunk(e.tmp[:13], "IHDR")
    164 }
    165 
    166 func (e *encoder) writePLTEAndTRNS(p color.Palette) {
    167 	if len(p) < 1 || len(p) > 256 {
    168 		e.err = FormatError("bad palette length: " + strconv.Itoa(len(p)))
    169 		return
    170 	}
    171 	last := -1
    172 	for i, c := range p {
    173 		c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
    174 		e.tmp[3*i+0] = c1.R
    175 		e.tmp[3*i+1] = c1.G
    176 		e.tmp[3*i+2] = c1.B
    177 		if c1.A != 0xff {
    178 			last = i
    179 		}
    180 		e.tmp[3*256+i] = c1.A
    181 	}
    182 	e.writeChunk(e.tmp[:3*len(p)], "PLTE")
    183 	if last != -1 {
    184 		e.writeChunk(e.tmp[3*256:3*256+1+last], "tRNS")
    185 	}
    186 }
    187 
    188 // An encoder is an io.Writer that satisfies writes by writing PNG IDAT chunks,
    189 // including an 8-byte header and 4-byte CRC checksum per Write call. Such calls
    190 // should be relatively infrequent, since writeIDATs uses a bufio.Writer.
    191 //
    192 // This method should only be called from writeIDATs (via writeImage).
    193 // No other code should treat an encoder as an io.Writer.
    194 func (e *encoder) Write(b []byte) (int, error) {
    195 	e.writeChunk(b, "IDAT")
    196 	if e.err != nil {
    197 		return 0, e.err
    198 	}
    199 	return len(b), nil
    200 }
    201 
    202 // Chooses the filter to use for encoding the current row, and applies it.
    203 // The return value is the index of the filter and also of the row in cr that has had it applied.
    204 func filter(cr *[nFilter][]byte, pr []byte, bpp int) int {
    205 	// We try all five filter types, and pick the one that minimizes the sum of absolute differences.
    206 	// This is the same heuristic that libpng uses, although the filters are attempted in order of
    207 	// estimated most likely to be minimal (ftUp, ftPaeth, ftNone, ftSub, ftAverage), rather than
    208 	// in their enumeration order (ftNone, ftSub, ftUp, ftAverage, ftPaeth).
    209 	cdat0 := cr[0][1:]
    210 	cdat1 := cr[1][1:]
    211 	cdat2 := cr[2][1:]
    212 	cdat3 := cr[3][1:]
    213 	cdat4 := cr[4][1:]
    214 	pdat := pr[1:]
    215 	n := len(cdat0)
    216 
    217 	// The up filter.
    218 	sum := 0
    219 	for i := 0; i < n; i++ {
    220 		cdat2[i] = cdat0[i] - pdat[i]
    221 		sum += abs8(cdat2[i])
    222 	}
    223 	best := sum
    224 	filter := ftUp
    225 
    226 	// The Paeth filter.
    227 	sum = 0
    228 	for i := 0; i < bpp; i++ {
    229 		cdat4[i] = cdat0[i] - pdat[i]
    230 		sum += abs8(cdat4[i])
    231 	}
    232 	for i := bpp; i < n; i++ {
    233 		cdat4[i] = cdat0[i] - paeth(cdat0[i-bpp], pdat[i], pdat[i-bpp])
    234 		sum += abs8(cdat4[i])
    235 		if sum >= best {
    236 			break
    237 		}
    238 	}
    239 	if sum < best {
    240 		best = sum
    241 		filter = ftPaeth
    242 	}
    243 
    244 	// The none filter.
    245 	sum = 0
    246 	for i := 0; i < n; i++ {
    247 		sum += abs8(cdat0[i])
    248 		if sum >= best {
    249 			break
    250 		}
    251 	}
    252 	if sum < best {
    253 		best = sum
    254 		filter = ftNone
    255 	}
    256 
    257 	// The sub filter.
    258 	sum = 0
    259 	for i := 0; i < bpp; i++ {
    260 		cdat1[i] = cdat0[i]
    261 		sum += abs8(cdat1[i])
    262 	}
    263 	for i := bpp; i < n; i++ {
    264 		cdat1[i] = cdat0[i] - cdat0[i-bpp]
    265 		sum += abs8(cdat1[i])
    266 		if sum >= best {
    267 			break
    268 		}
    269 	}
    270 	if sum < best {
    271 		best = sum
    272 		filter = ftSub
    273 	}
    274 
    275 	// The average filter.
    276 	sum = 0
    277 	for i := 0; i < bpp; i++ {
    278 		cdat3[i] = cdat0[i] - pdat[i]/2
    279 		sum += abs8(cdat3[i])
    280 	}
    281 	for i := bpp; i < n; i++ {
    282 		cdat3[i] = cdat0[i] - uint8((int(cdat0[i-bpp])+int(pdat[i]))/2)
    283 		sum += abs8(cdat3[i])
    284 		if sum >= best {
    285 			break
    286 		}
    287 	}
    288 	if sum < best {
    289 		best = sum
    290 		filter = ftAverage
    291 	}
    292 
    293 	return filter
    294 }
    295 
    296 func zeroMemory(v []uint8) {
    297 	for i := range v {
    298 		v[i] = 0
    299 	}
    300 }
    301 
    302 func (e *encoder) writeImage(w io.Writer, m image.Image, cb int, level int) error {
    303 	if e.zw == nil || e.zwLevel != level {
    304 		zw, err := zlib.NewWriterLevel(w, level)
    305 		if err != nil {
    306 			return err
    307 		}
    308 		e.zw = zw
    309 		e.zwLevel = level
    310 	} else {
    311 		e.zw.Reset(w)
    312 	}
    313 	defer e.zw.Close()
    314 
    315 	bpp := 0 // Bytes per pixel.
    316 
    317 	switch cb {
    318 	case cbG8:
    319 		bpp = 1
    320 	case cbTC8:
    321 		bpp = 3
    322 	case cbP8:
    323 		bpp = 1
    324 	case cbTCA8:
    325 		bpp = 4
    326 	case cbTC16:
    327 		bpp = 6
    328 	case cbTCA16:
    329 		bpp = 8
    330 	case cbG16:
    331 		bpp = 2
    332 	}
    333 	// cr[*] and pr are the bytes for the current and previous row.
    334 	// cr[0] is unfiltered (or equivalently, filtered with the ftNone filter).
    335 	// cr[ft], for non-zero filter types ft, are buffers for transforming cr[0] under the
    336 	// other PNG filter types. These buffers are allocated once and re-used for each row.
    337 	// The +1 is for the per-row filter type, which is at cr[*][0].
    338 	b := m.Bounds()
    339 	sz := 1 + bpp*b.Dx()
    340 	for i := range e.cr {
    341 		if cap(e.cr[i]) < sz {
    342 			e.cr[i] = make([]uint8, sz)
    343 		} else {
    344 			e.cr[i] = e.cr[i][:sz]
    345 		}
    346 		e.cr[i][0] = uint8(i)
    347 	}
    348 	cr := e.cr
    349 	if cap(e.pr) < sz {
    350 		e.pr = make([]uint8, sz)
    351 	} else {
    352 		e.pr = e.pr[:sz]
    353 		zeroMemory(e.pr)
    354 	}
    355 	pr := e.pr
    356 
    357 	gray, _ := m.(*image.Gray)
    358 	rgba, _ := m.(*image.RGBA)
    359 	paletted, _ := m.(*image.Paletted)
    360 	nrgba, _ := m.(*image.NRGBA)
    361 
    362 	for y := b.Min.Y; y < b.Max.Y; y++ {
    363 		// Convert from colors to bytes.
    364 		i := 1
    365 		switch cb {
    366 		case cbG8:
    367 			if gray != nil {
    368 				offset := (y - b.Min.Y) * gray.Stride
    369 				copy(cr[0][1:], gray.Pix[offset:offset+b.Dx()])
    370 			} else {
    371 				for x := b.Min.X; x < b.Max.X; x++ {
    372 					c := color.GrayModel.Convert(m.At(x, y)).(color.Gray)
    373 					cr[0][i] = c.Y
    374 					i++
    375 				}
    376 			}
    377 		case cbTC8:
    378 			// We have previously verified that the alpha value is fully opaque.
    379 			cr0 := cr[0]
    380 			stride, pix := 0, []byte(nil)
    381 			if rgba != nil {
    382 				stride, pix = rgba.Stride, rgba.Pix
    383 			} else if nrgba != nil {
    384 				stride, pix = nrgba.Stride, nrgba.Pix
    385 			}
    386 			if stride != 0 {
    387 				j0 := (y - b.Min.Y) * stride
    388 				j1 := j0 + b.Dx()*4
    389 				for j := j0; j < j1; j += 4 {
    390 					cr0[i+0] = pix[j+0]
    391 					cr0[i+1] = pix[j+1]
    392 					cr0[i+2] = pix[j+2]
    393 					i += 3
    394 				}
    395 			} else {
    396 				for x := b.Min.X; x < b.Max.X; x++ {
    397 					r, g, b, _ := m.At(x, y).RGBA()
    398 					cr0[i+0] = uint8(r >> 8)
    399 					cr0[i+1] = uint8(g >> 8)
    400 					cr0[i+2] = uint8(b >> 8)
    401 					i += 3
    402 				}
    403 			}
    404 		case cbP8:
    405 			if paletted != nil {
    406 				offset := (y - b.Min.Y) * paletted.Stride
    407 				copy(cr[0][1:], paletted.Pix[offset:offset+b.Dx()])
    408 			} else {
    409 				pi := m.(image.PalettedImage)
    410 				for x := b.Min.X; x < b.Max.X; x++ {
    411 					cr[0][i] = pi.ColorIndexAt(x, y)
    412 					i += 1
    413 				}
    414 			}
    415 		case cbTCA8:
    416 			if nrgba != nil {
    417 				offset := (y - b.Min.Y) * nrgba.Stride
    418 				copy(cr[0][1:], nrgba.Pix[offset:offset+b.Dx()*4])
    419 			} else {
    420 				// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
    421 				for x := b.Min.X; x < b.Max.X; x++ {
    422 					c := color.NRGBAModel.Convert(m.At(x, y)).(color.NRGBA)
    423 					cr[0][i+0] = c.R
    424 					cr[0][i+1] = c.G
    425 					cr[0][i+2] = c.B
    426 					cr[0][i+3] = c.A
    427 					i += 4
    428 				}
    429 			}
    430 		case cbG16:
    431 			for x := b.Min.X; x < b.Max.X; x++ {
    432 				c := color.Gray16Model.Convert(m.At(x, y)).(color.Gray16)
    433 				cr[0][i+0] = uint8(c.Y >> 8)
    434 				cr[0][i+1] = uint8(c.Y)
    435 				i += 2
    436 			}
    437 		case cbTC16:
    438 			// We have previously verified that the alpha value is fully opaque.
    439 			for x := b.Min.X; x < b.Max.X; x++ {
    440 				r, g, b, _ := m.At(x, y).RGBA()
    441 				cr[0][i+0] = uint8(r >> 8)
    442 				cr[0][i+1] = uint8(r)
    443 				cr[0][i+2] = uint8(g >> 8)
    444 				cr[0][i+3] = uint8(g)
    445 				cr[0][i+4] = uint8(b >> 8)
    446 				cr[0][i+5] = uint8(b)
    447 				i += 6
    448 			}
    449 		case cbTCA16:
    450 			// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
    451 			for x := b.Min.X; x < b.Max.X; x++ {
    452 				c := color.NRGBA64Model.Convert(m.At(x, y)).(color.NRGBA64)
    453 				cr[0][i+0] = uint8(c.R >> 8)
    454 				cr[0][i+1] = uint8(c.R)
    455 				cr[0][i+2] = uint8(c.G >> 8)
    456 				cr[0][i+3] = uint8(c.G)
    457 				cr[0][i+4] = uint8(c.B >> 8)
    458 				cr[0][i+5] = uint8(c.B)
    459 				cr[0][i+6] = uint8(c.A >> 8)
    460 				cr[0][i+7] = uint8(c.A)
    461 				i += 8
    462 			}
    463 		}
    464 
    465 		// Apply the filter.
    466 		// Skip filter for NoCompression and paletted images (cbP8) as
    467 		// "filters are rarely useful on palette images" and will result
    468 		// in larger files (see http://www.libpng.org/pub/png/book/chapter09.html).
    469 		f := ftNone
    470 		if level != zlib.NoCompression && cb != cbP8 {
    471 			f = filter(&cr, pr, bpp)
    472 		}
    473 
    474 		// Write the compressed bytes.
    475 		if _, err := e.zw.Write(cr[f]); err != nil {
    476 			return err
    477 		}
    478 
    479 		// The current row for y is the previous row for y+1.
    480 		pr, cr[0] = cr[0], pr
    481 	}
    482 	return nil
    483 }
    484 
    485 // Write the actual image data to one or more IDAT chunks.
    486 func (e *encoder) writeIDATs() {
    487 	if e.err != nil {
    488 		return
    489 	}
    490 	if e.bw == nil {
    491 		e.bw = bufio.NewWriterSize(e, 1<<15)
    492 	} else {
    493 		e.bw.Reset(e)
    494 	}
    495 	e.err = e.writeImage(e.bw, e.m, e.cb, levelToZlib(e.enc.CompressionLevel))
    496 	if e.err != nil {
    497 		return
    498 	}
    499 	e.err = e.bw.Flush()
    500 }
    501 
    502 // This function is required because we want the zero value of
    503 // Encoder.CompressionLevel to map to zlib.DefaultCompression.
    504 func levelToZlib(l CompressionLevel) int {
    505 	switch l {
    506 	case DefaultCompression:
    507 		return zlib.DefaultCompression
    508 	case NoCompression:
    509 		return zlib.NoCompression
    510 	case BestSpeed:
    511 		return zlib.BestSpeed
    512 	case BestCompression:
    513 		return zlib.BestCompression
    514 	default:
    515 		return zlib.DefaultCompression
    516 	}
    517 }
    518 
    519 func (e *encoder) writeIEND() { e.writeChunk(nil, "IEND") }
    520 
    521 // Encode writes the Image m to w in PNG format. Any Image may be
    522 // encoded, but images that are not image.NRGBA might be encoded lossily.
    523 func Encode(w io.Writer, m image.Image) error {
    524 	var e Encoder
    525 	return e.Encode(w, m)
    526 }
    527 
    528 // Encode writes the Image m to w in PNG format.
    529 func (enc *Encoder) Encode(w io.Writer, m image.Image) error {
    530 	// Obviously, negative widths and heights are invalid. Furthermore, the PNG
    531 	// spec section 11.2.2 says that zero is invalid. Excessively large images are
    532 	// also rejected.
    533 	mw, mh := int64(m.Bounds().Dx()), int64(m.Bounds().Dy())
    534 	if mw <= 0 || mh <= 0 || mw >= 1<<32 || mh >= 1<<32 {
    535 		return FormatError("invalid image size: " + strconv.FormatInt(mw, 10) + "x" + strconv.FormatInt(mh, 10))
    536 	}
    537 
    538 	var e *encoder
    539 	if enc.BufferPool != nil {
    540 		buffer := enc.BufferPool.Get()
    541 		e = (*encoder)(buffer)
    542 
    543 	}
    544 	if e == nil {
    545 		e = &encoder{}
    546 	}
    547 	if enc.BufferPool != nil {
    548 		defer enc.BufferPool.Put((*EncoderBuffer)(e))
    549 	}
    550 
    551 	e.enc = enc
    552 	e.w = w
    553 	e.m = m
    554 
    555 	var pal color.Palette
    556 	// cbP8 encoding needs PalettedImage's ColorIndexAt method.
    557 	if _, ok := m.(image.PalettedImage); ok {
    558 		pal, _ = m.ColorModel().(color.Palette)
    559 	}
    560 	if pal != nil {
    561 		e.cb = cbP8
    562 	} else {
    563 		switch m.ColorModel() {
    564 		case color.GrayModel:
    565 			e.cb = cbG8
    566 		case color.Gray16Model:
    567 			e.cb = cbG16
    568 		case color.RGBAModel, color.NRGBAModel, color.AlphaModel:
    569 			if opaque(m) {
    570 				e.cb = cbTC8
    571 			} else {
    572 				e.cb = cbTCA8
    573 			}
    574 		default:
    575 			if opaque(m) {
    576 				e.cb = cbTC16
    577 			} else {
    578 				e.cb = cbTCA16
    579 			}
    580 		}
    581 	}
    582 
    583 	_, e.err = io.WriteString(w, pngHeader)
    584 	e.writeIHDR()
    585 	if pal != nil {
    586 		e.writePLTEAndTRNS(pal)
    587 	}
    588 	e.writeIDATs()
    589 	e.writeIEND()
    590 	return e.err
    591 }
    592