47 Colour Conversion Algorithms
From Director Online Wiki
-- code converted by Josh Chunick -- Resources: -- http://www.easyrgb.com/math.html -- http://www.brucelindbloom.com/index.html?Equations.html -- http://www.cs.rit.edu/~ncs/color/a_spaces.html -- http://www.f4.fhtw-berlin.de/~barthel/ImageJ/ColorInspector/HTMLHelp/farbraumJava.htm -- http://www.efg2.com/Lab/Graphics/Colors/index.html -- http://www.nebulus.org/tutorials/2d/photoshop/color/index.html -- convert rgb or hex colours to Director's current frame palette. -- this is affected by the frame channel palette setting -- so, you should test using _movie.framePalette first... -- returns a negative value for built-in palettes: --systemMac -1 --systemWin -102 --rainbow -2 --grayscale -3 --pastels -4 --vivid -5 --ntsc -6 --metallic -7 --web16 -8 --systemWinDir4 -101 -- a frame set to a member of type #palette have a positive -- value equal to it's member number. on ToPaletteIndex(aColor) if ilk(aColor) = #color then return aColor.paletteIndex if stringP(aColor) then return color(aColor).paletteIndex return -1 end -- note, this returns the RGB colour from the index of Director's current frame palette. on PaletteIndexToRGB(tColorIndex, tPaletteRef) img = image(1,1,32) img.paletteRef = tPaletteRef img.setPixel(0, 0, paletteIndex(tColorIndex)) col = img.getPixel(0, 0) col.colorType = #rgb return rgb(col) end on RGBtoInteger(aColor) R = aColor.red G = aColor.green B = aColor.blue return R *256*256 + G *256 + B end --on aRGBtoInteger(a, R, G, B) -- R = aColor.red -- G = aColor.green -- B = aColor.blue -- int = R *256*256 + G *256 + B -- a = (int / -16777216) *256*256*256 -- return -(int + a) --end --on IntegertoRGB(int) -- R = aColor.red -- G = aColor.green -- B = aColor.blue -- return R *256*256 + G *256 + B --end on CMYKtoRGB (C, M, Y, K) if C > 1 or M > 1 or Y > 1 or K > 1 then C = C / 100.0 M = M / 100.0 Y = Y / 100.0 K = K / 100.0 end if R = (1 - C * (1 - K) - K) * 256 G = (1 - M * (1 - K) - K) * 256 B = (1 - Y * (1 - K) - K) * 256 return color(R, G, B) end on RGBtoCMYK (R, G, B) C = 1 - (R / 255.0) M = 1 - (G / 255.0) Y = 1 - (B / 255.0) if min(C, M, Y) = 1 then return [0, 0, 0, 1] K = min(C,M,Y) C = (C - K) / (1 - K) M = (M - K) / (1 - K) Y = (Y - K) / (1 - K) return [C, M, Y, K] end on RGBtoCMY (R, G, B) C = 1 - (R / 255.0) M = 1 - (G / 255.0) Y = 1 - (B / 255.0) return [C, M, Y] end on CMYtoRGB (C, M, Y) if C > 1 or M > 1 or Y > 1 then C = C / 100.0 M = M / 100.0 Y = Y / 100.0 K = K / 100.0 end if R = (1 - C) * 255 G = (1 - M) * 255 B = (1 - Y) * 255 return color(R, G, B) end on CMYtoCMYK (C, M, Y) K = 1 if C < K then K = C if M < K then K = M if Y < K then K = Y C = (C - K) / (1 - K) M = (M - K) / (1 - K) Y = (Y - K) / (1 - K) return [C, M, Y, K] end on CMYKtoCMY (C, M, Y, K) C = ( C * ( 1 - K ) + K ) M = ( M * ( 1 - K ) + K ) Y = ( Y * ( 1 - K ) + K ) return [C, M, Y] end on RGBtoHex(R, G, B) return color(R, G, B).hexString() end on HextoRGB(aHex) return rgb(aHex) end -- 0, 3, 6, 9, C, F -- 0%, 20%, 40%, 60%, 80%, 100% on RGBtoWebSafe(R, G, B) webSafe = [0, 51, 102, 153, 204, 255] webSafe.sort() R1 = webSafe[webSafe.findPosNear(R)] if R < max(0, R1 - 25.5) then R1 = webSafe[max(1,webSafe.getPos(R) - 1)] G1 = webSafe[webSafe.findPosNear(G)] if G < max(0, G1 - 25.5) then G1 = webSafe[max(1,webSafe.getPos(G) - 1)] B1 = webSafe[webSafe.findPosNear(B)] if B < max(0, B1 - 25.5) then B1 = webSafe[max(1,webSafe.getPos(B) - 1)] aColor = rgb(R1, G1, B1) return aColor.hexString() end on WebSafetoRGB(aHex) webSafe = ["0": 0, "3": 51, "6": 102, "9": 153, "C": 204, "F": 255] R = webSafe.getProp(aHex.char[2]) G = webSafe.getProp(aHex.char[4]) B = webSafe.getProp(aHex.char[6]) return color(R, G, B) end on HextoWebSafe(aHex) aColor = rgb(aHex) webSafe = [0, 51, 102, 153, 204, 255] webSafe.sort() R = webSafe[webSafe.findPosNear(aColor.red)] if aColor.red < max(0, R - 25.5) then R = webSafe[max(1,webSafe.getPos(R) - 1)] G = webSafe[webSafe.findPosNear(aColor.green)] if aColor.green < max(0, G - 25.5) then G = webSafe[max(1,webSafe.getPos(G) - 1)] B = webSafe[webSafe.findPosNear(aColor.blue)] if aColor.blue < max(0, B - 25.5) then B = webSafe[max(1,webSafe.getPos(B) - 1)] aColor = rgb(R, G, B) return aColor.hexString() end -- Colour Conversion Algorithms -- http://www.easyrgb.com/math.html -- http://www.cs.rit.edu/~ncs/color/t_convert.html -- RGB to Hue, Saturation, Value -- R, G, B values are from 0 to 1 -- h = [0,360], s = [0,1], v = [0,1] on RGBtoHSB(R, G, B) var_R = ( R / 255.0 ) var_G = ( G / 255.0 ) var_B = ( B / 255.0) var_Min = min( var_R, var_G, var_B ) var_Max = max( var_R, var_G, var_B ) del_Max = var_Max - var_Min V = var_Max if del_Max = 0 then H = 0 S = 0 else S = del_Max / var_Max del_R = ( ( ( var_Max - var_R ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max del_G = ( ( ( var_Max - var_G ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max del_B = ( ( ( var_Max - var_B ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max if ( var_R = var_Max ) then H = del_B - del_G else if ( var_G = var_Max ) then H = ( 1 / 3.0 ) + del_R - del_B else if ( var_B = var_Max ) then H = ( 2 / 3.0 ) + del_G - del_R end if if H < 0 then H = H + 1 if H > 1 then H = H - 1 end if return [H, S, V] end on HSBtoRGB(H, S, V) if S = 0 then R = V * 255 G = V * 255 B = V * 255 else var_h = H * 6 if var_h = 6 then var_h = 0 var_i = integer(var_h) - (var_h < integer(var_h)) var_1 = V * ( 1 - S ) var_2 = V * ( 1 - S * ( var_h - var_i ) ) var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) ) if var_i = 0 then var_r = V var_g = var_3 var_b = var_1 else if var_i = 1 then var_r = var_2 var_g = V var_b = var_1 else if var_i = 2 then var_r = var_1 var_g = V var_b = var_3 else if var_i = 3 then var_r = var_1 var_g = var_2 var_b = V else if var_i = 4 then var_r = var_3 var_g = var_1 var_b = V else var_r = V var_g = var_1 var_b = var_2 end if R = var_r * 255 G = var_g * 255 B = var_b * 255 end if return color(R, G, B) end -- alternative functions to the HSV functions -- in case the programmer knows HSB as the -- HSV colour space (Hue, Saturation, Value) on RGBtoHSV (R, G, B) return RGBtoHSB(R, G, B) end on HSVtoRGB (H, S, V) return HSBtoRGB(H, S, V) end -- RGB to Hue, Saturation, Luminosity -- dependencies: HueToRGB() on RGBtoHSL (R, G, B) R = R / 255.0 G = G / 255.0 B = B / 255.0 vMin = min(R, G, B) vMax = max(R, G, B) dMax = vMax - vMin L = (vMax + vMin) / 2 if dMax = 0 then H = 0 S = 0 else if L < 0.5 then S = dMax / float(vMax + vMin) else S = dMax / float(2 - vMax - vMin) end if dR = (((vMax - R) / 6.0) + (dMax / 2.0))/float(dMax) dG = (((vMax - G) / 6.0) + (dMax / 2.0))/float(dMax) dB = (((vMax - B) / 6.0) + (dMax / 2.0))/float(dMax) if R = vMax then H = B - G else if G = vMax then H = (1/3.0) + R - B else if B = vMax then H = (2/3.0) + G - R end if if H < 0 then H = H + 1 if H > 1 then H = H - 1 end if return [H, S, L] end -- this function calls another function: HuetoRGB( v1, v2, vH ) on HSLtoRGB (H, S, L) if S = 0 then R = L * 255 G = L * 255 B = L * 255 else if L < 0.5 then v2 = L * (1 + S) else v2 = (L + S) - (S * L) end if v1 = 2 * L - v2 R = 255 * HuetoRGB(v1, v2, H + (1/3.0)) G = 255 * HuetoRGB(v1, v2, H) B = 255 * HuetoRGB(v1, v2, H - (1/3.0)) end if return color(R, G, B) end on HuetoRGB( v1, v2, vH ) if vH < 0 then vH = vH + 1 if vH > 1 then vH = vH - 1 if ( 6 * vH ) < 1 then return (v1 + ( v2 - v1 ) * 6 * vH) end if if ( 2 * vH ) < 1 then return v2 end if if ( 3 * vH ) < 2 then return (v1 + ( v2 - v1 ) * ( ( 2.0 / 3.0 ) - vH ) * 6) end if return v1 end -- alternative versions of the HSL functions -- in case the user knows the HSL colour space as HLS or HSI (Hue, Saturation, Intensity) on HLStoRGB (H, L, S) return HSLtoRGB (H, S, L) end on RGBtoHLS (R, G, B) return RGBtoHSL (R, G, B) end on HSItoRGB (H, S, I) return HSLtoRGB (H, S, I) end on RGBtoHSI (R, G, B) return RGBtoHSI (R, G, B) end on RGBtoXYZ (R, G, B) R = ( R / 255.0 ) --Where R = 0 - 255 G = ( G / 255.0 ) --Where G = 0 - 255 B = ( B / 255.0 ) --Where B = 0 - 255 if R > 0.04045 then R = power((( R + 0.055 ) / 1.055 ), 2.4) else R = R / 12.92 end if if G > 0.04045 then G = power((( G + 0.055 ) / 1.055 ), 2.4) else G = G / 12.92 end if if B > 0.04045 then B = power((( B + 0.055 ) / 1.055 ), 2.4) else B = B / 12.92 end if R = R * 100 G = G * 100 B = B * 100 --Observer. = 2°, Illuminant = D65 X = (0.412453 * R) + (0.357580 * G) + (0.180423 * B) Y = (0.212671 * R) + (0.715160 * G) + (0.072169 * B) Z = (0.019334 * R) + (0.119193 * G) + (0.950227 * B) return [X, Y, Z] end on XYZtoRGB (X, Y, Z) X = X / 100.0 --Where X = 0 - 95.047 Y = Y / 100.0 --Where Y = 0 - 100.000 Z = Z / 100.0 --Where Z = 0 - 108.883 --Observer = 2°, Illuminant = D65 R = X * 3.2406 + Y * -1.5372 + Z * -0.4986 G = X * -0.9689 + Y * 1.8758 + Z * 0.0415 B = X * 0.0557 + Y * -0.2040 + Z * 1.0570 if ( R > 0.0031308 ) then R = 1.055 * power(R, 1 / 2.4) - 0.055 else R = 12.92 * R end if if ( G > 0.0031308 ) then G = 1.055 * power(G, 1 / 2.4) - 0.055 else G = 12.92 * G end if if ( B > 0.0031308 ) then B = 1.055 * power(B, 1 / 2.4) - 0.055 else B = 12.92 * B end if R = R * 255 G = G * 255 B = B * 255 return color(R, G, B) end on XYZtoCIELab (X, Y, Z) -- Observer= 2°, Illuminant= D65 X = X / 95.047 --refX = 95.047 Y = Y / 100.000 --refY = 100.000 Z = Z / 108.883 --refZ = 108.883 if ( X > 0.008856 ) then X = power(X, 1.0/3.0) else X = ( 7.787 * X ) + ( 16.0 / 116.0 ) end if if ( Y > 0.008856 ) then Y = power(Y, 1.0/3.0) else Y = ( 7.787 * Y ) + ( 16.0 / 116.0 ) end if if ( Z > 0.008856 ) then Z = power(Z, 1.0/3.0) else Z = ( 7.787 * Z ) + ( 16.0 / 116.0 ) end if L = ( 116 * Y ) - 16 a = 500 * ( X - Y ) b = 200 * ( Y - Z ) return [L, a, b] end on CIELabtoXYZ (L, a, b) Y = ( L + 16 ) / 116.0 X = ( a / 500.0 )+ Y Z = Y - ( b / 200.0 ) if ( power(Y, 3) > 0.008856 ) then Y = power( Y, 3) else Y = ( Y - (16.0 / 116.0 )) / 7.787 end if if ( power(X, 3) > 0.008856 ) then X = power(X, 3) else X = ( X - (16.0 / 116.0) ) / 7.787 end if if ( power(Z, 3) > 0.008856 ) then Z = power(Z, 3) else Z = ( Z - (16.0 / 116.0) ) / 7.787 end if X = 95.047 * X --refX = 95.047 Observer= 2°, Illuminant= D65 Y = 100.000 * Y --refY = 100.000 Z = 108.883 * Z --refZ = 108.883 return [X, Y, Z] end on XYZtoCIELuv (X, Y, Z) U = ( 4 * X ) / ( X + ( 15 * Y ) + ( 3 * Z ) ) V = ( 9 * Y ) / ( X + ( 15 * Y ) + ( 3 * Z ) ) Y = Y / 100.0 if ( Y > 0.008856 ) then Y = power(Y, 1/3.0) else Y = ( 7.787 * Y ) + ( 16 / 116.0 ) end if refX = 95.047 --Observer= 2°, Illuminant= D65 refY = 100.000 refZ = 108.883 refU = ( 4 * refX ) / ( refX + ( 15 * refY ) + ( 3 * refZ ) ) refV = ( 9 * refY ) / ( refX + ( 15 * refY ) + ( 3 * refZ ) ) L = ( 116 * Y ) - 16 U = 13 * L * ( U - refU ) V = 13 * L * ( V - refV ) return [L, U, V] end on CIELuvtoXYZ (L, U, V) Y = ( L + 16 ) / 116.0 if ( power(Y, 3) > 0.008856 ) then Y = power(Y, 3) else Y = ( Y - (16 / 116.0) ) / 7.787 end if refX = 95.047 --Observer= 2°, Illuminant= D65 refY = 100.000 refZ = 108.883 refU = ( 4 * refX ) / ( refX + ( 15 * refY ) + ( 3 * refZ ) ) refV = ( 9 * refY ) / ( refX + ( 15 * refY ) + ( 3 * refZ ) ) U = U / ( 13 * L ) + refU V = U / ( 13 * L ) + refV Y = Y * 100 X = - ( 9 * Y * U ) / ( ( U - 4 ) * V - U * V ) Z = ( 9 * Y - ( 15 * V * Y ) - ( V * X ) ) / ( 3 * V ) return [X, Y, Z] end on XYZtoHunterLab (X, Y, Z) HL = 10 * sqrt( Y ) Ha = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) ) Hb = 7 * ( ( Y - ( 0.847 * Z ) ) / sqrt( Y ) ) return [HL, Ha, Hb] end on HunterLabtoXYZ (HL, Ha, Hb) Y = HL / 10 X = Ha / 17.5 * HL / 10 Z = Hb / 7 * HL / 10 Y = power(Y,2) X = ( X + Y ) / 1.02 Z = -( Z - Y ) / 0.847 return [X, Y, Z] end --Where X = 0 - 95.047 Observer. = 2°, Illuminant = D65 --Where Y = 0 - 100.000 --Where Z = 0 - 108.883 on XYZtoYxy (X, Y, Z) Y = Y xx = X / ( X + Y + Z ) yy = Y / ( X + Y + Z ) return [Y, xx, yy] end --Where Y = 0 - 100 --Where xx = 0 - 1 --Where yy = 0 - 1 on YxytoXYZ (Y, xx, yy) X = xx * ( Y / yy ) Y = Y Z = ( 1 - xx - yy ) * ( Y / yy ) return [X, Y, Z] end -- The YIQ system is the colour primary system -- adopted by NTSC for colour television broadcasting on RGBtoYIQ (R, G, B) Y = (0.299 * R) + (0.587 * G) + (0.114 * B) I = (0.596 * R) + (-0.275 * G) + (-0.321 * B) Q = (0.212 * R) + (-0.523 * G) + (0.311 * B) return [Y, I, Q] end on YIQtoRGB (Y, I, Q) R = (1.0 * Y) + (0.956 * I) + (0.621 * Q) G = (1.0 * Y) + (-0.272 * I) + (-0.647 * Q) B = (1.0 * Y) + (-1.105 * I) + (1.702 * Q) return color(R, G, B) end -- YUV is like YIQ, except that it is the PAL/European standard on RGBtoYUV (R, G, B) Y = (0.299 * R) + (0.587 * G) + (0.114 * B) U = (-0.147 * R) + (-0.289 * G) + (0.437 * B) V = (0.615 * R) + (-0.515 * G) + (-0.100 * B) return [Y, U, V] end on YUVtoRGB (Y, U, V) R = (1.0 * Y) + (0.0 * U) + (1.140 * V) G = (1.0 * Y) + (-0.394 * U) + (-0.581 * V) B = (1.0 * Y) + (2.028 * U) + (0.0 * V) return color(R, G, B) end -- ****************************************************************** -- Sub Functions -- ****************************************************************** on CIELabtoRGB (L, a, b) XYZ = CIELabToXYZ(L, a, b) return XYZtoRGB(XYZ[1], XYZ[2], XYZ[3]) end on RGBtoCIELab (R, G, B) XYZ = RGBtoXYZ(R, G, B) return XYZtoCIELab (XYZ[1], XYZ[2], XYZ[3]) end -- ********************************************************************************* -- XYZ (Tristimulus) Reference values of a perfect reflecting diffuser -- ********************************************************************************* -- Observer 2° (CIE 1931) 10° (CIE 1964) --Illuminant X2 Y2 Z2 X10 Y10 Z10 -- --A (Tungsten) 109.850 100.0 35.585 111.144 100.0 35.200 --C 98.074 100.0 118.232 97.285 100.0 116.145 --D50 96.422 100.0 82.521 96.720 100.0 81.427 --D55 95.682 100.0 92.149 95.799 100.0 90.926 --D65 (Daylight) 95.047 100.0 108.883 94.811 100.0 107.304 --D75 94.972 100.0 122.638 94.416 100.0 120.641 --D93 (CRT monitor) --F2 (Fluorescent) 99.187 100.0 67.395 103.280 100.0 69.026 --F7 95.044 100.0 108.755 95.792 100.0 107.687 --F11 100.966 100.0 64.370 103.866 100.0 65.620 --Temperature x y Dir y/x --(Kelvin) --2000 0.52669 0.41331 1.33101 --2105 0.51541 0.41465 1.39021 --2222 0.50338 0.41525 1.45962 --2353 0.49059 0.41498 1.54240 --2500 0.47701 0.41368 1.64291 --2677 0.463 0.41121 1.76811 % error in table [3], estimated values --2857 0.446 0.40742 1.92863 --3077 0.43156 0.40216 2.14300 --3333 0.41502 0.39535 2.44455 --3636 0.39792 0.38690 2.90309 --4000 0.38045 0.37676 3.68730 --4444 0.36276 0.36496 5.34398 --5000 0.34510 0.35162 11.17883 --5714 0.32775 0.33690 -39.34888 --6667 0.31101 0.32116 -6.18336 --8000 0.29518 0.30477 -3.08425 --10000 0.28063 0.28828 -1.93507 -- ************************************************************ -- The below are from: -- http://www.srgb.com/hpsrgbprof/sld001.htm -- however, I do not know if the math is correct -- ************************************************************ on XYZD65toXYZD50 (X65, Y65, Z65) X50 = (1.0479 * X65) + (.0229 * Y65) + (-0.0502 * Z65) Y50 = (.0296 * X65) + (.9904 * Y65) + (-0.0171 * Z65) Z50 = (-0.0092 * X65) + (.0151 * Y65) + (.7519 * Z65) return [X50, Y50, Z50] end -- 2.2 Gamma on XYZD50toRGB (X, Y, Z) R = (.4361 * X) + (.2664 * Y) + (.1431 * Z) G = (.2225 * X) + (.7169 * Y) + (.0606 * Z) B = (.0139 * X) + (.0971 * Y) + (.7141 * Z) return color(R, G, B) end --on XYZtoRGB (X, Y, Z) -- R = (.8951 * X) + (.2664 * Y) + (-0.1614 * Z) -- G = (-0.7502 * X) + (1.7135 * Y) + (.0367 * Z) -- B = (.0389 * X) + (.0685 * Y) + (1.0296 * Z) -- return color(R, G, B) --end -- Gamma Equation -- For each R, G, B value: -- if RGB <= 0.03928 -- RGB' = RGB/12.92 -- else -- RGB' = power((0.55 + RGB)/1.055), 2.4) -- end if -- Note: RGB normalized to 0.0 to 0.1 --on ceil myNum -- --return integer(myNum + 0.499999999999999) -- --end -- --on floor myNum -- --return integer(myNum - 0.499999999999999) -- --end --ITU-R BT.709 Primaries and white point D65 [9]. Valid for sRGB. on sRGBtoXYZ (R, G, B) R = R/255.0 G = G/255.0 B = B/255.0 X = (0.4124 * R) + (0.3576 * G) + (0.1805 * B) Y = (0.2126 * R) + (0.7152 * G) + (0.0722 * B) Z = (0.0193 * R) + (0.1192 * G) + (0.9505 * B) return [X * 100, Y * 100, Z * 100] end on XYZtosRGB (X, Y, Z) X = X/100.0 Y = Y/100.0 Z = Z/100.0 R = (3.2410 * X) + (-1.5374 * Y) + ( -0.4986 * Z) G = (-0.9692 * X) + ( 1.8760 * Y) + ( 0.0416 * Z) B = (0.0556 * X) + ( -0.2040 * Y) + ( 1.0570 * Z) return color(R * 255, G * 255, B * 255) end --Basic matrix shells -- X = (0 * R) + (0 * G) + (0 * B) -- Y = (0 * R) + (0 * G) + (0 * B) -- Z = (0 * R) + (0 * G) + (0 * B) -- R = (0 * X) + (0 * Y) + (0 * Z) -- G = (0 * X) + (0 * Y) + (0 * Z) -- B = (0 * X) + (0 * Y) + (0 * Z) --The conversion for D65 RGB to D65 XYZ uses the matrix on page 14, ITU-R BT.709 Primaries. --D65 XYZ means XYZ without changing the illuminant. -- XYZD65 -> RGBD65 -- X = 0.4124 0.3576 0.1805 R -- Y = 0.2126 0.7152 0.0722 G -- Z = 0.0193 0.1192 0.9505 B on XYZ2RGB (X, Y, Z) X = X/100.0 Y = Y/100.0 Z = Z/100.0 R = (3.240479 * X) + (-1.537150 * Y) + (-0.498535 * Z) G = (-0.969256 * X) + (1.875992 * Y) + (0.041556 * Z) B = (0.055648 * X) + (-0.204043 * Y) + (1.057311 * Z) return color(R * 255, G * 255, B * 255) end on RGB2XYZ (R, G, B) R = R/255.0 G = G/255.0 B = B/255.0 X = (0.412453 * R) + (0.357580 * G) + (0.180423 * B) Y = (0.212671 * R) + (0.715160 * G) + (0.072169 * B) Z = (0.019334 * R) + (0.119193 * G) + (0.950227 * B) return [X * 100, Y * 100, Z * 100] end --The conversion for D65 RGB to D50 XYZ applies additionally (by multiplication) the Bradford --correction, which takes the adaptation of the eyes into account. This correction is an improved --alternative to the Von Kries correction [1]. --Monitors are assumed D65, but for printed paper the standard illuminant is D50. Therefore --this transformation is recommended if the data are used for printing: -- XYZD50 -> RGBD65 -- X = 0.4361 0.3851 0.1431 R -- Y = 0.2225 0.7169 0.0606 G -- Z = 0.0139 0.0971 0.7141 B