From e4dcf5c8c22d98ac9eac7b9b226596229624cb1d Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Wed, 23 Dec 2015 17:35:46 +1100 Subject: [PATCH] image/color: have NYCbCrA.RGBA work in 16-bit color. This makes NYCbCrA consistent with YCbCr. Fixes #13706. Change-Id: Ifced84372e4865925fa6efef9ca2f1de43da70e0 Reviewed-on: https://go-review.googlesource.com/18115 Reviewed-by: Rob Pike --- src/image/color/ycbcr.go | 36 +++++++++++++++++++++++++++-------- src/image/color/ycbcr_test.go | 26 ++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/image/color/ycbcr.go b/src/image/color/ycbcr.go index 0c2ba84c57..904434f6a3 100644 --- a/src/image/color/ycbcr.go +++ b/src/image/color/ycbcr.go @@ -98,7 +98,7 @@ func (c YCbCr) RGBA() (uint32, uint32, uint32, uint32) { // fmt.Printf("0x%04x 0x%04x 0x%04x\n", r0, g0, b0) // fmt.Printf("0x%04x 0x%04x 0x%04x\n", r1, g1, b1) // prints: - // 0x7e18 0x808e 0x7db9 + // 0x7e18 0x808d 0x7db9 // 0x7e7e 0x8080 0x7d7d yy1 := int32(c.Y) * 0x10100 // Convert 0x12 to 0x121200. @@ -144,13 +144,33 @@ type NYCbCrA struct { A uint8 } -func (c NYCbCrA) RGBA() (r, g, b, a uint32) { - r8, g8, b8 := YCbCrToRGB(c.Y, c.Cb, c.Cr) - a = uint32(c.A) * 0x101 - r = uint32(r8) * 0x101 * a / 0xffff - g = uint32(g8) * 0x101 * a / 0xffff - b = uint32(b8) * 0x101 * a / 0xffff - return +func (c NYCbCrA) RGBA() (uint32, uint32, uint32, uint32) { + // The first part of this method is the same as YCbCr.RGBA. + yy1 := int32(c.Y) * 0x10100 // Convert 0x12 to 0x121200. + cb1 := int32(c.Cb) - 128 + cr1 := int32(c.Cr) - 128 + r := (yy1 + 91881*cr1) >> 8 + g := (yy1 - 22554*cb1 - 46802*cr1) >> 8 + b := (yy1 + 116130*cb1) >> 8 + if r < 0 { + r = 0 + } else if r > 0xffff { + r = 0xffff + } + if g < 0 { + g = 0 + } else if g > 0xffff { + g = 0xffff + } + if b < 0 { + b = 0 + } else if b > 0xffff { + b = 0xffff + } + + // The second part of this method applies the alpha. + a := uint32(c.A) * 0x101 + return uint32(r) * a / 0xffff, uint32(g) * a / 0xffff, uint32(b) * a / 0xffff, a } // NYCbCrAModel is the Model for non-alpha-premultiplied Y'CbCr-with-alpha diff --git a/src/image/color/ycbcr_test.go b/src/image/color/ycbcr_test.go index 5da49d379a..f5e7cbf335 100644 --- a/src/image/color/ycbcr_test.go +++ b/src/image/color/ycbcr_test.go @@ -67,7 +67,31 @@ func TestYCbCrToRGBConsistency(t *testing.T) { // TestYCbCrGray tests that YCbCr colors are a superset of Gray colors. func TestYCbCrGray(t *testing.T) { for i := 0; i < 256; i++ { - if err := eq(YCbCr{uint8(i), 0x80, 0x80}, Gray{uint8(i)}); err != nil { + c0 := YCbCr{uint8(i), 0x80, 0x80} + c1 := Gray{uint8(i)} + if err := eq(c0, c1); err != nil { + t.Errorf("i=0x%02x:\n%v", i, err) + } + } +} + +// TestNYCbCrAAlpha tests that NYCbCrA colors are a superset of Alpha colors. +func TestNYCbCrAAlpha(t *testing.T) { + for i := 0; i < 256; i++ { + c0 := NYCbCrA{YCbCr{0xff, 0x80, 0x80}, uint8(i)} + c1 := Alpha{uint8(i)} + if err := eq(c0, c1); err != nil { + t.Errorf("i=0x%02x:\n%v", i, err) + } + } +} + +// TestNYCbCrAYCbCr tests that NYCbCrA colors are a superset of YCbCr colors. +func TestNYCbCrAYCbCr(t *testing.T) { + for i := 0; i < 256; i++ { + c0 := NYCbCrA{YCbCr{uint8(i), 0x40, 0xc0}, 0xff} + c1 := YCbCr{uint8(i), 0x40, 0xc0} + if err := eq(c0, c1); err != nil { t.Errorf("i=0x%02x:\n%v", i, err) } } -- 2.50.0