Source file
src/image/ycbcr.go
Documentation: image
1
2
3
4
5 package image
6
7 import (
8 "image/color"
9 )
10
11
12 type YCbCrSubsampleRatio int
13
14 const (
15 YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
16 YCbCrSubsampleRatio422
17 YCbCrSubsampleRatio420
18 YCbCrSubsampleRatio440
19 YCbCrSubsampleRatio411
20 YCbCrSubsampleRatio410
21 )
22
23 func (s YCbCrSubsampleRatio) String() string {
24 switch s {
25 case YCbCrSubsampleRatio444:
26 return "YCbCrSubsampleRatio444"
27 case YCbCrSubsampleRatio422:
28 return "YCbCrSubsampleRatio422"
29 case YCbCrSubsampleRatio420:
30 return "YCbCrSubsampleRatio420"
31 case YCbCrSubsampleRatio440:
32 return "YCbCrSubsampleRatio440"
33 case YCbCrSubsampleRatio411:
34 return "YCbCrSubsampleRatio411"
35 case YCbCrSubsampleRatio410:
36 return "YCbCrSubsampleRatio410"
37 }
38 return "YCbCrSubsampleRatioUnknown"
39 }
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 type YCbCr struct {
55 Y, Cb, Cr []uint8
56 YStride int
57 CStride int
58 SubsampleRatio YCbCrSubsampleRatio
59 Rect Rectangle
60 }
61
62 func (p *YCbCr) ColorModel() color.Model {
63 return color.YCbCrModel
64 }
65
66 func (p *YCbCr) Bounds() Rectangle {
67 return p.Rect
68 }
69
70 func (p *YCbCr) At(x, y int) color.Color {
71 return p.YCbCrAt(x, y)
72 }
73
74 func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr {
75 if !(Point{x, y}.In(p.Rect)) {
76 return color.YCbCr{}
77 }
78 yi := p.YOffset(x, y)
79 ci := p.COffset(x, y)
80 return color.YCbCr{
81 p.Y[yi],
82 p.Cb[ci],
83 p.Cr[ci],
84 }
85 }
86
87
88
89 func (p *YCbCr) YOffset(x, y int) int {
90 return (y-p.Rect.Min.Y)*p.YStride + (x - p.Rect.Min.X)
91 }
92
93
94
95 func (p *YCbCr) COffset(x, y int) int {
96 switch p.SubsampleRatio {
97 case YCbCrSubsampleRatio422:
98 return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
99 case YCbCrSubsampleRatio420:
100 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
101 case YCbCrSubsampleRatio440:
102 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
103 case YCbCrSubsampleRatio411:
104 return (y-p.Rect.Min.Y)*p.CStride + (x/4 - p.Rect.Min.X/4)
105 case YCbCrSubsampleRatio410:
106 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/4 - p.Rect.Min.X/4)
107 }
108
109 return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
110 }
111
112
113
114 func (p *YCbCr) SubImage(r Rectangle) Image {
115 r = r.Intersect(p.Rect)
116
117
118
119 if r.Empty() {
120 return &YCbCr{
121 SubsampleRatio: p.SubsampleRatio,
122 }
123 }
124 yi := p.YOffset(r.Min.X, r.Min.Y)
125 ci := p.COffset(r.Min.X, r.Min.Y)
126 return &YCbCr{
127 Y: p.Y[yi:],
128 Cb: p.Cb[ci:],
129 Cr: p.Cr[ci:],
130 SubsampleRatio: p.SubsampleRatio,
131 YStride: p.YStride,
132 CStride: p.CStride,
133 Rect: r,
134 }
135 }
136
137 func (p *YCbCr) Opaque() bool {
138 return true
139 }
140
141 func yCbCrSize(r Rectangle, subsampleRatio YCbCrSubsampleRatio) (w, h, cw, ch int) {
142 w, h = r.Dx(), r.Dy()
143 switch subsampleRatio {
144 case YCbCrSubsampleRatio422:
145 cw = (r.Max.X+1)/2 - r.Min.X/2
146 ch = h
147 case YCbCrSubsampleRatio420:
148 cw = (r.Max.X+1)/2 - r.Min.X/2
149 ch = (r.Max.Y+1)/2 - r.Min.Y/2
150 case YCbCrSubsampleRatio440:
151 cw = w
152 ch = (r.Max.Y+1)/2 - r.Min.Y/2
153 case YCbCrSubsampleRatio411:
154 cw = (r.Max.X+3)/4 - r.Min.X/4
155 ch = h
156 case YCbCrSubsampleRatio410:
157 cw = (r.Max.X+3)/4 - r.Min.X/4
158 ch = (r.Max.Y+1)/2 - r.Min.Y/2
159 default:
160
161 cw = w
162 ch = h
163 }
164 return
165 }
166
167
168
169 func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
170 w, h, cw, ch := yCbCrSize(r, subsampleRatio)
171
172
173 totalLength := add2NonNeg(
174 mul3NonNeg(1, w, h),
175 mul3NonNeg(2, cw, ch),
176 )
177 if totalLength < 0 {
178 panic("image: NewYCbCr Rectangle has huge or negative dimensions")
179 }
180
181 i0 := w*h + 0*cw*ch
182 i1 := w*h + 1*cw*ch
183 i2 := w*h + 2*cw*ch
184 b := make([]byte, i2)
185 return &YCbCr{
186 Y: b[:i0:i0],
187 Cb: b[i0:i1:i1],
188 Cr: b[i1:i2:i2],
189 SubsampleRatio: subsampleRatio,
190 YStride: w,
191 CStride: cw,
192 Rect: r,
193 }
194 }
195
196
197
198
199 type NYCbCrA struct {
200 YCbCr
201 A []uint8
202 AStride int
203 }
204
205 func (p *NYCbCrA) ColorModel() color.Model {
206 return color.NYCbCrAModel
207 }
208
209 func (p *NYCbCrA) At(x, y int) color.Color {
210 return p.NYCbCrAAt(x, y)
211 }
212
213 func (p *NYCbCrA) NYCbCrAAt(x, y int) color.NYCbCrA {
214 if !(Point{X: x, Y: y}.In(p.Rect)) {
215 return color.NYCbCrA{}
216 }
217 yi := p.YOffset(x, y)
218 ci := p.COffset(x, y)
219 ai := p.AOffset(x, y)
220 return color.NYCbCrA{
221 color.YCbCr{
222 Y: p.Y[yi],
223 Cb: p.Cb[ci],
224 Cr: p.Cr[ci],
225 },
226 p.A[ai],
227 }
228 }
229
230
231
232 func (p *NYCbCrA) AOffset(x, y int) int {
233 return (y-p.Rect.Min.Y)*p.AStride + (x - p.Rect.Min.X)
234 }
235
236
237
238 func (p *NYCbCrA) SubImage(r Rectangle) Image {
239 r = r.Intersect(p.Rect)
240
241
242
243 if r.Empty() {
244 return &NYCbCrA{
245 YCbCr: YCbCr{
246 SubsampleRatio: p.SubsampleRatio,
247 },
248 }
249 }
250 yi := p.YOffset(r.Min.X, r.Min.Y)
251 ci := p.COffset(r.Min.X, r.Min.Y)
252 ai := p.AOffset(r.Min.X, r.Min.Y)
253 return &NYCbCrA{
254 YCbCr: YCbCr{
255 Y: p.Y[yi:],
256 Cb: p.Cb[ci:],
257 Cr: p.Cr[ci:],
258 SubsampleRatio: p.SubsampleRatio,
259 YStride: p.YStride,
260 CStride: p.CStride,
261 Rect: r,
262 },
263 A: p.A[ai:],
264 AStride: p.AStride,
265 }
266 }
267
268
269 func (p *NYCbCrA) Opaque() bool {
270 if p.Rect.Empty() {
271 return true
272 }
273 i0, i1 := 0, p.Rect.Dx()
274 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
275 for _, a := range p.A[i0:i1] {
276 if a != 0xff {
277 return false
278 }
279 }
280 i0 += p.AStride
281 i1 += p.AStride
282 }
283 return true
284 }
285
286
287
288 func NewNYCbCrA(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *NYCbCrA {
289 w, h, cw, ch := yCbCrSize(r, subsampleRatio)
290
291
292 totalLength := add2NonNeg(
293 mul3NonNeg(2, w, h),
294 mul3NonNeg(2, cw, ch),
295 )
296 if totalLength < 0 {
297 panic("image: NewNYCbCrA Rectangle has huge or negative dimension")
298 }
299
300 i0 := 1*w*h + 0*cw*ch
301 i1 := 1*w*h + 1*cw*ch
302 i2 := 1*w*h + 2*cw*ch
303 i3 := 2*w*h + 2*cw*ch
304 b := make([]byte, i3)
305 return &NYCbCrA{
306 YCbCr: YCbCr{
307 Y: b[:i0:i0],
308 Cb: b[i0:i1:i1],
309 Cr: b[i1:i2:i2],
310 SubsampleRatio: subsampleRatio,
311 YStride: w,
312 CStride: cw,
313 Rect: r,
314 },
315 A: b[i2:],
316 AStride: w,
317 }
318 }
319
View as plain text