github.com/zxy12/golang151_with_comment@v0.0.0-20190507085033-721809559d3c/image/ycbcr.go (about) 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 YCbCrSubsampleRatio411 20 YCbCrSubsampleRatio410 21 ) 22 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" 37 } 38 return "YCbCrSubsampleRatioUnknown" 39 } 40 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 60 } 61 62 func (p *YCbCr) ColorModel() color.Model { 63 return color.YCbCrModel 64 } 65 66 func (p *YCbCr) Bounds() Rectangle { 67 return p.Rect 68 } 69 70 func (p *YCbCr) At(x, y int) color.Color { 71 return p.YCbCrAt(x, y) 72 } 73 74 func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr { 75 if !(Point{x, y}.In(p.Rect)) { 76 return color.YCbCr{} 77 } 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], 84 } 85 } 86 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) 91 } 92 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) 107 } 108 // Default to 4:4:4 subsampling. 109 return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X) 110 } 111 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, 122 } 123 } 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, 134 } 135 } 136 137 func (p *YCbCr) Opaque() bool { 138 return true 139 } 140 141 // NewYCbCr returns a new YCbCr with the given bounds and subsample ratio. 142 func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr { 143 w, h, cw, ch := r.Dx(), r.Dy(), 0, 0 144 switch subsampleRatio { 145 case YCbCrSubsampleRatio422: 146 cw = (r.Max.X+1)/2 - r.Min.X/2 147 ch = h 148 case YCbCrSubsampleRatio420: 149 cw = (r.Max.X+1)/2 - r.Min.X/2 150 ch = (r.Max.Y+1)/2 - r.Min.Y/2 151 case YCbCrSubsampleRatio440: 152 cw = w 153 ch = (r.Max.Y+1)/2 - r.Min.Y/2 154 case YCbCrSubsampleRatio411: 155 cw = (r.Max.X+3)/4 - r.Min.X/4 156 ch = h 157 case YCbCrSubsampleRatio410: 158 cw = (r.Max.X+3)/4 - r.Min.X/4 159 ch = (r.Max.Y+1)/2 - r.Min.Y/2 160 default: 161 // Default to 4:4:4 subsampling. 162 cw = w 163 ch = h 164 } 165 i0 := w*h + 0*cw*ch 166 i1 := w*h + 1*cw*ch 167 i2 := w*h + 2*cw*ch 168 b := make([]byte, i2) 169 return &YCbCr{ 170 Y: b[:i0:i0], 171 Cb: b[i0:i1:i1], 172 Cr: b[i1:i2:i2], 173 SubsampleRatio: subsampleRatio, 174 YStride: w, 175 CStride: cw, 176 Rect: r, 177 } 178 }