;; return HSL encoded in SDL color object
define rgb->hsl(rgb)
  define d
  define h
  define s
  define r sdl:color-rf(rgb)
  define g sdl:color-gf(rgb)
  define b sdl:color-bf(rgb)
  define cmax max(r g b)
  define cmin min(r g b)
  define l {{cmax + cmin} / 2}
  cond
    {cmax = cmin}  ;; achromatic color?
      {h := {s := 0}}
    else
      {d := {cmax - cmin}}
      {s := {d / (if {l > 0.5} {2 - cmax - cmin} {cmax + cmin})}}
      cond
        {r = cmax}
          {h := {{g - b} / d}}
          if {g < b} inc!(h 6)
        {g = cmax}
          {h := {{{b - r} / d} + 2}}
        {b = cmax}
          {h := {{{r - g} / d} + 4}}
      {h := {h / 6}}
  ;; `h`, `s` and `l` should be in `[0..1]`
  sdl:rgbf(h s l)


define hsl->rgb
  case-lambda
    (rgb)
      hsl->rgb rgb 255
    (rgb a)
      define hx->c(p q t)
        constant t0 {1 / 6}
        constant t1 {1 / 2}
        constant t2 {2 / 3}
        if {t < 0} inc!(t)
          if {t > 1} dec!(t)
        cond
          {t < t0}  {p + {{q - p} * t * 6}}
          {t < t1}  q
          {t < t2}  {p + {{q - p} * {t2 - t} * 6}}
          else      p
      define r
      define g
      define b
      define h sdl:color-rf(rgb)
      define s sdl:color-gf(rgb)
      define l sdl:color-bf(rgb)
      constant h3 {1 / 3}
      cond
        {zero? s}  ;; achromatic color?
          {r := {g := {b := l}}}
        else
          define q (if {l < 0.5} {l * {1 + s}} {{l + s} - {l * s}})
          define p {{2 * l} - q}
          {r := hx->c(p q {h + h3})}
          {g := hx->c(p q h)}
          {b := hx->c(p q {h - h3})}
      sdl:rgbaf(r g b a)


;; return texture
define recolor-surface(surf delta-h delta-s delta-l)
  define need-recolor?(rgb)
    (or {sdl:color-r(rgb) > 8} {sdl:color-g(rgb) > 8} {sdl:color-b(rgb) > 8})
  define shift-value(v delta)
    inc! v delta
    while {v < 0} inc!(v 1)
    while {v > 1} dec!(v 1)
    v
  define w sdl:surface-width(surf)
  define h sdl:surface-height(surf)
  define x
  define y
  define a
  define rgba
  define hsl
  define new-surf sdl:new-surface(w h)
  define stt {- ticks-msec()}
  iterate
    init {y := 0}
    repeat {y <> h}
      iterate
        init {x := 0}
        repeat {x <> w}
          {rgba := sdl:surface-get-pixel(surf x y)}
          if need-recolor?(rgba)
            then
              {a := sdl:color-af(rgba)}
              {hsl := rgb->hsl(rgba)}
              {hsl := sdl:rgbf(shift-value(sdl:color-rf(hsl) delta-h)
                               clamp({sdl:color-gf(hsl) + delta-s} 0 1)
                               clamp({sdl:color-bf(hsl) + delta-l} 0 1))}
              {rgba := hsl->rgb(hsl a)}
          sdl:surface-set-pixel new-surf x y rgba
          inc! x
        else #void
      inc! y
    else #void
  {stt := {stt + ticks-msec()}}
  printf "recolored in %o msecs.\n" stt
  new-surf
