// 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 (
	
)

// YCbCrSubsampleRatio is the chroma subsample ratio used in a YCbCr image.
type YCbCrSubsampleRatio int

const (
	YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
	YCbCrSubsampleRatio422
	YCbCrSubsampleRatio420
	YCbCrSubsampleRatio440
	YCbCrSubsampleRatio411
	YCbCrSubsampleRatio410
)

func ( YCbCrSubsampleRatio) () string {
	switch  {
	case YCbCrSubsampleRatio444:
		return "YCbCrSubsampleRatio444"
	case YCbCrSubsampleRatio422:
		return "YCbCrSubsampleRatio422"
	case YCbCrSubsampleRatio420:
		return "YCbCrSubsampleRatio420"
	case YCbCrSubsampleRatio440:
		return "YCbCrSubsampleRatio440"
	case YCbCrSubsampleRatio411:
		return "YCbCrSubsampleRatio411"
	case YCbCrSubsampleRatio410:
		return "YCbCrSubsampleRatio410"
	}
	return "YCbCrSubsampleRatioUnknown"
}

// 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.
//	For 4:4:0, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/2.
//	For 4:1:1, CStride == YStride/4 && len(Cb) == len(Cr) == len(Y)/4.
//	For 4:1:0, CStride == YStride/4 && len(Cb) == len(Cr) == len(Y)/8.
type YCbCr struct {
	Y, Cb, Cr      []uint8
	YStride        int
	CStride        int
	SubsampleRatio YCbCrSubsampleRatio
	Rect           Rectangle
}

func ( *YCbCr) () color.Model {
	return color.YCbCrModel
}

func ( *YCbCr) () Rectangle {
	return .Rect
}

func ( *YCbCr) (,  int) color.Color {
	return .YCbCrAt(, )
}

func ( *YCbCr) (,  int) color.YCbCr {
	if !(Point{, }.In(.Rect)) {
		return color.YCbCr{}
	}
	 := .YOffset(, )
	 := .COffset(, )
	return color.YCbCr{
		.Y[],
		.Cb[],
		.Cr[],
	}
}

// YOffset returns the index of the first element of Y that corresponds to
// the pixel at (x, y).
func ( *YCbCr) (,  int) int {
	return (-.Rect.Min.Y)*.YStride + ( - .Rect.Min.X)
}

