writer.go (11878B)
1 // Copyright 2012 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 tiff 6 7 import ( 8 "bytes" 9 "compress/zlib" 10 "encoding/binary" 11 "errors" 12 "image" 13 "io" 14 "sort" 15 ) 16 17 // The TIFF format allows to choose the order of the different elements freely. 18 // The basic structure of a TIFF file written by this package is: 19 // 20 // 1. Header (8 bytes). 21 // 2. Image data. 22 // 3. Image File Directory (IFD). 23 // 4. "Pointer area" for larger entries in the IFD. 24 25 // We only write little-endian TIFF files. 26 var enc = binary.LittleEndian 27 28 // An ifdEntry is a single entry in an Image File Directory. 29 // A value of type dtRational is composed of two 32-bit values, 30 // thus data contains two uints (numerator and denominator) for a single number. 31 type ifdEntry struct { 32 tag int 33 datatype int 34 data []uint32 35 } 36 37 func (e ifdEntry) putData(p []byte) { 38 for _, d := range e.data { 39 switch e.datatype { 40 case dtByte, dtASCII: 41 p[0] = byte(d) 42 p = p[1:] 43 case dtShort: 44 enc.PutUint16(p, uint16(d)) 45 p = p[2:] 46 case dtLong, dtRational: 47 enc.PutUint32(p, uint32(d)) 48 p = p[4:] 49 } 50 } 51 } 52 53 type byTag []ifdEntry 54 55 func (d byTag) Len() int { return len(d) } 56 func (d byTag) Less(i, j int) bool { return d[i].tag < d[j].tag } 57 func (d byTag) Swap(i, j int) { d[i], d[j] = d[j], d[i] } 58 59 func encodeGray(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { 60 if !predictor { 61 return writePix(w, pix, dy, dx, stride) 62 } 63 buf := make([]byte, dx) 64 for y := 0; y < dy; y++ { 65 min := y*stride + 0 66 max := y*stride + dx 67 off := 0 68 var v0 uint8 69 for i := min; i < max; i++ { 70 v1 := pix[i] 71 buf[off] = v1 - v0 72 v0 = v1 73 off++ 74 } 75 if _, err := w.Write(buf); err != nil { 76 return err 77 } 78 } 79 return nil 80 } 81 82 func encodeGray16(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { 83 buf := make([]byte, dx*2) 84 for y := 0; y < dy; y++ { 85 min := y*stride + 0 86 max := y*stride + dx*2 87 off := 0 88 var v0 uint16 89 for i := min; i < max; i += 2 { 90 // An image.Gray16's Pix is in big-endian order. 91 v1 := uint16(pix[i])<<8 | uint16(pix[i+1]) 92 if predictor { 93 v0, v1 = v1, v1-v0 94 } 95 // We only write little-endian TIFF files. 96 buf[off+0] = byte(v1) 97 buf[off+1] = byte(v1 >> 8) 98 off += 2 99 } 100 if _, err := w.Write(buf); err != nil { 101 return err 102 } 103 } 104 return nil 105 } 106 107 func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { 108 if !predictor { 109 return writePix(w, pix, dy, dx*4, stride) 110 } 111 buf := make([]byte, dx*4) 112 for y := 0; y < dy; y++ { 113 min := y*stride + 0 114 max := y*stride + dx*4 115 off := 0 116 var r0, g0, b0, a0 uint8 117 for i := min; i < max; i += 4 { 118 r1, g1, b1, a1 := pix[i+0], pix[i+1], pix[i+2], pix[i+3] 119 buf[off+0] = r1 - r0 120 buf[off+1] = g1 - g0 121 buf[off+2] = b1 - b0 122 buf[off+3] = a1 - a0 123 off += 4 124 r0, g0, b0, a0 = r1, g1, b1, a1 125 } 126 if _, err := w.Write(buf); err != nil { 127 return err 128 } 129 } 130 return nil 131 } 132 133 func encodeRGBA64(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { 134 buf := make([]byte, dx*8) 135 for y := 0; y < dy; y++ { 136 min := y*stride + 0 137 max := y*stride + dx*8 138 off := 0 139 var r0, g0, b0, a0 uint16 140 for i := min; i < max; i += 8 { 141 // An image.RGBA64's Pix is in big-endian order. 142 r1 := uint16(pix[i+0])<<8 | uint16(pix[i+1]) 143 g1 := uint16(pix[i+2])<<8 | uint16(pix[i+3]) 144 b1 := uint16(pix[i+4])<<8 | uint16(pix[i+5]) 145 a1 := uint16(pix[i+6])<<8 | uint16(pix[i+7]) 146 if predictor { 147 r0, r1 = r1, r1-r0 148 g0, g1 = g1, g1-g0 149 b0, b1 = b1, b1-b0 150 a0, a1 = a1, a1-a0 151 } 152 // We only write little-endian TIFF files. 153 buf[off+0] = byte(r1) 154 buf[off+1] = byte(r1 >> 8) 155 buf[off+2] = byte(g1) 156 buf[off+3] = byte(g1 >> 8) 157 buf[off+4] = byte(b1) 158 buf[off+5] = byte(b1 >> 8) 159 buf[off+6] = byte(a1) 160 buf[off+7] = byte(a1 >> 8) 161 off += 8 162 } 163 if _, err := w.Write(buf); err != nil { 164 return err 165 } 166 } 167 return nil 168 } 169 170 func encode(w io.Writer, m image.Image, predictor bool) error { 171 bounds := m.Bounds() 172 buf := make([]byte, 4*bounds.Dx()) 173 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 174 off := 0 175 if predictor { 176 var r0, g0, b0, a0 uint8 177 for x := bounds.Min.X; x < bounds.Max.X; x++ { 178 r, g, b, a := m.At(x, y).RGBA() 179 r1 := uint8(r >> 8) 180 g1 := uint8(g >> 8) 181 b1 := uint8(b >> 8) 182 a1 := uint8(a >> 8) 183 buf[off+0] = r1 - r0 184 buf[off+1] = g1 - g0 185 buf[off+2] = b1 - b0 186 buf[off+3] = a1 - a0 187 off += 4 188 r0, g0, b0, a0 = r1, g1, b1, a1 189 } 190 } else { 191 for x := bounds.Min.X; x < bounds.Max.X; x++ { 192 r, g, b, a := m.At(x, y).RGBA() 193 buf[off+0] = uint8(r >> 8) 194 buf[off+1] = uint8(g >> 8) 195 buf[off+2] = uint8(b >> 8) 196 buf[off+3] = uint8(a >> 8) 197 off += 4 198 } 199 } 200 if _, err := w.Write(buf); err != nil { 201 return err 202 } 203 } 204 return nil 205 } 206 207 // writePix writes the internal byte array of an image to w. It is less general 208 // but much faster then encode. writePix is used when pix directly 209 // corresponds to one of the TIFF image types. 210 func writePix(w io.Writer, pix []byte, nrows, length, stride int) error { 211 if length == stride { 212 _, err := w.Write(pix[:nrows*length]) 213 return err 214 } 215 for ; nrows > 0; nrows-- { 216 if _, err := w.Write(pix[:length]); err != nil { 217 return err 218 } 219 pix = pix[stride:] 220 } 221 return nil 222 } 223 224 func writeIFD(w io.Writer, ifdOffset int, d []ifdEntry) error { 225 var buf [ifdLen]byte 226 // Make space for "pointer area" containing IFD entry data 227 // longer than 4 bytes. 228 parea := make([]byte, 1024) 229 pstart := ifdOffset + ifdLen*len(d) + 6 230 var o int // Current offset in parea. 231 232 // The IFD has to be written with the tags in ascending order. 233 sort.Sort(byTag(d)) 234 235 // Write the number of entries in this IFD. 236 if err := binary.Write(w, enc, uint16(len(d))); err != nil { 237 return err 238 } 239 for _, ent := range d { 240 enc.PutUint16(buf[0:2], uint16(ent.tag)) 241 enc.PutUint16(buf[2:4], uint16(ent.datatype)) 242 count := uint32(len(ent.data)) 243 if ent.datatype == dtRational { 244 count /= 2 245 } 246 enc.PutUint32(buf[4:8], count) 247 datalen := int(count * lengths[ent.datatype]) 248 if datalen <= 4 { 249 ent.putData(buf[8:12]) 250 } else { 251 if (o + datalen) > len(parea) { 252 newlen := len(parea) + 1024 253 for (o + datalen) > newlen { 254 newlen += 1024 255 } 256 newarea := make([]byte, newlen) 257 copy(newarea, parea) 258 parea = newarea 259 } 260 ent.putData(parea[o : o+datalen]) 261 enc.PutUint32(buf[8:12], uint32(pstart+o)) 262 o += datalen 263 } 264 if _, err := w.Write(buf[:]); err != nil { 265 return err 266 } 267 } 268 // The IFD ends with the offset of the next IFD in the file, 269 // or zero if it is the last one (page 14). 270 if err := binary.Write(w, enc, uint32(0)); err != nil { 271 return err 272 } 273 _, err := w.Write(parea[:o]) 274 return err 275 } 276 277 // Options are the encoding parameters. 278 type Options struct { 279 // Compression is the type of compression used. 280 Compression CompressionType 281 // Predictor determines whether a differencing predictor is used; 282 // if true, instead of each pixel's color, the color difference to the 283 // preceding one is saved. This improves the compression for certain 284 // types of images and compressors. For example, it works well for 285 // photos with Deflate compression. 286 Predictor bool 287 } 288 289 // Encode writes the image m to w. opt determines the options used for 290 // encoding, such as the compression type. If opt is nil, an uncompressed 291 // image is written. 292 func Encode(w io.Writer, m image.Image, opt *Options) error { 293 d := m.Bounds().Size() 294 295 compression := uint32(cNone) 296 predictor := false 297 if opt != nil { 298 compression = opt.Compression.specValue() 299 // The predictor field is only used with LZW. See page 64 of the spec. 300 predictor = opt.Predictor && compression == cLZW 301 } 302 303 _, err := io.WriteString(w, leHeader) 304 if err != nil { 305 return err 306 } 307 308 // Compressed data is written into a buffer first, so that we 309 // know the compressed size. 310 var buf bytes.Buffer 311 // dst holds the destination for the pixel data of the image -- 312 // either w or a writer to buf. 313 var dst io.Writer 314 // imageLen is the length of the pixel data in bytes. 315 // The offset of the IFD is imageLen + 8 header bytes. 316 var imageLen int 317 318 switch compression { 319 case cNone: 320 dst = w 321 // Write IFD offset before outputting pixel data. 322 switch m.(type) { 323 case *image.Paletted: 324 imageLen = d.X * d.Y * 1 325 case *image.Gray: 326 imageLen = d.X * d.Y * 1 327 case *image.Gray16: 328 imageLen = d.X * d.Y * 2 329 case *image.RGBA64: 330 imageLen = d.X * d.Y * 8 331 case *image.NRGBA64: 332 imageLen = d.X * d.Y * 8 333 default: 334 imageLen = d.X * d.Y * 4 335 } 336 err = binary.Write(w, enc, uint32(imageLen+8)) 337 if err != nil { 338 return err 339 } 340 case cDeflate: 341 dst = zlib.NewWriter(&buf) 342 default: 343 return errors.New("tiff: unsupported compression") 344 } 345 346 pr := uint32(prNone) 347 photometricInterpretation := uint32(pRGB) 348 samplesPerPixel := uint32(4) 349 bitsPerSample := []uint32{8, 8, 8, 8} 350 extraSamples := uint32(0) 351 colorMap := []uint32{} 352 353 if predictor { 354 pr = prHorizontal 355 } 356 switch m := m.(type) { 357 case *image.Paletted: 358 photometricInterpretation = pPaletted 359 samplesPerPixel = 1 360 bitsPerSample = []uint32{8} 361 colorMap = make([]uint32, 256*3) 362 for i := 0; i < 256 && i < len(m.Palette); i++ { 363 r, g, b, _ := m.Palette[i].RGBA() 364 colorMap[i+0*256] = uint32(r) 365 colorMap[i+1*256] = uint32(g) 366 colorMap[i+2*256] = uint32(b) 367 } 368 err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor) 369 case *image.Gray: 370 photometricInterpretation = pBlackIsZero 371 samplesPerPixel = 1 372 bitsPerSample = []uint32{8} 373 err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor) 374 case *image.Gray16: 375 photometricInterpretation = pBlackIsZero 376 samplesPerPixel = 1 377 bitsPerSample = []uint32{16} 378 err = encodeGray16(dst, m.Pix, d.X, d.Y, m.Stride, predictor) 379 case *image.NRGBA: 380 extraSamples = 2 // Unassociated alpha. 381 err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor) 382 case *image.NRGBA64: 383 extraSamples = 2 // Unassociated alpha. 384 bitsPerSample = []uint32{16, 16, 16, 16} 385 err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor) 386 case *image.RGBA: 387 extraSamples = 1 // Associated alpha. 388 err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor) 389 case *image.RGBA64: 390 extraSamples = 1 // Associated alpha. 391 bitsPerSample = []uint32{16, 16, 16, 16} 392 err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor) 393 default: 394 extraSamples = 1 // Associated alpha. 395 err = encode(dst, m, predictor) 396 } 397 if err != nil { 398 return err 399 } 400 401 if compression != cNone { 402 if err = dst.(io.Closer).Close(); err != nil { 403 return err 404 } 405 imageLen = buf.Len() 406 if err = binary.Write(w, enc, uint32(imageLen+8)); err != nil { 407 return err 408 } 409 if _, err = buf.WriteTo(w); err != nil { 410 return err 411 } 412 } 413 414 ifd := []ifdEntry{ 415 {tImageWidth, dtShort, []uint32{uint32(d.X)}}, 416 {tImageLength, dtShort, []uint32{uint32(d.Y)}}, 417 {tBitsPerSample, dtShort, bitsPerSample}, 418 {tCompression, dtShort, []uint32{compression}}, 419 {tPhotometricInterpretation, dtShort, []uint32{photometricInterpretation}}, 420 {tStripOffsets, dtLong, []uint32{8}}, 421 {tSamplesPerPixel, dtShort, []uint32{samplesPerPixel}}, 422 {tRowsPerStrip, dtShort, []uint32{uint32(d.Y)}}, 423 {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}}, 424 // There is currently no support for storing the image 425 // resolution, so give a bogus value of 72x72 dpi. 426 {tXResolution, dtRational, []uint32{72, 1}}, 427 {tYResolution, dtRational, []uint32{72, 1}}, 428 {tResolutionUnit, dtShort, []uint32{resPerInch}}, 429 } 430 if pr != prNone { 431 ifd = append(ifd, ifdEntry{tPredictor, dtShort, []uint32{pr}}) 432 } 433 if len(colorMap) != 0 { 434 ifd = append(ifd, ifdEntry{tColorMap, dtShort, colorMap}) 435 } 436 if extraSamples > 0 { 437 ifd = append(ifd, ifdEntry{tExtraSamples, dtShort, []uint32{extraSamples}}) 438 } 439 440 return writeIFD(w, imageLen+8, ifd) 441 }