--
-- color conversion routines
--

-- R, G, B are from 0..1

function rgb2hsv (RGB)

   local R = clamp (RGB[1], 0.0, 1.0)
   local G = clamp (RGB[2], 0.0, 1.0)
   local B = clamp (RGB[3], 0.0, 1.0)

   local CMin = math.min (R, math.min (G, B))
   local CMax = math.max (R, math.max (G, B))
   local CDelta = CMax - CMin

   local H = 0
   local S = 0
   local V = CMax

   if (CDelta > 0) then

      S = CDelta / CMax

      local RDelta = ((CMax - R) / 6 + (CDelta / 2)) / CDelta
      local GDelta = ((CMax - G) / 6 + (CDelta / 2)) / CDelta
      local BDelta = ((CMax - B) / 6 + (CDelta / 2)) / CDelta

      if (R == CMax) then H = BDelta - GDelta
      elseif (G == CMax) then H = (1 / 3) + RDelta - BDelta
      else H = (2 / 3) + GDelta - RDelta
      end

      if (H < 0) then H = H + 1 end
      if (H > 1) then H = H - 1 end
   end

   local HSV = { H, S, V }

   return HSV
end

-- smart HSV conversion; allow user to specify as gimp format, h 0..360, s v 0..100

function converthsv (HSV)

   if (HSV[1] > 1) then HSV[1] = HSV[1] / 360 end
   if (HSV[2] > 1) then HSV[2] = HSV[2] / 100 end
   if (HSV[3] > 1) then HSV[3] = HSV[3] / 100 end
end

-- H, S, V are from 0 .. 1

function hsv2rgb (HSV)

   converthsv (HSV)

   local H = clamp (HSV[1], 0.0, 1.0)
   local S = clamp (HSV[2], 0.0, 1.0)
   local V = clamp (HSV[3], 0.0, 1.0)

   local R, G, B

   if (S == 0) then

      R = V
      G = V
      B = V
   else

      local HTemp = H * 6
      if (HTemp >= 6) then HTemp = HTemp - 6 end
      local HFloor = math.floor (HTemp)
      local T1 = V * (1 - S)
      local T2 = V * (1 - S * (HTemp - HFloor))
      local T3 = V * (1 - S * (1 - (HTemp - HFloor)))

      if (0 == HFloor) then     R = V;  G = T3; B = T1;
      elseif (1 == HFloor) then R = T2; G = V;  B = T1;
      elseif (2 == HFloor) then R = T1; G = V;  B = T3;
      elseif (3 == HFloor) then R = T1; G = T2; B = V;
      elseif (4 == HFloor) then R = T3; G = T1; B = V;
      else                      R = V;  G = T1; B = T2;
      end
   end

   local RGB = { R, G, B }

   return RGB
end

function hsvperturb (HSV)

   converthsv (HSV)

   HSV[1] = HSV[1] + RN_balance () * 0.005
   HSV[2] = HSV[2] + RN_balance () * 0.01
   HSV[3] = HSV[3] + RN_balance () * 0.025
end

function hsvperturb_rgb (RGB)

   -- perturb a rgb color in the hsv colorspace
   local HSV = rgb2hsv (RGB)
   hsvperturb (HSV)
   local RGB_new = hsv2rgb (HSV)
   RGB[1] = RGB_new[1]
   RGB[2] = RGB_new[2]
   RGB[3] = RGB_new[3]
end
