annotate libgo/go/image/ycbcr.go @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // Copyright 2011 The Go Authors. All rights reserved.
kono
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
kono
parents:
diff changeset
3 // license that can be found in the LICENSE file.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 package image
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 import (
kono
parents:
diff changeset
8 "image/color"
kono
parents:
diff changeset
9 )
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 // YCbCrSubsampleRatio is the chroma subsample ratio used in a YCbCr image.
kono
parents:
diff changeset
12 type YCbCrSubsampleRatio int
kono
parents:
diff changeset
13
kono
parents:
diff changeset
14 const (
kono
parents:
diff changeset
15 YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
kono
parents:
diff changeset
16 YCbCrSubsampleRatio422
kono
parents:
diff changeset
17 YCbCrSubsampleRatio420
kono
parents:
diff changeset
18 YCbCrSubsampleRatio440
kono
parents:
diff changeset
19 YCbCrSubsampleRatio411
kono
parents:
diff changeset
20 YCbCrSubsampleRatio410
kono
parents:
diff changeset
21 )
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 func (s YCbCrSubsampleRatio) String() string {
kono
parents:
diff changeset
24 switch s {
kono
parents:
diff changeset
25 case YCbCrSubsampleRatio444:
kono
parents:
diff changeset
26 return "YCbCrSubsampleRatio444"
kono
parents:
diff changeset
27 case YCbCrSubsampleRatio422:
kono
parents:
diff changeset
28 return "YCbCrSubsampleRatio422"
kono
parents:
diff changeset
29 case YCbCrSubsampleRatio420:
kono
parents:
diff changeset
30 return "YCbCrSubsampleRatio420"
kono
parents:
diff changeset
31 case YCbCrSubsampleRatio440:
kono
parents:
diff changeset
32 return "YCbCrSubsampleRatio440"
kono
parents:
diff changeset
33 case YCbCrSubsampleRatio411:
kono
parents:
diff changeset
34 return "YCbCrSubsampleRatio411"
kono
parents:
diff changeset
35 case YCbCrSubsampleRatio410:
kono
parents:
diff changeset
36 return "YCbCrSubsampleRatio410"
kono
parents:
diff changeset
37 }
kono
parents:
diff changeset
38 return "YCbCrSubsampleRatioUnknown"
kono
parents:
diff changeset
39 }
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 // YCbCr is an in-memory image of Y'CbCr colors. There is one Y sample per
kono
parents:
diff changeset
42 // pixel, but each Cb and Cr sample can span one or more pixels.
kono
parents:
diff changeset
43 // YStride is the Y slice index delta between vertically adjacent pixels.
kono
parents:
diff changeset
44 // CStride is the Cb and Cr slice index delta between vertically adjacent pixels
kono
parents:
diff changeset
45 // that map to separate chroma samples.
kono
parents:
diff changeset
46 // It is not an absolute requirement, but YStride and len(Y) are typically
kono
parents:
diff changeset
47 // multiples of 8, and:
kono
parents:
diff changeset
48 // For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
kono
parents:
diff changeset
49 // For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
kono
parents:
diff changeset
50 // For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
kono
parents:
diff changeset
51 // For 4:4:0, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/2.
kono
parents:
diff changeset
52 // For 4:1:1, CStride == YStride/4 && len(Cb) == len(Cr) == len(Y)/4.
kono
parents:
diff changeset
53 // For 4:1:0, CStride == YStride/4 && len(Cb) == len(Cr) == len(Y)/8.
kono
parents:
diff changeset
54 type YCbCr struct {
kono
parents:
diff changeset
55 Y, Cb, Cr []uint8
kono
parents:
diff changeset
56 YStride int
kono
parents:
diff changeset
57 CStride int
kono
parents:
diff changeset
58 SubsampleRatio YCbCrSubsampleRatio
kono
parents:
diff changeset
59 Rect Rectangle
kono
parents:
diff changeset
60 }
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 func (p *YCbCr) ColorModel() color.Model {
kono
parents:
diff changeset
63 return color.YCbCrModel
kono
parents:
diff changeset
64 }
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 func (p *YCbCr) Bounds() Rectangle {
kono
parents:
diff changeset
67 return p.Rect
kono
parents:
diff changeset
68 }
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 func (p *YCbCr) At(x, y int) color.Color {
kono
parents:
diff changeset
71 return p.YCbCrAt(x, y)
kono
parents:
diff changeset
72 }
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr {
kono
parents:
diff changeset
75 if !(Point{x, y}.In(p.Rect)) {
kono
parents:
diff changeset
76 return color.YCbCr{}
kono
parents:
diff changeset
77 }
kono
parents:
diff changeset
78 yi := p.YOffset(x, y)
kono
parents:
diff changeset
79 ci := p.COffset(x, y)
kono
parents:
diff changeset
80 return color.YCbCr{
kono
parents:
diff changeset
81 p.Y[yi],
kono
parents:
diff changeset
82 p.Cb[ci],
kono
parents:
diff changeset
83 p.Cr[ci],
kono
parents:
diff changeset
84 }
kono
parents:
diff changeset
85 }
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 // YOffset returns the index of the first element of Y that corresponds to
kono
parents:
diff changeset
88 // the pixel at (x, y).
kono
parents:
diff changeset
89 func (p *YCbCr) YOffset(x, y int) int {
kono
parents:
diff changeset
90 return (y-p.Rect.Min.Y)*p.YStride + (x - p.Rect.Min.X)
kono
parents:
diff changeset
91 }
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 // COffset returns the index of the first element of Cb or Cr that corresponds
kono
parents:
diff changeset
94 // to the pixel at (x, y).
kono
parents:
diff changeset
95 func (p *YCbCr) COffset(x, y int) int {
kono
parents:
diff changeset
96 switch p.SubsampleRatio {
kono
parents:
diff changeset
97 case YCbCrSubsampleRatio422:
kono
parents:
diff changeset
98 return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
kono
parents:
diff changeset
99 case YCbCrSubsampleRatio420:
kono
parents:
diff changeset
100 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
kono
parents:
diff changeset
101 case YCbCrSubsampleRatio440:
kono
parents:
diff changeset
102 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
kono
parents:
diff changeset
103 case YCbCrSubsampleRatio411:
kono
parents:
diff changeset
104 return (y-p.Rect.Min.Y)*p.CStride + (x/4 - p.Rect.Min.X/4)
kono
parents:
diff changeset
105 case YCbCrSubsampleRatio410:
kono
parents:
diff changeset
106 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/4 - p.Rect.Min.X/4)
kono
parents:
diff changeset
107 }
kono
parents:
diff changeset
108 // Default to 4:4:4 subsampling.
kono
parents:
diff changeset
109 return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
kono
parents:
diff changeset
110 }
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 // SubImage returns an image representing the portion of the image p visible
kono
parents:
diff changeset
113 // through r. The returned value shares pixels with the original image.
kono
parents:
diff changeset
114 func (p *YCbCr) SubImage(r Rectangle) Image {
kono
parents:
diff changeset
115 r = r.Intersect(p.Rect)
kono
parents:
diff changeset
116 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
kono
parents:
diff changeset
117 // either r1 or r2 if the intersection is empty. Without explicitly checking for
kono
parents:
diff changeset
118 // this, the Pix[i:] expression below can panic.
kono
parents:
diff changeset
119 if r.Empty() {
kono
parents:
diff changeset
120 return &YCbCr{
kono
parents:
diff changeset
121 SubsampleRatio: p.SubsampleRatio,
kono
parents:
diff changeset
122 }
kono
parents:
diff changeset
123 }
kono
parents:
diff changeset
124 yi := p.YOffset(r.Min.X, r.Min.Y)
kono
parents:
diff changeset
125 ci := p.COffset(r.Min.X, r.Min.Y)
kono
parents:
diff changeset
126 return &YCbCr{
kono
parents:
diff changeset
127 Y: p.Y[yi:],
kono
parents:
diff changeset
128 Cb: p.Cb[ci:],
kono
parents:
diff changeset
129 Cr: p.Cr[ci:],
kono
parents:
diff changeset
130 SubsampleRatio: p.SubsampleRatio,
kono
parents:
diff changeset
131 YStride: p.YStride,
kono
parents:
diff changeset
132 CStride: p.CStride,
kono
parents:
diff changeset
133 Rect: r,
kono
parents:
diff changeset
134 }
kono
parents:
diff changeset
135 }
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 func (p *YCbCr) Opaque() bool {
kono
parents:
diff changeset
138 return true
kono
parents:
diff changeset
139 }
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 func yCbCrSize(r Rectangle, subsampleRatio YCbCrSubsampleRatio) (w, h, cw, ch int) {
kono
parents:
diff changeset
142 w, h = r.Dx(), r.Dy()
kono
parents:
diff changeset
143 switch subsampleRatio {
kono
parents:
diff changeset
144 case YCbCrSubsampleRatio422:
kono
parents:
diff changeset
145 cw = (r.Max.X+1)/2 - r.Min.X/2
kono
parents:
diff changeset
146 ch = h
kono
parents:
diff changeset
147 case YCbCrSubsampleRatio420:
kono
parents:
diff changeset
148 cw = (r.Max.X+1)/2 - r.Min.X/2
kono
parents:
diff changeset
149 ch = (r.Max.Y+1)/2 - r.Min.Y/2
kono
parents:
diff changeset
150 case YCbCrSubsampleRatio440:
kono
parents:
diff changeset
151 cw = w
kono
parents:
diff changeset
152 ch = (r.Max.Y+1)/2 - r.Min.Y/2
kono
parents:
diff changeset
153 case YCbCrSubsampleRatio411:
kono
parents:
diff changeset
154 cw = (r.Max.X+3)/4 - r.Min.X/4
kono
parents:
diff changeset
155 ch = h
kono
parents:
diff changeset
156 case YCbCrSubsampleRatio410:
kono
parents:
diff changeset
157 cw = (r.Max.X+3)/4 - r.Min.X/4
kono
parents:
diff changeset
158 ch = (r.Max.Y+1)/2 - r.Min.Y/2
kono
parents:
diff changeset
159 default:
kono
parents:
diff changeset
160 // Default to 4:4:4 subsampling.
kono
parents:
diff changeset
161 cw = w
kono
parents:
diff changeset
162 ch = h
kono
parents:
diff changeset
163 }
kono
parents:
diff changeset
164 return
kono
parents:
diff changeset
165 }
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 // NewYCbCr returns a new YCbCr image with the given bounds and subsample
kono
parents:
diff changeset
168 // ratio.
kono
parents:
diff changeset
169 func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
kono
parents:
diff changeset
170 w, h, cw, ch := yCbCrSize(r, subsampleRatio)
kono
parents:
diff changeset
171 i0 := w*h + 0*cw*ch
kono
parents:
diff changeset
172 i1 := w*h + 1*cw*ch
kono
parents:
diff changeset
173 i2 := w*h + 2*cw*ch
kono
parents:
diff changeset
174 b := make([]byte, i2)
kono
parents:
diff changeset
175 return &YCbCr{
kono
parents:
diff changeset
176 Y: b[:i0:i0],
kono
parents:
diff changeset
177 Cb: b[i0:i1:i1],
kono
parents:
diff changeset
178 Cr: b[i1:i2:i2],
kono
parents:
diff changeset
179 SubsampleRatio: subsampleRatio,
kono
parents:
diff changeset
180 YStride: w,
kono
parents:
diff changeset
181 CStride: cw,
kono
parents:
diff changeset
182 Rect: r,
kono
parents:
diff changeset
183 }
kono
parents:
diff changeset
184 }
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 // NYCbCrA is an in-memory image of non-alpha-premultiplied Y'CbCr-with-alpha
kono
parents:
diff changeset
187 // colors. A and AStride are analogous to the Y and YStride fields of the
kono
parents:
diff changeset
188 // embedded YCbCr.
kono
parents:
diff changeset
189 type NYCbCrA struct {
kono
parents:
diff changeset
190 YCbCr
kono
parents:
diff changeset
191 A []uint8
kono
parents:
diff changeset
192 AStride int
kono
parents:
diff changeset
193 }
kono
parents:
diff changeset
194
kono
parents:
diff changeset
195 func (p *NYCbCrA) ColorModel() color.Model {
kono
parents:
diff changeset
196 return color.NYCbCrAModel
kono
parents:
diff changeset
197 }
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 func (p *NYCbCrA) At(x, y int) color.Color {
kono
parents:
diff changeset
200 return p.NYCbCrAAt(x, y)
kono
parents:
diff changeset
201 }
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 func (p *NYCbCrA) NYCbCrAAt(x, y int) color.NYCbCrA {
kono
parents:
diff changeset
204 if !(Point{X: x, Y: y}.In(p.Rect)) {
kono
parents:
diff changeset
205 return color.NYCbCrA{}
kono
parents:
diff changeset
206 }
kono
parents:
diff changeset
207 yi := p.YOffset(x, y)
kono
parents:
diff changeset
208 ci := p.COffset(x, y)
kono
parents:
diff changeset
209 ai := p.AOffset(x, y)
kono
parents:
diff changeset
210 return color.NYCbCrA{
kono
parents:
diff changeset
211 color.YCbCr{
kono
parents:
diff changeset
212 Y: p.Y[yi],
kono
parents:
diff changeset
213 Cb: p.Cb[ci],
kono
parents:
diff changeset
214 Cr: p.Cr[ci],
kono
parents:
diff changeset
215 },
kono
parents:
diff changeset
216 p.A[ai],
kono
parents:
diff changeset
217 }
kono
parents:
diff changeset
218 }
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 // AOffset returns the index of the first element of A that corresponds to the
kono
parents:
diff changeset
221 // pixel at (x, y).
kono
parents:
diff changeset
222 func (p *NYCbCrA) AOffset(x, y int) int {
kono
parents:
diff changeset
223 return (y-p.Rect.Min.Y)*p.AStride + (x - p.Rect.Min.X)
kono
parents:
diff changeset
224 }
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 // SubImage returns an image representing the portion of the image p visible
kono
parents:
diff changeset
227 // through r. The returned value shares pixels with the original image.
kono
parents:
diff changeset
228 func (p *NYCbCrA) SubImage(r Rectangle) Image {
kono
parents:
diff changeset
229 r = r.Intersect(p.Rect)
kono
parents:
diff changeset
230 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
kono
parents:
diff changeset
231 // either r1 or r2 if the intersection is empty. Without explicitly checking for
kono
parents:
diff changeset
232 // this, the Pix[i:] expression below can panic.
kono
parents:
diff changeset
233 if r.Empty() {
kono
parents:
diff changeset
234 return &NYCbCrA{
kono
parents:
diff changeset
235 YCbCr: YCbCr{
kono
parents:
diff changeset
236 SubsampleRatio: p.SubsampleRatio,
kono
parents:
diff changeset
237 },
kono
parents:
diff changeset
238 }
kono
parents:
diff changeset
239 }
kono
parents:
diff changeset
240 yi := p.YOffset(r.Min.X, r.Min.Y)
kono
parents:
diff changeset
241 ci := p.COffset(r.Min.X, r.Min.Y)
kono
parents:
diff changeset
242 ai := p.AOffset(r.Min.X, r.Min.Y)
kono
parents:
diff changeset
243 return &NYCbCrA{
kono
parents:
diff changeset
244 YCbCr: YCbCr{
kono
parents:
diff changeset
245 Y: p.Y[yi:],
kono
parents:
diff changeset
246 Cb: p.Cb[ci:],
kono
parents:
diff changeset
247 Cr: p.Cr[ci:],
kono
parents:
diff changeset
248 SubsampleRatio: p.SubsampleRatio,
kono
parents:
diff changeset
249 YStride: p.YStride,
kono
parents:
diff changeset
250 CStride: p.CStride,
kono
parents:
diff changeset
251 Rect: r,
kono
parents:
diff changeset
252 },
kono
parents:
diff changeset
253 A: p.A[ai:],
kono
parents:
diff changeset
254 AStride: p.AStride,
kono
parents:
diff changeset
255 }
kono
parents:
diff changeset
256 }
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 // Opaque scans the entire image and reports whether it is fully opaque.
kono
parents:
diff changeset
259 func (p *NYCbCrA) Opaque() bool {
kono
parents:
diff changeset
260 if p.Rect.Empty() {
kono
parents:
diff changeset
261 return true
kono
parents:
diff changeset
262 }
kono
parents:
diff changeset
263 i0, i1 := 0, p.Rect.Dx()
kono
parents:
diff changeset
264 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
kono
parents:
diff changeset
265 for _, a := range p.A[i0:i1] {
kono
parents:
diff changeset
266 if a != 0xff {
kono
parents:
diff changeset
267 return false
kono
parents:
diff changeset
268 }
kono
parents:
diff changeset
269 }
kono
parents:
diff changeset
270 i0 += p.AStride
kono
parents:
diff changeset
271 i1 += p.AStride
kono
parents:
diff changeset
272 }
kono
parents:
diff changeset
273 return true
kono
parents:
diff changeset
274 }
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 // NewNYCbCrA returns a new NYCbCrA image with the given bounds and subsample
kono
parents:
diff changeset
277 // ratio.
kono
parents:
diff changeset
278 func NewNYCbCrA(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *NYCbCrA {
kono
parents:
diff changeset
279 w, h, cw, ch := yCbCrSize(r, subsampleRatio)
kono
parents:
diff changeset
280 i0 := 1*w*h + 0*cw*ch
kono
parents:
diff changeset
281 i1 := 1*w*h + 1*cw*ch
kono
parents:
diff changeset
282 i2 := 1*w*h + 2*cw*ch
kono
parents:
diff changeset
283 i3 := 2*w*h + 2*cw*ch
kono
parents:
diff changeset
284 b := make([]byte, i3)
kono
parents:
diff changeset
285 return &NYCbCrA{
kono
parents:
diff changeset
286 YCbCr: YCbCr{
kono
parents:
diff changeset
287 Y: b[:i0:i0],
kono
parents:
diff changeset
288 Cb: b[i0:i1:i1],
kono
parents:
diff changeset
289 Cr: b[i1:i2:i2],
kono
parents:
diff changeset
290 SubsampleRatio: subsampleRatio,
kono
parents:
diff changeset
291 YStride: w,
kono
parents:
diff changeset
292 CStride: cw,
kono
parents:
diff changeset
293 Rect: r,
kono
parents:
diff changeset
294 },
kono
parents:
diff changeset
295 A: b[i2:],
kono
parents:
diff changeset
296 AStride: w,
kono
parents:
diff changeset
297 }
kono
parents:
diff changeset
298 }