47 Colour Conversion Algorithms

From Director Online Wiki
Jump to: navigation, search
-- 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