Commit 7d735139 authored by Nigel Tao's avatar Nigel Tao

image: add YCbCrSubsampleRatio411 and YCbCrSubsampleRatio410.

Some real world JPEG images are in 4:1:1 and 4:1:0 formats.

See also http://en.wikipedia.org/wiki/Chroma_subsampling

Change-Id: I2d51a41944f581cf11f4ab975046b1737271842f
Reviewed-on: https://go-review.googlesource.com/5838Reviewed-by: 's avatarRob Pike <r@golang.org>
parent b351e1de
...@@ -16,6 +16,8 @@ const ( ...@@ -16,6 +16,8 @@ const (
YCbCrSubsampleRatio422 YCbCrSubsampleRatio422
YCbCrSubsampleRatio420 YCbCrSubsampleRatio420
YCbCrSubsampleRatio440 YCbCrSubsampleRatio440
YCbCrSubsampleRatio411
YCbCrSubsampleRatio410
) )
func (s YCbCrSubsampleRatio) String() string { func (s YCbCrSubsampleRatio) String() string {
...@@ -28,6 +30,10 @@ func (s YCbCrSubsampleRatio) String() string { ...@@ -28,6 +30,10 @@ func (s YCbCrSubsampleRatio) String() string {
return "YCbCrSubsampleRatio420" return "YCbCrSubsampleRatio420"
case YCbCrSubsampleRatio440: case YCbCrSubsampleRatio440:
return "YCbCrSubsampleRatio440" return "YCbCrSubsampleRatio440"
case YCbCrSubsampleRatio411:
return "YCbCrSubsampleRatio411"
case YCbCrSubsampleRatio410:
return "YCbCrSubsampleRatio410"
} }
return "YCbCrSubsampleRatioUnknown" return "YCbCrSubsampleRatioUnknown"
} }
...@@ -43,6 +49,8 @@ func (s YCbCrSubsampleRatio) String() string { ...@@ -43,6 +49,8 @@ func (s YCbCrSubsampleRatio) String() string {
// For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2. // 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: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: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 { type YCbCr struct {
Y, Cb, Cr []uint8 Y, Cb, Cr []uint8
YStride int YStride int
...@@ -92,6 +100,10 @@ func (p *YCbCr) COffset(x, y int) int { ...@@ -92,6 +100,10 @@ func (p *YCbCr) COffset(x, y int) int {
return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2) return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
case YCbCrSubsampleRatio440: case YCbCrSubsampleRatio440:
return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X) return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
case YCbCrSubsampleRatio411:
return (y-p.Rect.Min.Y)*p.CStride + (x/4 - p.Rect.Min.X/4)
case YCbCrSubsampleRatio410:
return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/4 - p.Rect.Min.X/4)
} }
// Default to 4:4:4 subsampling. // Default to 4:4:4 subsampling.
return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X) return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
...@@ -139,6 +151,12 @@ func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr { ...@@ -139,6 +151,12 @@ func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
case YCbCrSubsampleRatio440: case YCbCrSubsampleRatio440:
cw = w cw = w
ch = (r.Max.Y+1)/2 - r.Min.Y/2 ch = (r.Max.Y+1)/2 - r.Min.Y/2
case YCbCrSubsampleRatio411:
cw = (r.Max.X+3)/4 - r.Min.X/4
ch = h
case YCbCrSubsampleRatio410:
cw = (r.Max.X+3)/4 - r.Min.X/4
ch = (r.Max.Y+1)/2 - r.Min.Y/2
default: default:
// Default to 4:4:4 subsampling. // Default to 4:4:4 subsampling.
cw = w cw = w
......
...@@ -37,6 +37,8 @@ func TestYCbCr(t *testing.T) { ...@@ -37,6 +37,8 @@ func TestYCbCr(t *testing.T) {
YCbCrSubsampleRatio422, YCbCrSubsampleRatio422,
YCbCrSubsampleRatio420, YCbCrSubsampleRatio420,
YCbCrSubsampleRatio440, YCbCrSubsampleRatio440,
YCbCrSubsampleRatio411,
YCbCrSubsampleRatio410,
} }
deltas := []Point{ deltas := []Point{
Pt(0, 0), Pt(0, 0),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment