88 lines
2.2 KiB
Go
88 lines
2.2 KiB
Go
|
// 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
|
||
|
}
|