5b73bef789581e21a684362dd8deec35ab0b3dfc
[platform/upstream/gcc.git] / libgo / go / image / ycbcr.go
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.
4
5 package image
6
7 import (
8         "image/color"
9 )
10
11 // YCbCrSubsampleRatio is the chroma subsample ratio used in a YCbCr image.
12 type YCbCrSubsampleRatio int
13
14 const (
15         YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
16         YCbCrSubsampleRatio422
17         YCbCrSubsampleRatio420
18         YCbCrSubsampleRatio440
19 )
20
21 func (s YCbCrSubsampleRatio) String() string {
22         switch s {
23         case YCbCrSubsampleRatio444:
24                 return "YCbCrSubsampleRatio444"
25         case YCbCrSubsampleRatio422:
26                 return "YCbCrSubsampleRatio422"
27         case YCbCrSubsampleRatio420:
28                 return "YCbCrSubsampleRatio420"
29         case YCbCrSubsampleRatio440:
30                 return "YCbCrSubsampleRatio440"
31         }
32         return "YCbCrSubsampleRatioUnknown"
33 }
34
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.
46 type YCbCr struct {
47         Y, Cb, Cr      []uint8
48         YStride        int
49         CStride        int
50         SubsampleRatio YCbCrSubsampleRatio
51         Rect           Rectangle
52 }
53
54 func (p *YCbCr) ColorModel() color.Model {
55         return color.YCbCrModel
56 }
57
58 func (p *YCbCr) Bounds() Rectangle {
59         return p.Rect
60 }
61
62 func (p *YCbCr) At(x, y int) color.Color {
63         if !(Point{x, y}.In(p.Rect)) {
64                 return color.YCbCr{}
65         }
66         yi := p.YOffset(x, y)
67         ci := p.COffset(x, y)
68         return color.YCbCr{
69                 p.Y[yi],
70                 p.Cb[ci],
71                 p.Cr[ci],
72         }
73 }
74
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)
79 }
80
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)
91         }
92         // Default to 4:4:4 subsampling.
93         return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
94 }
95
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.
103         if r.Empty() {
104                 return &YCbCr{
105                         SubsampleRatio: p.SubsampleRatio,
106                 }
107         }
108         yi := p.YOffset(r.Min.X, r.Min.Y)
109         ci := p.COffset(r.Min.X, r.Min.Y)
110         return &YCbCr{
111                 Y:              p.Y[yi:],
112                 Cb:             p.Cb[ci:],
113                 Cr:             p.Cr[ci:],
114                 SubsampleRatio: p.SubsampleRatio,
115                 YStride:        p.YStride,
116                 CStride:        p.CStride,
117                 Rect:           r,
118         }
119 }
120
121 func (p *YCbCr) Opaque() bool {
122         return true
123 }
124
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
131                 ch = h
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:
136                 cw = w
137                 ch = (r.Max.Y+1)/2 - r.Min.Y/2
138         default:
139                 // Default to 4:4:4 subsampling.
140                 cw = w
141                 ch = h
142         }
143         b := make([]byte, w*h+2*cw*ch)
144         return &YCbCr{
145                 Y:              b[:w*h],
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,
149                 YStride:        w,
150                 CStride:        cw,
151                 Rect:           r,
152         }
153 }