123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- package image
- import (
- "image/color"
- )
- type YCbCrSubsampleRatio int
- const (
- YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
- YCbCrSubsampleRatio422
- YCbCrSubsampleRatio420
- YCbCrSubsampleRatio440
- )
- func (s YCbCrSubsampleRatio) String() string {
- switch s {
- case YCbCrSubsampleRatio444:
- return "YCbCrSubsampleRatio444"
- case YCbCrSubsampleRatio422:
- return "YCbCrSubsampleRatio422"
- case YCbCrSubsampleRatio420:
- return "YCbCrSubsampleRatio420"
- case YCbCrSubsampleRatio440:
- return "YCbCrSubsampleRatio440"
- }
- return "YCbCrSubsampleRatioUnknown"
- }
- type YCbCr struct {
- Y, Cb, 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 {
- return p.YCbCrAt(x, y)
- }
- func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr {
- if !(Point{x, y}.In(p.Rect)) {
- return color.YCbCr{}
- }
- yi := p.YOffset(x, y)
- ci := p.COffset(x, y)
- return color.YCbCr{
- p.Y[yi],
- p.Cb[ci],
- p.Cr[ci],
- }
- }
- func (p *YCbCr) YOffset(x, y int) int {
- return (y-p.Rect.Min.Y)*p.YStride + (x - p.Rect.Min.X)
- }
- func (p *YCbCr) COffset(x, y int) int {
- switch p.SubsampleRatio {
- case YCbCrSubsampleRatio422:
- return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
- case YCbCrSubsampleRatio420:
- return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
- case YCbCrSubsampleRatio440:
- return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
- }
-
- return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
- }
- func (p *YCbCr) SubImage(r Rectangle) Image {
- r = r.Intersect(p.Rect)
-
-
-
- if r.Empty() {
- return &YCbCr{
- SubsampleRatio: p.SubsampleRatio,
- }
- }
- yi := p.YOffset(r.Min.X, r.Min.Y)
- ci := p.COffset(r.Min.X, r.Min.Y)
- return &YCbCr{
- Y: p.Y[yi:],
- Cb: p.Cb[ci:],
- Cr: p.Cr[ci:],
- SubsampleRatio: p.SubsampleRatio,
- YStride: p.YStride,
- CStride: p.CStride,
- Rect: r,
- }
- }
- func (p *YCbCr) Opaque() bool {
- return true
- }
- func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
- w, h, cw, ch := r.Dx(), r.Dy(), 0, 0
- switch subsampleRatio {
- case YCbCrSubsampleRatio422:
- cw = (r.Max.X+1)/2 - r.Min.X/2
- ch = h
- case YCbCrSubsampleRatio420:
- cw = (r.Max.X+1)/2 - r.Min.X/2
- ch = (r.Max.Y+1)/2 - r.Min.Y/2
- case YCbCrSubsampleRatio440:
- cw = w
- ch = (r.Max.Y+1)/2 - r.Min.Y/2
- default:
-
- cw = w
- ch = h
- }
- b := make([]byte, w*h+2*cw*ch)
- return &YCbCr{
- Y: b[:w*h],
- Cb: b[w*h+0*cw*ch : w*h+1*cw*ch],
- Cr: b[w*h+1*cw*ch : w*h+2*cw*ch],
- SubsampleRatio: subsampleRatio,
- YStride: w,
- CStride: cw,
- Rect: r,
- }
- }
|