aboutsummaryrefslogtreecommitdiff
path: root/src/image
diff options
context:
space:
mode:
authorNigel Tao <nigeltao@golang.org>2015-03-26 09:47:24 +1100
committerNigel Tao <nigeltao@golang.org>2015-03-26 22:30:55 +0000
commit2f34e606faa8cf676010fba04c5c3ca355a9cc84 (patch)
treeb8441dcd94f048973a07da2c5e80b89a5429d3d8 /src/image
parent392336f94ea783c69ac8ed43bf716ebdc0fc71cd (diff)
downloadgo-2f34e606faa8cf676010fba04c5c3ca355a9cc84.tar.xz
image/color: have YCbCr.RGBA work in 16-bit color, per the Color
interface. Change-Id: Ie025753df08ae93e7a5095a3426aff15fa2016fd Reviewed-on: https://go-review.googlesource.com/8073 Reviewed-by: Rob Pike <r@golang.org>
Diffstat (limited to 'src/image')
-rw-r--r--src/image/color/color.go4
-rw-r--r--src/image/color/ycbcr.go83
2 files changed, 62 insertions, 25 deletions
diff --git a/src/image/color/color.go b/src/image/color/color.go
index e062e0f9ac..00bd8fd9b1 100644
--- a/src/image/color/color.go
+++ b/src/image/color/color.go
@@ -9,8 +9,8 @@ package color
// The conversion may be lossy.
type Color interface {
// RGBA returns the alpha-premultiplied red, green, blue and alpha values
- // for the color. Each value ranges within [0, 0xFFFF], but is represented
- // by a uint32 so that multiplying by a blend factor up to 0xFFFF will not
+ // for the color. Each value ranges within [0, 0xffff], but is represented
+ // by a uint32 so that multiplying by a blend factor up to 0xffff will not
// overflow.
//
// An alpha-premultiplied color component c has been scaled by alpha (a),
diff --git a/src/image/color/ycbcr.go b/src/image/color/ycbcr.go
index b7df672784..bbaaf7e188 100644
--- a/src/image/color/ycbcr.go
+++ b/src/image/color/ycbcr.go
@@ -19,18 +19,18 @@ func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
cr := (32768*r1 - 27440*g1 - 5328*b1 + 257<<15) >> 16
if yy < 0 {
yy = 0
- } else if yy > 255 {
- yy = 255
+ } else if yy > 0xff {
+ yy = 0xff
}
if cb < 0 {
cb = 0
- } else if cb > 255 {
- cb = 255
+ } else if cb > 0xff {
+ cb = 0xff
}
if cr < 0 {
cr = 0
- } else if cr > 255 {
- cr = 255
+ } else if cr > 0xff {
+ cr = 0xff
}
return uint8(yy), uint8(cb), uint8(cr)
}
@@ -50,18 +50,18 @@ func YCbCrToRGB(y, cb, cr uint8) (uint8, uint8, uint8) {
b := (yy1 + 116130*cb1) >> 16
if r < 0 {
r = 0
- } else if r > 255 {
- r = 255
+ } else if r > 0xff {
+ r = 0xff
}
if g < 0 {
g = 0
- } else if g > 255 {
- g = 255
+ } else if g > 0xff {
+ g = 0xff
}
if b < 0 {
b = 0
- } else if b > 255 {
- b = 255
+ } else if b > 0xff {
+ b = 0xff
}
return uint8(r), uint8(g), uint8(b)
}
@@ -82,8 +82,45 @@ type YCbCr struct {
}
func (c YCbCr) RGBA() (uint32, uint32, uint32, uint32) {
- r, g, b := YCbCrToRGB(c.Y, c.Cb, c.Cr)
- return uint32(r) * 0x101, uint32(g) * 0x101, uint32(b) * 0x101, 0xffff
+ // This code is a copy of the YCbCrToRGB function above, except that it
+ // returns values in the range [0, 0xffff] instead of [0, 0xff]. There is a
+ // subtle difference between doing this and having YCbCr satisfy the Color
+ // interface by first converting to an RGBA. The latter loses some
+ // information by going to and from 8 bits per channel.
+ //
+ // For example, this code:
+ // const y, cb, cr = 0x7f, 0x7f, 0x7f
+ // r, g, b := color.YCbCrToRGB(y, cb, cr)
+ // r0, g0, b0, _ := color.YCbCr{y, cb, cr}.RGBA()
+ // r1, g1, b1, _ := color.RGBA{r, g, b, 0xff}.RGBA()
+ // 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:
+ // 0x7e19 0x808e 0x7dba
+ // 0x7e7e 0x8080 0x7d7d
+
+ yy1 := int(c.Y)<<16 + 1<<15
+ cb1 := int(c.Cb) - 128
+ cr1 := int(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
+ }
+ return uint32(r), uint32(g), uint32(b), 0xffff
}
// YCbCrModel is the Model for Y'CbCr colors.
@@ -111,20 +148,20 @@ func RGBToCMYK(r, g, b uint8) (uint8, uint8, uint8, uint8) {
w = bb
}
if w == 0 {
- return 0, 0, 0, 255
+ return 0, 0, 0, 0xff
}
- c := (w - rr) * 255 / w
- m := (w - gg) * 255 / w
- y := (w - bb) * 255 / w
- return uint8(c), uint8(m), uint8(y), uint8(255 - w)
+ c := (w - rr) * 0xff / w
+ m := (w - gg) * 0xff / w
+ y := (w - bb) * 0xff / w
+ return uint8(c), uint8(m), uint8(y), uint8(0xff - w)
}
// CMYKToRGB converts a CMYK quadruple to an RGB triple.
func CMYKToRGB(c, m, y, k uint8) (uint8, uint8, uint8) {
- w := uint32(255 - k)
- r := uint32(255-c) * w / 255
- g := uint32(255-m) * w / 255
- b := uint32(255-y) * w / 255
+ w := uint32(0xff - k)
+ r := uint32(0xff-c) * w / 0xff
+ g := uint32(0xff-m) * w / 0xff
+ b := uint32(0xff-y) * w / 0xff
return uint8(r), uint8(g), uint8(b)
}