1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
11 // YCbCrSubsampleRatio is the chroma subsample ratio used in a YCbCr image.
12 type YCbCrSubsampleRatio
int
15 YCbCrSubsampleRatio444 YCbCrSubsampleRatio
= iota
16 YCbCrSubsampleRatio422
17 YCbCrSubsampleRatio420
18 YCbCrSubsampleRatio440
19 YCbCrSubsampleRatio411
20 YCbCrSubsampleRatio410
23 func (s YCbCrSubsampleRatio
) String() string {
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"
38 return "YCbCrSubsampleRatioUnknown"
41 // YCbCr is an in-memory image of Y'CbCr colors. There is one Y sample per
42 // pixel, but each Cb and Cr sample can span one or more pixels.
43 // YStride is the Y slice index delta between vertically adjacent pixels.
44 // CStride is the Cb and Cr slice index delta between vertically adjacent pixels
45 // that map to separate chroma samples.
46 // It is not an absolute requirement, but YStride and len(Y) are typically
47 // multiples of 8, and:
48 // For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
49 // For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
50 // For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
51 // For 4:4:0, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/2.
52 // For 4:1:1, CStride == YStride/4 && len(Cb) == len(Cr) == len(Y)/4.
53 // For 4:1:0, CStride == YStride/4 && len(Cb) == len(Cr) == len(Y)/8.
58 SubsampleRatio YCbCrSubsampleRatio
62 func (p
*YCbCr
) ColorModel() color
.Model
{
63 return color
.YCbCrModel
66 func (p
*YCbCr
) Bounds() Rectangle
{
70 func (p
*YCbCr
) At(x
, y
int) color
.Color
{
71 return p
.YCbCrAt(x
, y
)
74 func (p
*YCbCr
) YCbCrAt(x
, y
int) color
.YCbCr
{
75 if !(Point
{x
, y
}.In(p
.Rect
)) {
87 // YOffset returns the index of the first element of Y that corresponds to
88 // the pixel at (x, y).
89 func (p
*YCbCr
) YOffset(x
, y
int) int {
90 return (y
-p
.Rect
.Min
.Y
)*p
.YStride
+ (x
- p
.Rect
.Min
.X
)
93 // COffset returns the index of the first element of Cb or Cr that corresponds
94 // to the pixel at (x, y).
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)
108 // Default to 4:4:4 subsampling.
109 return (y
-p
.Rect
.Min
.Y
)*p
.CStride
+ (x
- p
.Rect
.Min
.X
)
112 // SubImage returns an image representing the portion of the image p visible
113 // through r. The returned value shares pixels with the original image.
114 func (p
*YCbCr
) SubImage(r Rectangle
) Image
{
115 r
= r
.Intersect(p
.Rect
)
116 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
117 // either r1 or r2 if the intersection is empty. Without explicitly checking for
118 // this, the Pix[i:] expression below can panic.
121 SubsampleRatio
: p
.SubsampleRatio
,
124 yi
:= p
.YOffset(r
.Min
.X
, r
.Min
.Y
)
125 ci
:= p
.COffset(r
.Min
.X
, r
.Min
.Y
)
130 SubsampleRatio
: p
.SubsampleRatio
,
137 func (p
*YCbCr
) Opaque() bool {
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
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
:
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
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
160 // Default to 4:4:4 subsampling.
167 // NewYCbCr returns a new YCbCr image with the given bounds and subsample
169 func NewYCbCr(r Rectangle
, subsampleRatio YCbCrSubsampleRatio
) *YCbCr
{
170 w
, h
, cw
, ch
:= yCbCrSize(r
, subsampleRatio
)
174 b
:= make([]byte, i2
)
179 SubsampleRatio
: subsampleRatio
,
186 // NYCbCrA is an in-memory image of non-alpha-premultiplied Y'CbCr-with-alpha
187 // colors. A and AStride are analogous to the Y and YStride fields of the
189 type NYCbCrA
struct {
195 func (p
*NYCbCrA
) ColorModel() color
.Model
{
196 return color
.NYCbCrAModel
199 func (p
*NYCbCrA
) At(x
, y
int) color
.Color
{
200 return p
.NYCbCrAAt(x
, y
)
203 func (p
*NYCbCrA
) NYCbCrAAt(x
, y
int) color
.NYCbCrA
{
204 if !(Point
{X
: x
, Y
: y
}.In(p
.Rect
)) {
205 return color
.NYCbCrA
{}
207 yi
:= p
.YOffset(x
, y
)
208 ci
:= p
.COffset(x
, y
)
209 ai
:= p
.AOffset(x
, y
)
210 return color
.NYCbCrA
{
220 // AOffset returns the index of the first element of A that corresponds to the
222 func (p
*NYCbCrA
) AOffset(x
, y
int) int {
223 return (y
-p
.Rect
.Min
.Y
)*p
.AStride
+ (x
- p
.Rect
.Min
.X
)
226 // SubImage returns an image representing the portion of the image p visible
227 // through r. The returned value shares pixels with the original image.
228 func (p
*NYCbCrA
) SubImage(r Rectangle
) Image
{
229 r
= r
.Intersect(p
.Rect
)
230 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
231 // either r1 or r2 if the intersection is empty. Without explicitly checking for
232 // this, the Pix[i:] expression below can panic.
236 SubsampleRatio
: p
.SubsampleRatio
,
240 yi
:= p
.YOffset(r
.Min
.X
, r
.Min
.Y
)
241 ci
:= p
.COffset(r
.Min
.X
, r
.Min
.Y
)
242 ai
:= p
.AOffset(r
.Min
.X
, r
.Min
.Y
)
248 SubsampleRatio
: p
.SubsampleRatio
,
258 // Opaque scans the entire image and reports whether it is fully opaque.
259 func (p
*NYCbCrA
) Opaque() bool {
263 i0
, i1
:= 0, p
.Rect
.Dx()
264 for y
:= p
.Rect
.Min
.Y
; y
< p
.Rect
.Max
.Y
; y
++ {
265 for _
, a
:= range p
.A
[i0
:i1
] {
276 // NewNYCbCrA returns a new NYCbCrA image with the given bounds and subsample
278 func NewNYCbCrA(r Rectangle
, subsampleRatio YCbCrSubsampleRatio
) *NYCbCrA
{
279 w
, h
, cw
, ch
:= yCbCrSize(r
, subsampleRatio
)
280 i0
:= 1*w
*h
+ 0*cw
*ch
281 i1
:= 1*w
*h
+ 1*cw
*ch
282 i2
:= 1*w
*h
+ 2*cw
*ch
283 i3
:= 2*w
*h
+ 2*cw
*ch
284 b
:= make([]byte, i3
)
290 SubsampleRatio
: subsampleRatio
,