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

Side by Side Diff: tiff/writer.go

Issue 5738044: code review 5738044: go.image/tiff: simplify encoding. (Closed)
Patch Set: diff -r 2bf0db14a16d https://code.google.com/p/go.image Created 13 years 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 | « no previous file | no next file » | 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 "encoding/binary" 8 "encoding/binary"
9 "image" 9 "image"
10 "io" 10 "io"
(...skipping 29 matching lines...) Expand all
40 case dtShort: 40 case dtShort:
41 enc.PutUint16(p, uint16(d)) 41 enc.PutUint16(p, uint16(d))
42 p = p[2:] 42 p = p[2:]
43 case dtLong, dtRational: 43 case dtLong, dtRational:
44 enc.PutUint32(p, uint32(d)) 44 enc.PutUint32(p, uint32(d))
45 p = p[4:] 45 p = p[4:]
46 } 46 }
47 } 47 }
48 } 48 }
49 49
50 type ifd []ifdEntry 50 type byTag []ifdEntry
51 51
52 func (d ifd) Len() int { 52 func (d byTag) Len() int { return len(d) }
53 » return len(d) 53 func (d byTag) Less(i, j int) bool { return d[i].tag < d[j].tag }
54 } 54 func (d byTag) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
55 55
56 func (d ifd) Less(i, j int) bool { 56 func writeImgData(w io.Writer, m image.Image) error {
57 » return d[i].tag < d[j].tag 57 » b := m.Bounds()
bsiegert 2012/03/05 13:21:14 Now that I think about it, this variable should ma
nigeltao 2012/03/05 23:35:04 Done.
58 }
59
60 func (d ifd) Swap(i, j int) {
61 » d[i], d[j] = d[j], d[i]
62 }
63
64 type encoder struct {
65 » ifd ifd
66 » img image.Image
67 » imageLen int // Length of the image in bytes.
68 }
69
70 func newEncoder(m image.Image) *encoder {
71 » width := m.Bounds().Dx()
72 » height := m.Bounds().Dy()
73 » imageLen := width * height * 4
74 » return &encoder{
75 » » img: m,
76 » » // For uncompressed images, imageLen is known in advance.
77 » » // For compressed images, we would need to write the image
78 » » // data in a buffer here to get its length.
79 » » imageLen: imageLen,
80 » » ifd: ifd{
81 » » » {tImageWidth, dtShort, []uint32{uint32(width)}},
82 » » » {tImageLength, dtShort, []uint32{uint32(height)}},
83 » » » {tBitsPerSample, dtShort, []uint32{8, 8, 8, 8}},
84 » » » {tCompression, dtShort, []uint32{cNone}},
85 » » » {tPhotometricInterpretation, dtShort, []uint32{pRGB}},
86 » » » {tStripOffsets, dtLong, []uint32{8}},
87 » » » {tSamplesPerPixel, dtShort, []uint32{4}},
88 » » » {tRowsPerStrip, dtShort, []uint32{uint32(height)}},
89 » » » {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}},
90 » » » // There is currently no support for storing the image
91 » » » // resolution, so give a bogus value of 72x72 dpi.
92 » » » {tXResolution, dtRational, []uint32{72, 1}},
93 » » » {tYResolution, dtRational, []uint32{72, 1}},
94 » » » {tResolutionUnit, dtShort, []uint32{resPerInch}},
95 » » » {tExtraSamples, dtShort, []uint32{1}}, // RGBA.
96 » » },
97 » }
98 }
99
100 func (e *encoder) writeImgData(w io.Writer) error {
101 » b := e.img.Bounds()
102 buf := make([]byte, 4*b.Dx()) 58 buf := make([]byte, 4*b.Dx())
103 for y := b.Min.Y; y < b.Max.Y; y++ { 59 for y := b.Min.Y; y < b.Max.Y; y++ {
104 i := 0 60 i := 0
105 for x := b.Min.X; x < b.Max.X; x++ { 61 for x := b.Min.X; x < b.Max.X; x++ {
106 » » » r, g, b, a := e.img.At(x, y).RGBA() 62 » » » r, g, b, a := m.At(x, y).RGBA()
107 buf[i+0] = uint8(r >> 8) 63 buf[i+0] = uint8(r >> 8)
108 buf[i+1] = uint8(g >> 8) 64 buf[i+1] = uint8(g >> 8)
109 buf[i+2] = uint8(b >> 8) 65 buf[i+2] = uint8(b >> 8)
110 buf[i+3] = uint8(a >> 8) 66 buf[i+3] = uint8(a >> 8)
111 i += 4 67 i += 4
112 } 68 }
113 if _, err := w.Write(buf); err != nil { 69 if _, err := w.Write(buf); err != nil {
114 return err 70 return err
115 } 71 }
116 } 72 }
117 return nil 73 return nil
118 } 74 }
119 75
120 func (e *encoder) writeIFD(w io.Writer) error { 76 func writeIFD(w io.Writer, ifdOffset int, d []ifdEntry) error {
121 var buf [ifdLen]byte 77 var buf [ifdLen]byte
122 // Make space for "pointer area" containing IFD entry data 78 // Make space for "pointer area" containing IFD entry data
123 // longer than 4 bytes. 79 // longer than 4 bytes.
124 parea := make([]byte, 1024) 80 parea := make([]byte, 1024)
125 » pstart := int(e.imageLen) + 8 + (ifdLen * len(e.ifd)) + 6 81 » pstart := ifdOffset + ifdLen*len(d) + 6
126 var o int // Current offset in parea. 82 var o int // Current offset in parea.
127 83
128 // The IFD has to be written with the tags in ascending order. 84 // The IFD has to be written with the tags in ascending order.
129 » sort.Sort(e.ifd) 85 » sort.Sort(byTag(d))
130 86
131 // Write the number of entries in this IFD. 87 // Write the number of entries in this IFD.
132 » if err := binary.Write(w, enc, uint16(len(e.ifd))); err != nil { 88 » if err := binary.Write(w, enc, uint16(len(d))); err != nil {
133 return err 89 return err
134 } 90 }
135 » for _, ent := range e.ifd { 91 » for _, ent := range d {
136 enc.PutUint16(buf[0:2], uint16(ent.tag)) 92 enc.PutUint16(buf[0:2], uint16(ent.tag))
137 enc.PutUint16(buf[2:4], uint16(ent.datatype)) 93 enc.PutUint16(buf[2:4], uint16(ent.datatype))
138 count := uint32(len(ent.data)) 94 count := uint32(len(ent.data))
139 if ent.datatype == dtRational { 95 if ent.datatype == dtRational {
140 count /= 2 96 count /= 2
141 } 97 }
142 enc.PutUint32(buf[4:8], count) 98 enc.PutUint32(buf[4:8], count)
143 datalen := int(count * lengths[ent.datatype]) 99 datalen := int(count * lengths[ent.datatype])
144 if datalen <= 4 { 100 if datalen <= 4 {
145 ent.putData(buf[8:12]) 101 ent.putData(buf[8:12])
(...skipping 17 matching lines...) Expand all
163 } 119 }
164 // The IFD ends with the offset of the next IFD in the file, 120 // The IFD ends with the offset of the next IFD in the file,
165 // or zero if it is the last one (page 14). 121 // or zero if it is the last one (page 14).
166 if err := binary.Write(w, enc, uint32(0)); err != nil { 122 if err := binary.Write(w, enc, uint32(0)); err != nil {
167 return err 123 return err
168 } 124 }
169 _, err := w.Write(parea[:o]) 125 _, err := w.Write(parea[:o])
170 return err 126 return err
171 } 127 }
172 128
173 func (e *encoder) encode(w io.Writer) error { 129 // Encode writes the image m to w in uncompressed RGBA format.
130 func Encode(w io.Writer, m image.Image) error {
131 » b := m.Bounds()
132 » width := b.Dx()
133 » height := b.Dy()
134 » // imageLen is the length of the image data in bytes.
135 » imageLen := width * height * 4
136
174 _, err := io.WriteString(w, leHeader) 137 _, err := io.WriteString(w, leHeader)
175 if err != nil { 138 if err != nil {
176 return err 139 return err
177 } 140 }
178 141
179 » ifdOffset := e.imageLen + 8 // 8 bytes for TIFF header. 142 » ifdOffset := imageLen + 8 // 8 bytes for TIFF header.
bsiegert 2012/03/05 13:21:14 Move the definition of imageLen before this line.
nigeltao 2012/03/05 23:35:04 Done.
180 err = binary.Write(w, enc, uint32(ifdOffset)) 143 err = binary.Write(w, enc, uint32(ifdOffset))
181 if err != nil { 144 if err != nil {
182 return err 145 return err
183 } 146 }
184 » err = e.writeImgData(w) 147 » err = writeImgData(w, m)
185 if err != nil { 148 if err != nil {
186 return err 149 return err
187 } 150 }
188 » return e.writeIFD(w) 151 » return writeIFD(w, ifdOffset, []ifdEntry{
152 » » {tImageWidth, dtShort, []uint32{uint32(width)}},
153 » » {tImageLength, dtShort, []uint32{uint32(height)}},
154 » » {tBitsPerSample, dtShort, []uint32{8, 8, 8, 8}},
155 » » {tCompression, dtShort, []uint32{cNone}},
156 » » {tPhotometricInterpretation, dtShort, []uint32{pRGB}},
157 » » {tStripOffsets, dtLong, []uint32{8}},
158 » » {tSamplesPerPixel, dtShort, []uint32{4}},
159 » » {tRowsPerStrip, dtShort, []uint32{uint32(height)}},
160 » » {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}},
161 » » // There is currently no support for storing the image
162 » » // resolution, so give a bogus value of 72x72 dpi.
163 » » {tXResolution, dtRational, []uint32{72, 1}},
164 » » {tYResolution, dtRational, []uint32{72, 1}},
165 » » {tResolutionUnit, dtShort, []uint32{resPerInch}},
166 » » {tExtraSamples, dtShort, []uint32{1}}, // RGBA.
167 » })
189 } 168 }
190
191 // Encode writes the image m to w in uncompressed RGBA format.
192 func Encode(w io.Writer, m image.Image) error {
193 return newEncoder(m).encode(w)
194 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

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