| // Copyright 2011 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package image |
| |
| import ( |
| "image/color" |
| ) |
| |
| // YCbCrSubsampleRatio is the chroma subsample ratio used in a YCbCr image. |
| type YCbCrSubsampleRatio int |
| |
| const ( |
| YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota |
| YCbCrSubsampleRatio422 |
| YCbCrSubsampleRatio420 |
| ) |
| |
| // YCbCr is an in-memory image of Y'CbCr colors. There is one Y sample per |
| // pixel, but each Cb and Cr sample can span one or more pixels. |
| // YStride is the Y slice index delta between vertically adjacent pixels. |
| // CStride is the Cb and Cr slice index delta between vertically adjacent pixels |
| // that map to separate chroma samples. |
| // It is not an absolute requirement, but YStride and len(Y) are typically |
| // multiples of 8, and: |
| // For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1. |
| // For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2. |
| // For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4. |
| type YCbCr struct { |
| Y []uint8 |
| Cb []uint8 |
| Cr []uint8 |
| YStride int |
| CStride int |
| SubsampleRatio YCbCrSubsampleRatio |
| Rect Rectangle |
| } |
| |
| func (p *YCbCr) ColorModel() color.Model { |
| return color.YCbCrModel |
| } |
| |
| func (p *YCbCr) Bounds() Rectangle { |
| return p.Rect |
| } |
| |
| func (p *YCbCr) At(x, y int) color.Color { |
| if !(Point{x, y}.In(p.Rect)) { |
| return color.YCbCr{} |
| } |
| switch p.SubsampleRatio { |
| case YCbCrSubsampleRatio422: |
| i := x / 2 |
| return color.YCbCr{ |
| p.Y[y*p.YStride+x], |
| p.Cb[y*p.CStride+i], |
| p.Cr[y*p.CStride+i], |
| } |
| case YCbCrSubsampleRatio420: |
| i, j := x/2, y/2 |
| return color.YCbCr{ |
| p.Y[y*p.YStride+x], |
| p.Cb[j*p.CStride+i], |
| p.Cr[j*p.CStride+i], |
| } |
| } |
| // Default to 4:4:4 subsampling. |
| return color.YCbCr{ |
| p.Y[y*p.YStride+x], |
| p.Cb[y*p.CStride+x], |
| p.Cr[y*p.CStride+x], |
| } |
| } |
| |
| // SubImage returns an image representing the portion of the image p visible |
| // through r. The returned value shares pixels with the original image. |
| func (p *YCbCr) SubImage(r Rectangle) Image { |
| q := new(YCbCr) |
| *q = *p |
| q.Rect = q.Rect.Intersect(r) |
| return q |
| } |
| |
| func (p *YCbCr) Opaque() bool { |
| return true |
| } |