2018-03-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / go / image / ycbcr.go
blob71c0518a8180e649f7cffd23e89de65e43118b3d
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.
5 package image
7 import (
8 "image/color"
11 // YCbCrSubsampleRatio is the chroma subsample ratio used in a YCbCr image.
12 type YCbCrSubsampleRatio int
14 const (
15 YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
16 YCbCrSubsampleRatio422
17 YCbCrSubsampleRatio420
18 YCbCrSubsampleRatio440
19 YCbCrSubsampleRatio411
20 YCbCrSubsampleRatio410
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"
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.
54 type YCbCr struct {
55 Y, Cb, Cr []uint8
56 YStride int
57 CStride int
58 SubsampleRatio YCbCrSubsampleRatio
59 Rect Rectangle
62 func (p *YCbCr) ColorModel() color.Model {
63 return color.YCbCrModel
66 func (p *YCbCr) Bounds() Rectangle {
67 return p.Rect
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)) {
76 return color.YCbCr{}
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],
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.
119 if r.Empty() {
120 return &YCbCr{
121 SubsampleRatio: p.SubsampleRatio,
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,
137 func (p *YCbCr) Opaque() bool {
138 return true
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 // Default to 4:4:4 subsampling.
161 cw = w
162 ch = h
164 return
167 // NewYCbCr returns a new YCbCr image with the given bounds and subsample
168 // ratio.
169 func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
170 w, h, cw, ch := yCbCrSize(r, subsampleRatio)
171 i0 := w*h + 0*cw*ch
172 i1 := w*h + 1*cw*ch
173 i2 := w*h + 2*cw*ch
174 b := make([]byte, i2)
175 return &YCbCr{
176 Y: b[:i0:i0],
177 Cb: b[i0:i1:i1],
178 Cr: b[i1:i2:i2],
179 SubsampleRatio: subsampleRatio,
180 YStride: w,
181 CStride: cw,
182 Rect: r,
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
188 // embedded YCbCr.
189 type NYCbCrA struct {
190 YCbCr
191 A []uint8
192 AStride int
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{
211 color.YCbCr{
212 Y: p.Y[yi],
213 Cb: p.Cb[ci],
214 Cr: p.Cr[ci],
216 p.A[ai],
220 // AOffset returns the index of the first element of A that corresponds to the
221 // pixel at (x, y).
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.
233 if r.Empty() {
234 return &NYCbCrA{
235 YCbCr: YCbCr{
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)
243 return &NYCbCrA{
244 YCbCr: YCbCr{
245 Y: p.Y[yi:],
246 Cb: p.Cb[ci:],
247 Cr: p.Cr[ci:],
248 SubsampleRatio: p.SubsampleRatio,
249 YStride: p.YStride,
250 CStride: p.CStride,
251 Rect: r,
253 A: p.A[ai:],
254 AStride: p.AStride,
258 // Opaque scans the entire image and reports whether it is fully opaque.
259 func (p *NYCbCrA) Opaque() bool {
260 if p.Rect.Empty() {
261 return true
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] {
266 if a != 0xff {
267 return false
270 i0 += p.AStride
271 i1 += p.AStride
273 return true
276 // NewNYCbCrA returns a new NYCbCrA image with the given bounds and subsample
277 // ratio.
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)
285 return &NYCbCrA{
286 YCbCr: YCbCr{
287 Y: b[:i0:i0],
288 Cb: b[i0:i1:i1],
289 Cr: b[i1:i2:i2],
290 SubsampleRatio: subsampleRatio,
291 YStride: w,
292 CStride: cw,
293 Rect: r,
295 A: b[i2:],
296 AStride: w,