Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(498)

Side by Side Diff: tiff/writer.go

Issue 6866051: code review 6866051: tiff: support for writing compressed images. (Closed)
Patch Set: diff -r a0de9da0017e https://code.google.com/p/go.image Created 12 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tiff/consts.go ('k') | tiff/writer_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Go Authors. All rights reserved. 1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package tiff 5 package tiff
6 6
7 import ( 7 import (
8 "bytes"
9 "compress/zlib"
8 "encoding/binary" 10 "encoding/binary"
9 "image" 11 "image"
10 "io" 12 "io"
11 "sort" 13 "sort"
12 ) 14 )
13 15
14 // The TIFF format allows to choose the order of the different elements freely. 16 // The TIFF format allows to choose the order of the different elements freely.
15 // The basic structure of a TIFF file written by this package is: 17 // The basic structure of a TIFF file written by this package is:
16 // 18 //
17 // 1. Header (8 bytes). 19 // 1. Header (8 bytes).
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 // types of images and compressors. For example, it works well for 174 // types of images and compressors. For example, it works well for
173 // photos with Deflate compression. 175 // photos with Deflate compression.
174 Predictor bool 176 Predictor bool
175 } 177 }
176 178
177 // Encode writes the image m to w. opt determines the options used for 179 // Encode writes the image m to w. opt determines the options used for
178 // encoding, such as the compression type. If opt is nil, an uncompressed 180 // encoding, such as the compression type. If opt is nil, an uncompressed
179 // image is written. 181 // image is written.
180 func Encode(w io.Writer, m image.Image, opt *Options) error { 182 func Encode(w io.Writer, m image.Image, opt *Options) error {
181 predictor := false 183 predictor := false
182 » compression := Uncompressed 184 » compression := uint32(cNone)
183 if opt != nil { 185 if opt != nil {
184 predictor = opt.Predictor 186 predictor = opt.Predictor
185 » » compression = opt.Compression 187 » » compression = opt.Compression.specValue()
186 » }
187 » if compression != Uncompressed {
188 » » return UnsupportedError("compression type")
189 } 188 }
190 189
191 var extrasamples uint32
192 _, err := io.WriteString(w, leHeader) 190 _, err := io.WriteString(w, leHeader)
193 if err != nil { 191 if err != nil {
194 return err 192 return err
195 } 193 }
196 194
195 // Compressed data is written into a buffer first, so that we
196 // know the compressed size.
197 var buf bytes.Buffer
198 // dst holds the destination for the pixel data of the image --
199 // either w or a writer to buf.
200 var dst io.Writer
201 // imageLen is the length of the pixel data in bytes.
202 // The offset of the IFD is imageLen + 8 header bytes.
203 var imageLen int
197 bounds := m.Bounds() 204 bounds := m.Bounds()
198 width, height := bounds.Dx(), bounds.Dy() 205 width, height := bounds.Dx(), bounds.Dy()
199 » // imageLen is the length of the image data in bytes. 206
200 » imageLen := width * height * 4 207 » switch compression {
201 » ifdOffset := imageLen + 8 // 8 bytes for TIFF header. 208 » case cNone:
202 » err = binary.Write(w, enc, uint32(ifdOffset)) 209 » » dst = w
203 » if err != nil { 210 » » // Write IFD offset before outputting pixel data.
204 » » return err 211 » » imageLen = width * height * 4
212 » » err = binary.Write(w, enc, uint32(imageLen+8))
213 » » if err != nil {
214 » » » return err
215 » » }
216 » case cDeflate:
217 » » dst = zlib.NewWriter(&buf)
205 } 218 }
219
206 var pr uint32 = prNone 220 var pr uint32 = prNone
207 » extrasamples = 1 // Associated alpha (default). 221 » var extrasamples uint32 = 1 // Associated alpha (default).
208 if predictor { 222 if predictor {
209 pr = prHorizontal 223 pr = prHorizontal
210 » » err = writeImgData(w, m, predictor) 224 » » err = writeImgData(dst, m, predictor)
211 } else { 225 } else {
212 switch img := m.(type) { 226 switch img := m.(type) {
213 case *image.NRGBA: 227 case *image.NRGBA:
214 extrasamples = 2 // Unassociated alpha. 228 extrasamples = 2 // Unassociated alpha.
215 off := img.PixOffset(img.Rect.Min.X, img.Rect.Min.Y) 229 off := img.PixOffset(img.Rect.Min.X, img.Rect.Min.Y)
216 » » » err = writePix(w, img.Pix[off:], img.Rect.Dy(), 4*img.Re ct.Dx(), img.Stride) 230 » » » err = writePix(dst, img.Pix[off:], img.Rect.Dy(), 4*img. Rect.Dx(), img.Stride)
217 case *image.RGBA: 231 case *image.RGBA:
218 off := img.PixOffset(img.Rect.Min.X, img.Rect.Min.Y) 232 off := img.PixOffset(img.Rect.Min.X, img.Rect.Min.Y)
219 » » » err = writePix(w, img.Pix[off:], img.Rect.Dy(), 4*img.Re ct.Dx(), img.Stride) 233 » » » err = writePix(dst, img.Pix[off:], img.Rect.Dy(), 4*img. Rect.Dx(), img.Stride)
220 default: 234 default:
221 » » » err = writeImgData(w, m, predictor) 235 » » » err = writeImgData(dst, m, predictor)
222 } 236 }
223 } 237 }
224 if err != nil { 238 if err != nil {
225 return err 239 return err
226 } 240 }
227 241
228 » return writeIFD(w, ifdOffset, []ifdEntry{ 242 » if compression != cNone {
243 » » if err = dst.(io.Closer).Close(); err != nil {
244 » » » return err
245 » » }
246 » » imageLen = buf.Len()
247 » » if err = binary.Write(w, enc, uint32(imageLen+8)); err != nil {
248 » » » return err
249 » » }
250 » » if _, err = buf.WriteTo(w); err != nil {
251 » » » return err
252 » » }
253 » }
254
255 » return writeIFD(w, imageLen+8, []ifdEntry{
229 {tImageWidth, dtShort, []uint32{uint32(width)}}, 256 {tImageWidth, dtShort, []uint32{uint32(width)}},
230 {tImageLength, dtShort, []uint32{uint32(height)}}, 257 {tImageLength, dtShort, []uint32{uint32(height)}},
231 {tBitsPerSample, dtShort, []uint32{8, 8, 8, 8}}, 258 {tBitsPerSample, dtShort, []uint32{8, 8, 8, 8}},
232 » » {tCompression, dtShort, []uint32{cNone}}, 259 » » {tCompression, dtShort, []uint32{compression}},
233 {tPhotometricInterpretation, dtShort, []uint32{pRGB}}, 260 {tPhotometricInterpretation, dtShort, []uint32{pRGB}},
234 {tStripOffsets, dtLong, []uint32{8}}, 261 {tStripOffsets, dtLong, []uint32{8}},
235 {tSamplesPerPixel, dtShort, []uint32{4}}, 262 {tSamplesPerPixel, dtShort, []uint32{4}},
236 {tRowsPerStrip, dtShort, []uint32{uint32(height)}}, 263 {tRowsPerStrip, dtShort, []uint32{uint32(height)}},
237 {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}}, 264 {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}},
238 // There is currently no support for storing the image 265 // There is currently no support for storing the image
239 // resolution, so give a bogus value of 72x72 dpi. 266 // resolution, so give a bogus value of 72x72 dpi.
240 {tXResolution, dtRational, []uint32{72, 1}}, 267 {tXResolution, dtRational, []uint32{72, 1}},
241 {tYResolution, dtRational, []uint32{72, 1}}, 268 {tYResolution, dtRational, []uint32{72, 1}},
242 {tResolutionUnit, dtShort, []uint32{resPerInch}}, 269 {tResolutionUnit, dtShort, []uint32{resPerInch}},
243 {tPredictor, dtShort, []uint32{pr}}, 270 {tPredictor, dtShort, []uint32{pr}},
244 {tExtraSamples, dtShort, []uint32{extrasamples}}, 271 {tExtraSamples, dtShort, []uint32{extrasamples}},
245 }) 272 })
246 } 273 }
OLDNEW
« no previous file with comments | « tiff/consts.go ('k') | tiff/writer_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b