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

Delta Between Two Patch Sets: bmp/writer.go

Issue 13407045: code review 13407045: go.image/bmp: add Encode (Closed)
Left Patch Set: diff -r 0788e15aed14 https://code.google.com/p/go.image Created 11 years, 6 months ago
Right Patch Set: diff -r 0788e15aed14 https://code.google.com/p/go.image Created 11 years, 6 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:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « bmp/reader.go ('k') | bmp/writer_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2013 The Go Authors. All rights reserved. 1 // Copyright 2013 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 bmp 5 package bmp
6 6
7 import ( 7 import (
8 "encoding/binary" 8 "encoding/binary"
9 "image" 9 "image"
10 "io" 10 "io"
(...skipping 10 matching lines...) Expand all
21 colorPlane uint16 21 colorPlane uint16
22 bpp uint16 22 bpp uint16
23 compression uint32 23 compression uint32
24 imageSize uint32 24 imageSize uint32
25 xPixelsPerMeter uint32 25 xPixelsPerMeter uint32
26 yPixelsPerMeter uint32 26 yPixelsPerMeter uint32
27 colorUse uint32 27 colorUse uint32
28 colorImportant uint32 28 colorImportant uint32
29 } 29 }
30 30
31 func encodePaletted(w io.Writer, m image.Image, pix []uint8, stride, step int) e rror { 31 func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
32 » if stride < step { 32 » var padding []byte
33 » » padding := make([]byte, step-stride) 33 » if dx < step {
34 » » for y := m.Bounds().Dy() - 1; y >= 0; y-- { 34 » » padding = make([]byte, step-dx)
35 » » » min := y*stride + 0 35 » }
36 » » » max := y*stride + stride 36 » for y := dy - 1; y >= 0; y-- {
nigeltao 2013/09/09 07:18:26 This isn't right. Again, this can panic if width <
chai2010 2013/09/09 07:42:41 Done.
37 » » » if _, err := w.Write(pix[min:max]); err != nil { 37 » » min := y*stride + 0
38 » » » » return err 38 » » max := y*stride + dx
39 » » » } 39 » » if _, err := w.Write(pix[min:max]); err != nil {
40 » » » return err
41 » » }
42 » » if padding != nil {
40 if _, err := w.Write(padding); err != nil { 43 if _, err := w.Write(padding); err != nil {
41 return err
42 }
43 }
44 } else {
45 for y := m.Bounds().Dy() - 1; y >= 0; y-- {
46 min := y*stride + 0
47 max := y*stride + step
nigeltao 2013/09/09 07:18:26 This will panic if width < step && step <= stride.
chai2010 2013/09/09 07:42:41 Done.
48 if _, err := w.Write(pix[min:max]); err != nil {
49 return err 44 return err
50 } 45 }
51 } 46 }
52 } 47 }
53 return nil 48 return nil
54 } 49 }
55 50
56 func encodeRGBA(w io.Writer, m image.Image, pix []uint8, stride, step int) error { 51 func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
57 buf := make([]byte, step) 52 buf := make([]byte, step)
58 » for y := m.Bounds().Dy() - 1; y >= 0; y-- { 53 » for y := dy - 1; y >= 0; y-- {
59 min := y*stride + 0 54 min := y*stride + 0
60 » » max := y*stride + m.Bounds().Dx()*4 55 » » max := y*stride + dx*4
61 off := 0 56 off := 0
62 for i := min; i < max; i += 4 { 57 for i := min; i < max; i += 4 {
63 buf[off+2] = pix[i+0] 58 buf[off+2] = pix[i+0]
64 buf[off+1] = pix[i+1] 59 buf[off+1] = pix[i+1]
65 buf[off+0] = pix[i+2] 60 buf[off+0] = pix[i+2]
66 off += 3 61 off += 3
67 } 62 }
68 if _, err := w.Write(buf); err != nil { 63 if _, err := w.Write(buf); err != nil {
69 return err 64 return err
70 } 65 }
71 } 66 }
72 return nil 67 return nil
73 } 68 }
74 69
75 func encode(w io.Writer, m image.Image, step int) error { 70 func encode(w io.Writer, m image.Image, step int) error {
71 b := m.Bounds()
76 buf := make([]byte, step) 72 buf := make([]byte, step)
77 » for y := m.Bounds().Dy() - 1; y >= 0; y-- { 73 » for y := b.Max.Y - 1; y >= b.Min.Y; y-- {
78 off := 0 74 off := 0
79 » » for x := 0; x < m.Bounds().Dx(); x++ { 75 » » for x := b.Min.X; x < b.Max.X; x++ {
80 r, g, b, _ := m.At(x, y).RGBA() 76 r, g, b, _ := m.At(x, y).RGBA()
81 buf[off+2] = byte(r >> 8) 77 buf[off+2] = byte(r >> 8)
82 buf[off+1] = byte(g >> 8) 78 buf[off+1] = byte(g >> 8)
83 buf[off+0] = byte(b >> 8) 79 buf[off+0] = byte(b >> 8)
84 off += 3 80 off += 3
85 } 81 }
86 if _, err := w.Write(buf); err != nil { 82 if _, err := w.Write(buf); err != nil {
87 return err 83 return err
88 } 84 }
89 } 85 }
90 return nil 86 return nil
91 } 87 }
92 88
93 // Encode writes the image m to w in BMP format. 89 // Encode writes the image m to w in BMP format.
94 func Encode(w io.Writer, m image.Image) error { 90 func Encode(w io.Writer, m image.Image) error {
91 d := m.Bounds().Size()
95 h := &header{ 92 h := &header{
96 sigBM: [2]byte{'B', 'M'}, 93 sigBM: [2]byte{'B', 'M'},
97 fileSize: 14 + 40, 94 fileSize: 14 + 40,
98 pixOffset: 14 + 40, 95 pixOffset: 14 + 40,
99 dibHeaderSize: 40, 96 dibHeaderSize: 40,
100 » » width: uint32(m.Bounds().Dx()), 97 » » width: uint32(d.X),
101 » » height: uint32(m.Bounds().Dy()), 98 » » height: uint32(d.Y),
102 colorPlane: 1, 99 colorPlane: 1,
103 } 100 }
104 101
105 var step int 102 var step int
106 var palette []byte 103 var palette []byte
107 switch m := m.(type) { 104 switch m := m.(type) {
108 case *image.Gray: 105 case *image.Gray:
109 » » step = (m.Bounds().Dx() + 3) &^ 3 106 » » step = (d.X + 3) &^ 3
110 palette = make([]byte, 1024) 107 palette = make([]byte, 1024)
111 for i := 0; i < 256; i++ { 108 for i := 0; i < 256; i++ {
112 palette[i*4+0] = uint8(i) 109 palette[i*4+0] = uint8(i)
113 palette[i*4+1] = uint8(i) 110 palette[i*4+1] = uint8(i)
114 palette[i*4+2] = uint8(i) 111 palette[i*4+2] = uint8(i)
115 palette[i*4+3] = 0xFF 112 palette[i*4+3] = 0xFF
116 } 113 }
117 » » h.imageSize = uint32(m.Bounds().Dy() * step) 114 » » h.imageSize = uint32(d.Y * step)
118 h.fileSize += uint32(len(palette)) + h.imageSize 115 h.fileSize += uint32(len(palette)) + h.imageSize
119 h.pixOffset += uint32(len(palette)) 116 h.pixOffset += uint32(len(palette))
120 h.bpp = 8 117 h.bpp = 8
121 118
122 case *image.Paletted: 119 case *image.Paletted:
123 » » step = (m.Bounds().Dx() + 3) &^ 3 120 » » step = (d.X + 3) &^ 3
124 palette = make([]byte, 1024) 121 palette = make([]byte, 1024)
125 for i := 0; i < len(m.Palette) && i < 256; i++ { 122 for i := 0; i < len(m.Palette) && i < 256; i++ {
126 r, g, b, _ := m.Palette[i].RGBA() 123 r, g, b, _ := m.Palette[i].RGBA()
127 palette[i*4+0] = uint8(b >> 8) 124 palette[i*4+0] = uint8(b >> 8)
128 palette[i*4+1] = uint8(g >> 8) 125 palette[i*4+1] = uint8(g >> 8)
129 palette[i*4+2] = uint8(r >> 8) 126 palette[i*4+2] = uint8(r >> 8)
130 palette[i*4+3] = 0xFF 127 palette[i*4+3] = 0xFF
131 } 128 }
132 » » h.imageSize = uint32(m.Bounds().Dy() * step) 129 » » h.imageSize = uint32(d.Y * step)
133 h.fileSize += uint32(len(palette)) + h.imageSize 130 h.fileSize += uint32(len(palette)) + h.imageSize
134 h.pixOffset += uint32(len(palette)) 131 h.pixOffset += uint32(len(palette))
135 h.bpp = 8 132 h.bpp = 8
136 default: 133 default:
137 » » step = (3*m.Bounds().Dx() + 3) &^ 3 134 » » step = (3*d.X + 3) &^ 3
138 » » h.imageSize = uint32(m.Bounds().Dy() * step) 135 » » h.imageSize = uint32(d.Y * step)
139 h.fileSize += h.imageSize 136 h.fileSize += h.imageSize
140 h.bpp = 24 137 h.bpp = 24
141 } 138 }
142 139
143 if err := binary.Write(w, binary.LittleEndian, h); err != nil { 140 if err := binary.Write(w, binary.LittleEndian, h); err != nil {
144 return err 141 return err
145 } 142 }
146 » if err := binary.Write(w, binary.LittleEndian, palette); err != nil { 143 » if palette != nil {
nigeltao 2013/09/09 07:18:26 Guard this by if palette != nil
chai2010 2013/09/09 07:42:41 Done.
147 » » return err 144 » » if err := binary.Write(w, binary.LittleEndian, palette); err != nil {
145 » » » return err
146 » » }
148 } 147 }
149 148
150 switch m := m.(type) { 149 switch m := m.(type) {
151 case *image.Gray: 150 case *image.Gray:
152 » » return encodePaletted(w, m, m.Pix, m.Stride, step) 151 » » return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
153 case *image.Paletted: 152 case *image.Paletted:
154 » » return encodePaletted(w, m, m.Pix, m.Stride, step) 153 » » return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
155 case *image.RGBA: 154 case *image.RGBA:
156 » » return encodeRGBA(w, m, m.Pix, m.Stride, step) 155 » » return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step)
157 } 156 }
158 return encode(w, m, step) 157 return encode(w, m, step)
159 } 158 }
LEFTRIGHT

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