Source file src/pkg/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 ) 19 20 func (s YCbCrSubsampleRatio) String() string { 21 switch s { 22 case YCbCrSubsampleRatio444: 23 return "YCbCrSubsampleRatio444" 24 case YCbCrSubsampleRatio422: 25 return "YCbCrSubsampleRatio422" 26 case YCbCrSubsampleRatio420: 27 return "YCbCrSubsampleRatio420" 28 } 29 return "YCbCrSubsampleRatioUnknown" 30 } 31 32 // YCbCr is an in-memory image of Y'CbCr colors. There is one Y sample per 33 // pixel, but each Cb and Cr sample can span one or more pixels. 34 // YStride is the Y slice index delta between vertically adjacent pixels. 35 // CStride is the Cb and Cr slice index delta between vertically adjacent pixels 36 // that map to separate chroma samples. 37 // It is not an absolute requirement, but YStride and len(Y) are typically 38 // multiples of 8, and: 39 // For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1. 40 // For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2. 41 // For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4. 42 type YCbCr struct { 43 Y, Cb, Cr []uint8 44 YStride int 45 CStride int 46 SubsampleRatio YCbCrSubsampleRatio 47 Rect Rectangle 48 } 49 50 func (p *YCbCr) ColorModel() color.Model { 51 return color.YCbCrModel 52 } 53 54 func (p *YCbCr) Bounds() Rectangle { 55 return p.Rect 56 } 57 58 func (p *YCbCr) At(x, y int) color.Color { 59 if !(Point{x, y}.In(p.Rect)) { 60 return color.YCbCr{} 61 } 62 yi := p.YOffset(x, y) 63 ci := p.COffset(x, y) 64 return color.YCbCr{ 65 p.Y[yi], 66 p.Cb[ci], 67 p.Cr[ci], 68 } 69 } 70 71 // YOffset returns the index of the first element of Y that corresponds to 72 // the pixel at (x, y). 73 func (p *YCbCr) YOffset(x, y int) int { 74 return (y-p.Rect.Min.Y)*p.YStride + (x - p.Rect.Min.X) 75 } 76 77 // COffset returns the index of the first element of Cb or Cr that corresponds 78 // to the pixel at (x, y). 79 func (p *YCbCr) COffset(x, y int) int { 80 switch p.SubsampleRatio { 81 case YCbCrSubsampleRatio422: 82 return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2) 83 case YCbCrSubsampleRatio420: 84 return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2) 85 } 86 // Default to 4:4:4 subsampling. 87 return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X) 88 } 89 90 // SubImage returns an image representing the portion of the image p visible 91 // through r. The returned value shares pixels with the original image. 92 func (p *YCbCr) SubImage(r Rectangle) Image { 93 r = r.Intersect(p.Rect) 94 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 95 // either r1 or r2 if the intersection is empty. Without explicitly checking for 96 // this, the Pix[i:] expression below can panic. 97 if r.Empty() { 98 return &YCbCr{ 99 SubsampleRatio: p.SubsampleRatio, 100 } 101 } 102 yi := p.YOffset(r.Min.X, r.Min.Y) 103 ci := p.COffset(r.Min.X, r.Min.Y) 104 return &YCbCr{ 105 Y: p.Y[yi:], 106 Cb: p.Cb[ci:], 107 Cr: p.Cr[ci:], 108 SubsampleRatio: p.SubsampleRatio, 109 YStride: p.YStride, 110 CStride: p.CStride, 111 Rect: r, 112 } 113 } 114 115 func (p *YCbCr) Opaque() bool { 116 return true 117 } 118 119 // NewYCbCr returns a new YCbCr with the given bounds and subsample ratio. 120 func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr { 121 w, h, cw, ch := r.Dx(), r.Dy(), 0, 0 122 switch subsampleRatio { 123 case YCbCrSubsampleRatio422: 124 cw = (r.Max.X+1)/2 - r.Min.X/2 125 ch = h 126 case YCbCrSubsampleRatio420: 127 cw = (r.Max.X+1)/2 - r.Min.X/2 128 ch = (r.Max.Y+1)/2 - r.Min.Y/2 129 default: 130 // Default to 4:4:4 subsampling. 131 cw = w 132 ch = h 133 } 134 b := make([]byte, w*h+2*cw*ch) 135 return &YCbCr{ 136 Y: b[:w*h], 137 Cb: b[w*h+0*cw*ch : w*h+1*cw*ch], 138 Cr: b[w*h+1*cw*ch : w*h+2*cw*ch], 139 SubsampleRatio: subsampleRatio, 140 YStride: w, 141 CStride: cw, 142 Rect: r, 143 } 144 }