// COffset returns the index of the first element of Cb or Cr that corresponds
// to the pixel at (x, y).
func ( *YCbCr) (,  int) int {
	switch .SubsampleRatio {
	case YCbCrSubsampleRatio422:
		return (-.Rect.Min.Y)*.CStride + (/2 - .Rect.Min.X/2)
	case YCbCrSubsampleRatio420:
		return (/2-.Rect.Min.Y/2)*.CStride + (/2 - .Rect.Min.X/2)
	case YCbCrSubsampleRatio440:
		return (/2-.Rect.Min.Y/2)*.CStride + ( - .Rect.Min.X)
	case YCbCrSubsampleRatio411:
		return (-.Rect.Min.Y)*.CStride + (/4 - .Rect.Min.X/4)
	case YCbCrSubsampleRatio410:
		return (/2-.Rect.Min.Y/2)*.CStride + (/4 - .Rect.Min.X/4)
	}
	// Default to 4:4:4 subsampling.
	return (-.Rect.Min.Y)*.CStride + ( - .Rect.Min.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 ( *YCbCr) ( Rectangle) Image {
	 = .Intersect(.Rect)
	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
	// either r1 or r2 if the intersection is empty. Without explicitly checking for
	// this, the Pix[i:] expression below can panic.
	if .Empty() {
		return &YCbCr{
			SubsampleRatio: .SubsampleRatio,
		}
	}
	 := .YOffset(.Min.X, .Min.Y)
	 := .COffset(.Min.X, .Min.Y)
	return &YCbCr{
		Y:              .Y[:],
		Cb:             .Cb[:],
		Cr:             .Cr[:],
		SubsampleRatio: .SubsampleRatio,
		YStride:        .YStride,
		CStride:        .CStride,
		Rect:           ,
	}
}

func ( *YCbCr) () bool {
	return true
}

func yCbCrSize( Rectangle,  YCbCrSubsampleRatio) (, , ,  int) {
	,  = .Dx(), .Dy()
	switch  {
	case YCbCrSubsampleRatio422:
		 = (.Max.X+1)/2 - .Min.X/2
		 = 
	case YCbCrSubsampleRatio420:
		 = (.Max.X+1)/2 - .Min.X/2
		 = (.Max.Y+1)/2 - .Min.Y/2
	case YCbCrSubsampleRatio440:
		 = 
		 = (.Max.Y+1)/2 - .Min.Y/2
	case YCbCrSubsampleRatio411:
		 = (.Max.X+3)/4 - .Min.X/4
		 = 
	case YCbCrSubsampleRatio410:
		 = (.Max.X+3)/4 - .Min.X/4
		 = (.Max.Y+1)/2 - .Min.Y/2
	default:
		// Default to 4:4:4 subsampling.
		 = 
		 = 
	}
	return
}

// NewYCbCr returns a new YCbCr image with the given bounds and subsample
// ratio.
func ( Rectangle,  YCbCrSubsampleRatio) *YCbCr {
	, , ,  := yCbCrSize(, )

	// totalLength should be the same as i2, below, for a valid Rectangle r.
	 := add2NonNeg(
		mul3NonNeg(1, , ),
		mul3NonNeg(2, , ),
	)
	if  < 0 {
		panic("image: NewYCbCr Rectangle has huge or negative dimensions")
	}

	 := * + 0**
	 := * + 1**
	 := * + 2**
	 := make([]byte, )
	return &YCbCr{
		Y:              [::],
		Cb:             [::],
		Cr:             [::],
		SubsampleRatio: ,
		YStride:        ,
		CStride:        ,
		Rect:           ,
	}
}

// NYCbCrA is an in-memory image of non-alpha-premultiplied Y'CbCr-with-alpha
// colors. A and AStride are analogous to the Y and YStride fields of the
// embedded YCbCr.
type NYCbCrA struct {
	YCbCr
	A       []uint8
	AStride int
}

func ( *NYCbCrA) () color.Model {
	return color.NYCbCrAModel
}

func ( *NYCbCrA) (,  int) color.Color {
	return .NYCbCrAAt(, )
}

func ( *NYCbCrA) (,  int) color.NYCbCrA {
	if !(Point{X: , Y: }.In(.Rect)) {
		return color.NYCbCrA{}
	}
	 := .YOffset(, )
	 := .COffset(, )
	 := .AOffset(, )
	return color.NYCbCrA{
		color.YCbCr{
			Y:  .Y[],
			Cb: .Cb[],
			Cr: .Cr[],
		},
		.A[],
	}
}

// AOffset returns the index of the first element of A that corresponds to the
// pixel at (x, y).
func ( *NYCbCrA) (,  int) int {
	return (-.Rect.Min.Y)*.AStride + ( - .Rect.Min.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 ( *NYCbCrA) ( Rectangle) Image {
	 = .Intersect(.Rect)
	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
	// either r1 or r2 if the intersection is empty. Without explicitly checking for
	// this, the Pix[i:] expression below can panic.
	if .Empty() {
		return &NYCbCrA{
			YCbCr: YCbCr{
				SubsampleRatio: .SubsampleRatio,
			},
		}
	}
	 := .YOffset(.Min.X, .Min.Y)
	 := .COffset(.Min.X, .Min.Y)
	 := .AOffset(.Min.X, .Min.Y)
	return &NYCbCrA{
		YCbCr: YCbCr{
			Y:              .Y[:],
			Cb:             .Cb[:],
			Cr:             .Cr[:],
			SubsampleRatio: .SubsampleRatio,
			YStride:        .YStride,
			CStride:        .CStride,
			Rect:           ,
		},
		A:       .A[:],
		AStride: .AStride,
	}
}

// Opaque scans the entire image and reports whether it is fully opaque.
func ( *NYCbCrA) () bool {
	if .Rect.Empty() {
		return true
	}
	,  := 0, .Rect.Dx()
	for  := .Rect.Min.Y;  < .Rect.Max.Y; ++ {
		for ,  := range .A[:] {
			if  != 0xff {
				return false
			}
		}
		 += .AStride
		 += .AStride
	}
	return true
}

// NewNYCbCrA returns a new NYCbCrA image with the given bounds and subsample
// ratio.
func ( Rectangle,  YCbCrSubsampleRatio) *NYCbCrA {
	, , ,  := yCbCrSize(, )

	// totalLength should be the same as i3, below, for a valid Rectangle r.
	 := add2NonNeg(
		mul3NonNeg(2, , ),
		mul3NonNeg(2, , ),
	)
	if  < 0 {
		panic("image: NewNYCbCrA Rectangle has huge or negative dimension")
	}

	 := 1** + 0**
	 := 1** + 1**
	 := 1** + 2**
	 := 2** + 2**
	 := make([]byte, )
	return &NYCbCrA{
		YCbCr: YCbCr{
			Y:              [::],
			Cb:             [::],
			Cr:             [::],
			SubsampleRatio: ,
			YStride:        ,
			CStride:        ,
			Rect:           ,
		},
		A:       [:],
		AStride: ,
	}
}