1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 package color
6 7 // RGBToYCbCr converts an RGB triple to a Y'CbCr triple.
8 func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
9 // The JFIF specification says:
10 // Y' = 0.2990*R + 0.5870*G + 0.1140*B
11 // Cb = -0.1687*R - 0.3313*G + 0.5000*B + 128
12 // Cr = 0.5000*R - 0.4187*G - 0.0813*B + 128
13 // https://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
14 15 r1 := int32(r)
16 g1 := int32(g)
17 b1 := int32(b)
18 19 // yy is in range [0,0xff].
20 //
21 // Note that 19595 + 38470 + 7471 equals 65536.
22 yy := (19595*r1 + 38470*g1 + 7471*b1 + 1<<15) >> 16
23 24 // The bit twiddling below is equivalent to
25 //
26 // cb := (-11056*r1 - 21712*g1 + 32768*b1 + 257<<15) >> 16
27 // if cb < 0 {
28 // cb = 0
29 // } else if cb > 0xff {
30 // cb = ^int32(0)
31 // }
32 //
33 // but uses fewer branches and is faster.
34 // Note that the uint8 type conversion in the return
35 // statement will convert ^int32(0) to 0xff.
36 // The code below to compute cr uses a similar pattern.
37 //
38 // Note that -11056 - 21712 + 32768 equals 0.
39 cb := -11056*r1 - 21712*g1 + 32768*b1 + 257<<15
40 if uint32(cb)&0xff000000 == 0 {
41 cb >>= 16
42 } else {
43 cb = ^(cb >> 31)
44 }
45 46 // Note that 32768 - 27440 - 5328 equals 0.
47 cr := 32768*r1 - 27440*g1 - 5328*b1 + 257<<15
48 if uint32(cr)&0xff000000 == 0 {
49 cr >>= 16
50 } else {
51 cr = ^(cr >> 31)
52 }
53 54 return uint8(yy), uint8(cb), uint8(cr)
55 }
56 57 // YCbCrToRGB converts a Y'CbCr triple to an RGB triple.
58 func YCbCrToRGB(y, cb, cr uint8) (uint8, uint8, uint8) {
59 // The JFIF specification says:
60 // R = Y' + 1.40200*(Cr-128)
61 // G = Y' - 0.34414*(Cb-128) - 0.71414*(Cr-128)
62 // B = Y' + 1.77200*(Cb-128)
63 // https://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
64 //
65 // Those formulae use non-integer multiplication factors. When computing,
66 // integer math is generally faster than floating point math. We multiply
67 // all of those factors by 1<<16 and round to the nearest integer:
68 // 91881 = roundToNearestInteger(1.40200 * 65536).
69 // 22554 = roundToNearestInteger(0.34414 * 65536).
70 // 46802 = roundToNearestInteger(0.71414 * 65536).
71 // 116130 = roundToNearestInteger(1.77200 * 65536).
72 //
73 // Adding a rounding adjustment in the range [0, 1<<16-1] and then shifting
74 // right by 16 gives us an integer math version of the original formulae.
75 // R = (65536*Y' + 91881 *(Cr-128) + adjustment) >> 16
76 // G = (65536*Y' - 22554 *(Cb-128) - 46802*(Cr-128) + adjustment) >> 16
77 // B = (65536*Y' + 116130 *(Cb-128) + adjustment) >> 16
78 // A constant rounding adjustment of 1<<15, one half of 1<<16, would mean
79 // round-to-nearest when dividing by 65536 (shifting right by 16).
80 // Similarly, a constant rounding adjustment of 0 would mean round-down.
81 //
82 // Defining YY1 = 65536*Y' + adjustment simplifies the formulae and
83 // requires fewer CPU operations:
84 // R = (YY1 + 91881 *(Cr-128) ) >> 16
85 // G = (YY1 - 22554 *(Cb-128) - 46802*(Cr-128)) >> 16
86 // B = (YY1 + 116130 *(Cb-128) ) >> 16
87 //
88 // The inputs (y, cb, cr) are 8 bit color, ranging in [0x00, 0xff]. In this
89 // function, the output is also 8 bit color, but in the related YCbCr.RGBA
90 // method, below, the output is 16 bit color, ranging in [0x0000, 0xffff].
91 // Outputting 16 bit color simply requires changing the 16 to 8 in the "R =
92 // etc >> 16" equation, and likewise for G and B.
93 //
94 // As mentioned above, a constant rounding adjustment of 1<<15 is a natural
95 // choice, but there is an additional constraint: if c0 := YCbCr{Y: y, Cb:
96 // 0x80, Cr: 0x80} and c1 := Gray{Y: y} then c0.RGBA() should equal
97 // c1.RGBA(). Specifically, if y == 0 then "R = etc >> 8" should yield
98 // 0x0000 and if y == 0xff then "R = etc >> 8" should yield 0xffff. If we
99 // used a constant rounding adjustment of 1<<15, then it would yield 0x0080
100 // and 0xff80 respectively.
101 //
102 // Note that when cb == 0x80 and cr == 0x80 then the formulae collapse to:
103 // R = YY1 >> n
104 // G = YY1 >> n
105 // B = YY1 >> n
106 // where n is 16 for this function (8 bit color output) and 8 for the
107 // YCbCr.RGBA method (16 bit color output).
108 //
109 // The solution is to make the rounding adjustment non-constant, and equal
110 // to 257*Y', which ranges over [0, 1<<16-1] as Y' ranges over [0, 255].
111 // YY1 is then defined as:
112 // YY1 = 65536*Y' + 257*Y'
113 // or equivalently:
114 // YY1 = Y' * 0x10101
115 yy1 := int32(y) * 0x10101
116 cb1 := int32(cb) - 128
117 cr1 := int32(cr) - 128
118 119 // The bit twiddling below is equivalent to
120 //
121 // r := (yy1 + 91881*cr1) >> 16
122 // if r < 0 {
123 // r = 0
124 // } else if r > 0xff {
125 // r = ^int32(0)
126 // }
127 //
128 // but uses fewer branches and is faster.
129 // Note that the uint8 type conversion in the return
130 // statement will convert ^int32(0) to 0xff.
131 // The code below to compute g and b uses a similar pattern.
132 r := yy1 + 91881*cr1
133 if uint32(r)&0xff000000 == 0 {
134 r >>= 16
135 } else {
136 r = ^(r >> 31)
137 }
138 139 g := yy1 - 22554*cb1 - 46802*cr1
140 if uint32(g)&0xff000000 == 0 {
141 g >>= 16
142 } else {
143 g = ^(g >> 31)
144 }
145 146 b := yy1 + 116130*cb1
147 if uint32(b)&0xff000000 == 0 {
148 b >>= 16
149 } else {
150 b = ^(b >> 31)
151 }
152 153 return uint8(r), uint8(g), uint8(b)
154 }
155 156 // YCbCr represents a fully opaque 24-bit Y'CbCr color, having 8 bits each for
157 // one luma and two chroma components.
158 //
159 // JPEG, VP8, the MPEG family and other codecs use this color model. Such
160 // codecs often use the terms YUV and Y'CbCr interchangeably, but strictly
161 // speaking, the term YUV applies only to analog video signals, and Y' (luma)
162 // is Y (luminance) after applying gamma correction.
163 //
164 // Conversion between RGB and Y'CbCr is lossy and there are multiple, slightly
165 // different formulae for converting between the two. This package follows
166 // the JFIF specification at https://www.w3.org/Graphics/JPEG/jfif3.pdf.
167 type YCbCr struct {
168 Y, Cb, Cr uint8
169 }
170 171 func (c YCbCr) RGBA() (uint32, uint32, uint32, uint32) {
172 // This code is a copy of the YCbCrToRGB function above, except that it
173 // returns values in the range [0, 0xffff] instead of [0, 0xff]. There is a
174 // subtle difference between doing this and having YCbCr satisfy the Color
175 // interface by first converting to an RGBA. The latter loses some
176 // information by going to and from 8 bits per channel.
177 //
178 // For example, this code:
179 // const y, cb, cr = 0x7f, 0x7f, 0x7f
180 // r, g, b := color.YCbCrToRGB(y, cb, cr)
181 // r0, g0, b0, _ := color.YCbCr{y, cb, cr}.RGBA()
182 // r1, g1, b1, _ := color.RGBA{r, g, b, 0xff}.RGBA()
183 // fmt.Printf("0x%04x 0x%04x 0x%04x\n", r0, g0, b0)
184 // fmt.Printf("0x%04x 0x%04x 0x%04x\n", r1, g1, b1)
185 // prints:
186 // 0x7e18 0x808d 0x7db9
187 // 0x7e7e 0x8080 0x7d7d
188 189 yy1 := int32(c.Y) * 0x10101
190 cb1 := int32(c.Cb) - 128
191 cr1 := int32(c.Cr) - 128
192 193 // The bit twiddling below is equivalent to
194 //
195 // r := (yy1 + 91881*cr1) >> 8
196 // if r < 0 {
197 // r = 0
198 // } else if r > 0xff {
199 // r = 0xffff
200 // }
201 //
202 // but uses fewer branches and is faster.
203 // The code below to compute g and b uses a similar pattern.
204 r := yy1 + 91881*cr1
205 if uint32(r)&0xff000000 == 0 {
206 r >>= 8
207 } else {
208 r = ^(r >> 31) & 0xffff
209 }
210 211 g := yy1 - 22554*cb1 - 46802*cr1
212 if uint32(g)&0xff000000 == 0 {
213 g >>= 8
214 } else {
215 g = ^(g >> 31) & 0xffff
216 }
217 218 b := yy1 + 116130*cb1
219 if uint32(b)&0xff000000 == 0 {
220 b >>= 8
221 } else {
222 b = ^(b >> 31) & 0xffff
223 }
224 225 return uint32(r), uint32(g), uint32(b), 0xffff
226 }
227 228 // YCbCrModel is the [Model] for Y'CbCr colors.
229 var YCbCrModel Model = ModelFunc(yCbCrModel)
230 231 func yCbCrModel(c Color) Color {
232 if _, ok := c.(YCbCr); ok {
233 return c
234 }
235 r, g, b, _ := c.RGBA()
236 y, u, v := RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
237 return YCbCr{y, u, v}
238 }
239 240 // NYCbCrA represents a non-alpha-premultiplied Y'CbCr-with-alpha color, having
241 // 8 bits each for one luma, two chroma and one alpha component.
242 type NYCbCrA struct {
243 YCbCr
244 A uint8
245 }
246 247 func (c NYCbCrA) RGBA() (uint32, uint32, uint32, uint32) {
248 // The first part of this method is the same as YCbCr.RGBA.
249 yy1 := int32(c.Y) * 0x10101
250 cb1 := int32(c.Cb) - 128
251 cr1 := int32(c.Cr) - 128
252 253 // The bit twiddling below is equivalent to
254 //
255 // r := (yy1 + 91881*cr1) >> 8
256 // if r < 0 {
257 // r = 0
258 // } else if r > 0xff {
259 // r = 0xffff
260 // }
261 //
262 // but uses fewer branches and is faster.
263 // The code below to compute g and b uses a similar pattern.
264 r := yy1 + 91881*cr1
265 if uint32(r)&0xff000000 == 0 {
266 r >>= 8
267 } else {
268 r = ^(r >> 31) & 0xffff
269 }
270 271 g := yy1 - 22554*cb1 - 46802*cr1
272 if uint32(g)&0xff000000 == 0 {
273 g >>= 8
274 } else {
275 g = ^(g >> 31) & 0xffff
276 }
277 278 b := yy1 + 116130*cb1
279 if uint32(b)&0xff000000 == 0 {
280 b >>= 8
281 } else {
282 b = ^(b >> 31) & 0xffff
283 }
284 285 // The second part of this method applies the alpha.
286 a := uint32(c.A) * 0x101
287 return uint32(r) * a / 0xffff, uint32(g) * a / 0xffff, uint32(b) * a / 0xffff, a
288 }
289 290 // NYCbCrAModel is the [Model] for non-alpha-premultiplied Y'CbCr-with-alpha
291 // colors.
292 var NYCbCrAModel Model = ModelFunc(nYCbCrAModel)
293 294 func nYCbCrAModel(c Color) Color {
295 switch c := c.(type) {
296 case NYCbCrA:
297 return c
298 case YCbCr:
299 return NYCbCrA{c, 0xff}
300 }
301 r, g, b, a := c.RGBA()
302 303 // Convert from alpha-premultiplied to non-alpha-premultiplied.
304 if a != 0 {
305 r = (r * 0xffff) / a
306 g = (g * 0xffff) / a
307 b = (b * 0xffff) / a
308 }
309 310 y, u, v := RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
311 return NYCbCrA{YCbCr{Y: y, Cb: u, Cr: v}, uint8(a >> 8)}
312 }
313 314 // RGBToCMYK converts an RGB triple to a CMYK quadruple.
315 func RGBToCMYK(r, g, b uint8) (uint8, uint8, uint8, uint8) {
316 rr := uint32(r)
317 gg := uint32(g)
318 bb := uint32(b)
319 w := rr
320 if w < gg {
321 w = gg
322 }
323 if w < bb {
324 w = bb
325 }
326 if w == 0 {
327 return 0, 0, 0, 0xff
328 }
329 c := (w - rr) * 0xff / w
330 m := (w - gg) * 0xff / w
331 y := (w - bb) * 0xff / w
332 return uint8(c), uint8(m), uint8(y), uint8(0xff - w)
333 }
334 335 // CMYKToRGB converts a [CMYK] quadruple to an RGB triple.
336 func CMYKToRGB(c, m, y, k uint8) (uint8, uint8, uint8) {
337 w := 0xffff - uint32(k)*0x101
338 r := (0xffff - uint32(c)*0x101) * w / 0xffff
339 g := (0xffff - uint32(m)*0x101) * w / 0xffff
340 b := (0xffff - uint32(y)*0x101) * w / 0xffff
341 return uint8(r >> 8), uint8(g >> 8), uint8(b >> 8)
342 }
343 344 // CMYK represents a fully opaque CMYK color, having 8 bits for each of cyan,
345 // magenta, yellow and black.
346 //
347 // It is not associated with any particular color profile.
348 type CMYK struct {
349 C, M, Y, K uint8
350 }
351 352 func (c CMYK) RGBA() (uint32, uint32, uint32, uint32) {
353 // This code is a copy of the CMYKToRGB function above, except that it
354 // returns values in the range [0, 0xffff] instead of [0, 0xff].
355 356 w := 0xffff - uint32(c.K)*0x101
357 r := (0xffff - uint32(c.C)*0x101) * w / 0xffff
358 g := (0xffff - uint32(c.M)*0x101) * w / 0xffff
359 b := (0xffff - uint32(c.Y)*0x101) * w / 0xffff
360 return r, g, b, 0xffff
361 }
362 363 // CMYKModel is the [Model] for CMYK colors.
364 var CMYKModel Model = ModelFunc(cmykModel)
365 366 func cmykModel(c Color) Color {
367 if _, ok := c.(CMYK); ok {
368 return c
369 }
370 r, g, b, _ := c.RGBA()
371 cc, mm, yy, kk := RGBToCMYK(uint8(r>>8), uint8(g>>8), uint8(b>>8))
372 return CMYK{cc, mm, yy, kk}
373 }
374