-
Notifications
You must be signed in to change notification settings - Fork 19
/
Color Conversion Algorithms.htm
executable file
·296 lines (240 loc) · 11.6 KB
/
Color Conversion Algorithms.htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
<html>
<head>
<title>Color Conversion Algorithms</title>
</head>
<body bgcolor="#FFFFFF" background="bkgr.gif">
<p align="center"><big><strong><big><big>Color Conversion Algorithms</big></big></strong></big></p>
<hr>
<p><strong><big>Contents</big></strong>
<ul>
<li><a href="#RGB to HSV & HSV to RGB">RGB to HSV & HSV to RGB</a></li>
<li><a href="#RGB to YIQ & YIQ to RGB">RGB to YIQ & YIQ to RGB</a></li>
<li><a href="#RGB to XYZ & XYZ to RGB">RGB to XYZ & XYZ to RGB</a></li>
<li><a href="#XYZ to CIE L*a*b* (CIELAB) & CIELAB to XYZ">XYZ to CIE L*a*b* (CIELAB)
& CIELAB to XYZ</a></li>
<li><a href="#XYZ to CIELUV & CIELUV to XYZ">XYZ to CIELUV & CIELUV to XYZ</a></li>
</ul>
<hr>
<p><a name="RGB to HSV & HSV to RGB"><font color="#FF8000"><big><strong>RGB to HSV
& HSV to RGB</strong></big></font></a></p>
<p>The Hue/Saturation/Value model was created by A. R. Smith in 1978. It is based on such
intuitive color characteristics as tint, shade and tone (or family, purety and intensity).
The coordinate system is cylindrical, and the colors are defined inside a hexcone. The hue
value H runs from 0 to 360º. The saturation S is the degree of strength or purity and is
from 0 to 1. Purity is how much white is added to the color, so S=1 makes the purest color
(no white). Brightness V also ranges from 0 to 1, where 0 is the black.</p>
<p>There is no transformation matrix for RGB/HSV conversion, but the algorithm follows:</p>
<pre><strong><font color="#408080">// r,g,b values are from 0 to 1
// h = [0,360], s = [0,1], v = [0,1]
// if s == 0, then h = -1 (undefined)</font></strong></pre>
<pre><strong><font color="#408080">void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v )
{
float min, max, delta;</font></strong></pre>
<pre><strong><font color="#408080"> min = MIN( r, g, b );
max = MAX( r, g, b );
*v = max; // v</font></strong></pre>
<pre><strong><font color="#408080"> delta = max - min;</font></strong></pre>
<pre><strong><font color="#408080"> if( max != 0 )
*s = delta / max; // s
else {
// r = g = b = 0 // s = 0, v is undefined
*s = 0;
*h = -1;
return;
}</font></strong></pre>
<pre><strong><font color="#408080"> if( r == max )
*h = ( g - b ) / delta; // between yellow & magenta
else if( g == max )
*h = 2 + ( b - r ) / delta; // between cyan & yellow
else
*h = 4 + ( r - g ) / delta; // between magenta & cyan</font></strong></pre>
<pre><strong><font color="#408080"> *h *= 60; // degrees
if( *h < 0 )
*h += 360;</font></strong></pre>
<pre><strong><font color="#408080">}</font></strong></pre>
<pre><strong><font color="#408080">void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v )
{
int i;
float f, p, q, t;</font></strong></pre>
<pre><strong><font color="#408080"> if( s == 0 ) {
// achromatic (grey)
*r = *g = *b = v;
return;
}</font></strong></pre>
<pre><strong><font color="#408080"> h /= 60; // sector 0 to 5
i = floor( h );
f = h - i; // factorial part of h
p = v * ( 1 - s );
q = v * ( 1 - s * f );
t = v * ( 1 - s * ( 1 - f ) );</font></strong></pre>
<pre><strong><font color="#408080"> switch( i ) {
case 0:
*r = v;
*g = t;
*b = p;
break;
case 1:
*r = q;
*g = v;
*b = p;
break;
case 2:
*r = p;
*g = v;
*b = t;
break;
case 3:
*r = p;
*g = q;
*b = v;
break;
case 4:
*r = t;
*g = p;
*b = v;
break;
default: // case 5:
*r = v;
*g = p;
*b = q;
break;
}</font></strong></pre>
<pre><big><strong>}</strong></big></pre>
<p>When programming in Java, use the <font face="Courier">RGBtoHSB</font> and <font
face="Courier">HSBtoRGB</font> functions from the <font face="Courier">java.awt.Color</font>
class.</p>
<hr>
<p><a name="RGB to YIQ & YIQ to RGB"><font color="#FF8000"><big><strong>RGB to YIQ
& YIQ to RGB</strong></big></font></a></p>
<p>The YIQ system is the color primary system adopted by National Television System
Committee (NTSC) for color TV broadcasting. The YIQ color solid is made by a linear
transformation of the RGB cube. Its purpose is to exploit certain characteristics of the
human eye to maximize the utilization of a fixed bandwidth. The human visual system is
more sensitive to changes in luminance than to changes in hue or saturation, and thus a
wider bandwidth should be dedicated to luminance than to color information. <strong>Y</strong>
is similar to perceived luminance, <strong>I</strong> and <strong>Q</strong> carry color
information and some luminance information. The <strong>Y</strong> signal usually has 4.2
MHz bandwidth in a 525 line system. Originally, the <strong>I </strong>and <strong>Q</strong>
had different bandwidths (1.5 and 0.6 MHz), but now they commonly have the same bandwidth
of 1 MHz. </p>
<p>Here is the RGB -> YIQ conversion:</p>
<p><strong><font face="Courier" color="#408080"> [ Y
] [ 0.299 0.587 0.114 ] [ R ]<br>
[ I ] = [ 0.596 -0.275 -0.321 ] [ G ]<br>
[ Q ] [ 0.212 -0.523 0.311 ]
[ B ]</font></strong></p>
<p>Here is the YIQ -> RGB conversion:</p>
<p><strong><font face="Courier" color="#408080"> [ R
] [ 1 0.956 0.621 ] [ Y ]<br>
[ G ] = [ 1 -0.272 -0.647 ] [ I ]<br>
[ B ] [ 1 -1.105 1.702 ] [ Q
]</font></strong></p>
<hr>
<p><a name="RGB to XYZ & XYZ to RGB"><font color="#FF8000"><big><strong>RGB to XYZ
& XYZ to RGB</strong></big></font></a></p>
<p align="left">RGB values in a particular set of primaries can be transformed to and from
CIE XYZ via a 3x3 matrix transform. These transforms involve <a href="glossary.htm">tristimulus
values</a>, that is a set of three linear-light components that conform to the <a
href="glossary.htm">CIE color-matching functions</a>. CIE XYZ is a special set of
tristimulus values. In XYZ, any color is represented as a set of positive values.</p>
<p align="left">To transform from <strong>XYZ</strong> to <strong>RGB</strong> (with <a
href="glossary.htm">D65 white point</a>), the matrix transform used is <a
href="glossary.htm">[3]</a>:</p>
<p align="left"><font face="Courier"> [ R ] [ 3.240479
-1.537150 -0.498535 ] [ X ]<br>
[ G ] = [ -0.969256 1.875992 0.041556 ] * [ Y ]<br>
[ B ] [ 0.055648 -0.204043 1.057311 ] [ Z
].</font></p>
<p align="left">The range for valid R, G, B values is [0,1]. Note, this matrix has
negative coefficients. Some XYZ color may be transformed to RGB values that are negative
or greater than one. This means that not all visible colors can be produced using the RGB
system.</p>
<p>The inverse transformation matrix is as follows:</p>
<p align="left"><font face="Courier"> [ X ] [ 0.412453
0.357580 0.180423 ] [ R ] **<br>
[ Y ] = [ 0.212671 0.715160 0.072169 ] * [ G ]<br>
[ Z ] [ 0.019334 0.119193 0.950227
] [ B ].</font></p>
<hr>
** February 20, 2000 - typo in this line of the matrix was corrected
(0.189423 to 0.180423), thanks to Michal
Karczmarek, University of Toronto
<hr>
<p><a name="XYZ to CIE L*a*b* (CIELAB) & CIELAB to XYZ"><font color="#FF8040"><big><strong>XYZ
to CIE L*a*b* (CIELAB) & CIELAB to XYZ</strong></big></font></a></p>
<p>CIE 1976 L*a*b* is based directly on CIE XYZ and is an attampt to linearize the
perceptibility of color differences. The non-linear relations for L*, a*, and b* are
intended to mimic the logarithmic response of the eye. Coloring information is referred to
the color of the white point of the system, subscript n.</p>
<blockquote>
<blockquote>
<p><font color="#408080"><big>L<sup>*</sup> = 116 <strong>*</strong> (Y/Yn)</big><sup>1/3</sup><big>
- 16 for Y/Yn > 0.008856<br>
L<sup>*</sup> = 903.3 <strong>*</strong>
Y/Yn otherwise</font></big></p>
<p><font color="#408080"><big>a<sup>*</sup> = 500 <strong>*</strong> ( f(X/Xn) - f(Y/Yn) )<br>
b<sup>*</sup> = 200 <strong>*</strong> ( f(Y/Yn) - f(Z/Zn) )<br>
where f(t) = t</big><sup>1/3</sup><big> for t
> 0.008856<br>
f(t) =
7.787 <strong>*</strong> t + 16/116 otherwise</font></big></p>
</blockquote>
</blockquote>
<p>Here Xn, Yn and Zn are the tristimulus values of the reference white.<br>
The reverse transformation (for Y/Yn > 0.008856) is</p>
<blockquote>
<blockquote>
<p><font color="#408080"><big>X = Xn <strong>*</strong> ( P + a<sup>*</sup> / 500 ) <sup>3</sup><br>
Y = Yn <strong>*</strong> P <sup>3</sup><br>
Z = Zn <strong>*</strong> ( P - b<sup>*</sup> / 200 ) <sup>3</sup><br>
where P = (L<sup>*</sup> + 16) / 116</big></font></p>
</blockquote>
</blockquote>
<hr>
<p><a name="XYZ to CIELUV & CIELUV to XYZ"><font color="#FF8040"><big><strong>XYZ to
CIELUV & CIELUV to XYZ</strong></big></font></a></p>
<p>CIE 1976 L*u*u* (CIELUV) is based directly on CIE XYZ and is another attampt to
linearize the perceptibility of color differences. The non-linear relations for L*, u*,
and v* are given below:</p>
<blockquote>
<blockquote>
<p><font color="#408080"><big>L<sup>*</sup> = <font color="#408080">1</font>16 <strong>*</strong>
(Y/Yn)</big><sup>1/3</sup><big> - 16</big><br>
<big>u<sup>*</sup> = 13L<sup>*</sup> <strong>*</strong> ( u' - u<sub>n</sub>' )<br>
v<sup>*</sup> = 13L<sup>*</sup><strong> *</strong> ( v' - v<sub>n</sub>' )</font></big></p>
</blockquote>
</blockquote>
<p>The quantities u<sub>n</sub>' and v<sub>n</sub>' refer to the reference white or
the light source; for the 2° observer and illuminant C, u<sub>n</sub>' = 0.2009, v<sub>n</sub>'
= 0.4610 [<a href="glossary.htm"> 1 </a>]. Equations for u' and v' are given below:</p>
<p><font color="#408080"><big> u' = 4X / (X +
15Y + 3Z) = 4x / ( -2x + 12y + 3 )<br>
v' = 9Y / (X + 15Y + 3Z) = 9y / ( -2x + 12y + 3
).</big></font></p>
<p>The transformation from (u',v') to (x,y) is:</p>
<p><font color="#408080"><big> x = 27u' / ( 18u'
- 48v' + 36 )<br>
y = 12v' / ( 18u' - 48v' + 36 ).<br>
</big></font><br>
The transformation from CIELUV to XYZ is performed as following:</p>
<blockquote>
<p><font color="#408080"><big>u' = u / ( 13L<sup>*</sup>) + u<sub>n</sub><br>
v' = v / ( 13L<sup>*</sup> ) + v<sub>n</sub><br>
Y = (( L* + 16 ) / 116 )<sup>3</sup><br>
X = - 9Yu' / (( u' - 4 ) v' - u'v' )<br>
Z = ( 9Y - 15v'Y - v'X ) / 3v'</big></font></p>
</blockquote>
<P>
<b>Disclaimer:</b> I (N. Schaller) received e-mail from Alexandre
Campo ([email protected]) stating that he felt the last three lines
above should be
<P>
Y = (( L* + 16 ) / 116 )^3 * Yn
<P>
and then simplify by noticing u'v' - u'v' -4v' = -4v'
<P>
X = 9Yu' / 4v'
<P>
I have not verified this, but have added it for your purusal.
</body>
</html>