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
21 func (s YCbCrSubsampleRatio) String() string {
23 case YCbCrSubsampleRatio444:
24 return "YCbCrSubsampleRatio444"
25 case YCbCrSubsampleRatio422:
26 return "YCbCrSubsampleRatio422"
27 case YCbCrSubsampleRatio420:
28 return "YCbCrSubsampleRatio420"
29 case YCbCrSubsampleRatio440:
30 return "YCbCrSubsampleRatio440"
32 return "YCbCrSubsampleRatioUnknown"
35 // YCbCr is an in-memory image of Y'CbCr colors. There is one Y sample per
36 // pixel, but each Cb and Cr sample can span one or more pixels.
37 // YStride is the Y slice index delta between vertically adjacent pixels.
38 // CStride is the Cb and Cr slice index delta between vertically adjacent pixels
39 // that map to separate chroma samples.
40 // It is not an absolute requirement, but YStride and len(Y) are typically
41 // multiples of 8, and:
42 // For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
43 // For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
44 // For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
45 // For 4:4:0, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/2.
50 SubsampleRatio YCbCrSubsampleRatio
54 func (p *YCbCr) ColorModel() color.Model {
55 return color.YCbCrModel
58 func (p *YCbCr) Bounds() Rectangle {
62 func (p *YCbCr) At(x, y int) color.Color {
63 if !(Point{x, y}.In(p.Rect)) {
75 // YOffset returns the index of the first element of Y that corresponds to
76 // the pixel at (x, y).
77 func (p *YCbCr) YOffset(x, y int) int {
78 return (y-p.Rect.Min.Y)*p.YStride + (x - p.Rect.Min.X)
81 // COffset returns the index of the first element of Cb or Cr that corresponds
82 // to the pixel at (x, y).
83 func (p *YCbCr) COffset(x, y int) int {
84 switch p.SubsampleRatio {
85 case YCbCrSubsampleRatio422:
86 return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
87 case YCbCrSubsampleRatio420:
88 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
89 case YCbCrSubsampleRatio440:
90 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
92 // Default to 4:4:4 subsampling.
93 return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
96 // SubImage returns an image representing the portion of the image p visible
97 // through r. The returned value shares pixels with the original image.
98 func (p *YCbCr) SubImage(r Rectangle) Image {
99 r = r.Intersect(p.Rect)
100 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
101 // either r1 or r2 if the intersection is empty. Without explicitly checking for
102 // this, the Pix[i:] expression below can panic.
105 SubsampleRatio: p.SubsampleRatio,
108 yi := p.YOffset(r.Min.X, r.Min.Y)
109 ci := p.COffset(r.Min.X, r.Min.Y)
114 SubsampleRatio: p.SubsampleRatio,
121 func (p *YCbCr) Opaque() bool {
125 // NewYCbCr returns a new YCbCr with the given bounds and subsample ratio.
126 func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
127 w, h, cw, ch := r.Dx(), r.Dy(), 0, 0
128 switch subsampleRatio {
129 case YCbCrSubsampleRatio422:
130 cw = (r.Max.X+1)/2 - r.Min.X/2
132 case YCbCrSubsampleRatio420:
133 cw = (r.Max.X+1)/2 - r.Min.X/2
134 ch = (r.Max.Y+1)/2 - r.Min.Y/2
135 case YCbCrSubsampleRatio440:
137 ch = (r.Max.Y+1)/2 - r.Min.Y/2
139 // Default to 4:4:4 subsampling.
143 b := make([]byte, w*h+2*cw*ch)
146 Cb: b[w*h+0*cw*ch : w*h+1*cw*ch],
147 Cr: b[w*h+1*cw*ch : w*h+2*cw*ch],
148 SubsampleRatio: subsampleRatio,