c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

RGBとHSVとHLSとCMYKの色空間を相互変換する。Rubyで

前回のを書き足した。合ってる気がしない。
cf. RGBとHSVの色空間を相互変換する。Rubyhttp://c4se.hatenablog.com/entry/2013/08/04/190937

# coding=utf-8

class Color
  # RGB to HSV conversion | color conversion http://www.rapidtables.com/convert/color/rgb-to-hsv.htm
  # @param r [Integer] red 0..255
  # @param g [Integer] green 0..255
  # @param b [Integer] blue 0..255
  # @return [Integer[]] [hue, saturation, value]
  #   hue 0..360 degree
  #   saturation 0..100 %
  #   value 0..100 %
  def self.rgb_to_hsv r, g, b
    r /= 255.0
    g /= 255.0
    b /= 255.0
    cmax = [r, g, b].max
    cmin = [r, b, g].min
    d = cmax - cmin
    return [0, 0, (cmax * 100).floor] if d == 0
    h = case cmax
        when r then 60 * ((g - b) / d % 6)
        when g then 60 * ((b - r) / d + 2)
        else        60 * ((r - g) / d + 4)
        end
    [ h,
      d / cmax * 100,
      cmax * 100
    ].map &:floor
  end

  # HSV to RGB conversion | color conversion http://www.rapidtables.com/convert/color/hsv-to-rgb.htm
  # @param h [Integer] hue 0..360 degree
  # @param s [Integer] saturation 0..100 %
  # @param v [Integer] value 0..100 %
  # @return [Integer[]] [red, green, blue]
  #   red 0..255
  #   green 0..255
  #   blue 0..255
  def self.hsv_to_rgb h, s, v
    s /= 100.0
    v /= 100.0
    c = v * s
    x = c * (1 - ((h / 60.0) % 2 - 1).abs)
    m = v - c
    r, g, b = case
              when h < 60  then [c, x, 0]
              when h < 120 then [x, c, 0]
              when h < 180 then [0, c, x]
              when h < 240 then [0, x, c]
              when h < 300 then [x, 0, c]
              else              [c, 0, x]
              end
    [r, g, b].map{|channel| ((channel + m) * 255).ceil }
  end

  # RGB to HSL converter | color conversion http://www.rapidtables.com/convert/color/rgb-to-hsl.htm
  # @param r [Integer] red 0..255
  # @param g [Integer] green 0..255
  # @param b [Integer] blue 0..255
  # @return [Integer[]] [hue, lightness, saturation]
  #   hue 0..360 degree
  #   lightness 0..100 %
  #   saturation 0..100 %
  def self.rgb_to_hls r, g, b
    r /= 255.0
    g /= 255.0
    b /= 255.0
    cmax = [r, g, b].max
    cmin = [r, b, g].min
    d = cmax - cmin
    l = (cmax + cmin) / 2
    return [0, (l * 100).floor, 0] if d == 0
    h = case cmax
        when r then 60 * ((g - b) / d % 6)
        when g then 60 * ((b - r) / d + 2)
        else        60 * ((r - g) / d + 4)
        end
    [ h,
      l * 100,
      d / (1 - (l * 2 - 1).abs) * 100
    ].map &:floor
  end

  # HSL to RGB conversion | color conversion http://www.rapidtables.com/convert/color/hsl-to-rgb.htm
  # @param h [Integer] hue 0..360 degree
  # @param l [Integer] lightness 0..100 %
  # @param s [Integer] saturation 0..100 %
  # @return [Integer[]] [red, green, blue]
  #   red 0..255
  #   green 0..255
  #   blue 0..255
  def self.hls_to_rgb h, l, s
    s /= 100.0
    l /= 100.0
    c = (1 - (l * 2 - 1).abs) * s
    x = c * (1 - ((h / 60.0) % 2 - 1).abs)
    m = l - c / 2
    r, g, b = case
              when h < 60  then [c, x, 0]
              when h < 120 then [x, c, 0]
              when h < 180 then [0, c, x]
              when h < 240 then [0, x, c]
              when h < 300 then [x, 0, c]
              else              [c, 0, x]
              end
    [r, g, b].map{|channel| ((channel + m) * 255).ceil }
  end

  # RGB to CMYK conversion | color conversion http://www.rapidtables.com/convert/color/rgb-to-cmyk.htm
  def self.rgb_to_cmyk r, g, b
    r /= 255.0
    g /= 255.0
    b /= 255.0
    k = 1 - [r, g, b].max
    return [0, 0, 0, k.floor] if k == 1
    [ (1 - r - k) / (1 - k),
      (1 - g - k) / (1 - k),
      (1 - b - k) / (1 - k),
      k
    ].map{|channel| channel.to_i if channel.to_i == channel }
  end

  # CMYK to RGB conversion | color conversion http://www.rapidtables.com/convert/color/cmyk-to-rgb.htm
  def self.cmyk_to_rgb c, m, y, k
    [ (1 - c) * (1 - k),
      (1 - m) * (1 - k),
      (1 - y) * (1 - k)
    ].map{|channel| (channel * 255).ceil }
  end

  # don't code today what you can't debug tomorrow: Converting between HSL and HSV http://ariya.blogspot.jp/2008/07/converting-between-hsl-and-hsv.html
  # @param h [Integer] hue 0..360 degree
  # @param s [Integer] saturation 0..100 %
  # @param v [Integer] value 0..100 %
  # @return [Integer[]] [hue, lightness, saturation]
  #   hue 0..360 degree
  #   lightness 0..100 %
  #   saturation 0..100 %
  def self.hsv_to_hls h, hsv_s, v
    l = (200 - hsv_s) * v / 100.0
    return [h, l / 2.0, 0].map(&:ceil) if l == 0 || l == 200
    [ h,
      l / 2.0,
      hsv_s * v * 1.0 / (l <= 100 ? l : 200 - l)
    ].map &:ceil
  end

  # don't code today what you can't debug tomorrow: Converting between HSL and HSV http://ariya.blogspot.jp/2008/07/converting-between-hsl-and-hsv.html
  def self.hls_to_hsv h, l, hls_s
    l /= 100.0
    hls_s /= 100.0
    l *= 2.0
    hls_s *= (l <= 1 ? l : 2 - l)
    return [h, 0, (l + hls_s) / 2.0].map(&:ceil) if l + hls_s == 0
    [ h,
      (2.0 * hls_s) / (l + hls_s) * 100,
      (l + hls_s) / 2.0 * 100
    ].map &:ceil
  end

  def initialize r = 0, g = 0, b = 0, a = 0
    @r = r
    @g = g
    @b = b
    @a = a
  end

  def alpha; @a end

  def alpha= a; @a = a end

  def rgba; [@r, @g, @b, @a] end

  def rgba= channels
    r, g, b, a = channels
    @r = r if r
    @g = g if g
    @b = b if b
    @a = a if a
  end

  def hsva; [*self.class.rgb_to_hsv(@r, @g, @b), @a] end

  def hsva= channels
    h, s, v = self.class.rgb_to_hsv @r, @g, @b
    h = channels[0] if channels[0]
    s = channels[1] if channels[1]
    v = channels[2] if channels[2]
    @r, @g, @b = self.class.hsv_to_rgb h, s, v
    @a = channels[3] if channels[3]
  end

  def hlsa; [*self.class.rgb_to_hls(@r, @g, @b), @a] end

  def hsva= channels
    h, l, s = self.class.rgb_to_hls @r, @g, @b
    h = channels[0] if channels[0]
    l = channels[1] if channels[1]
    s = channels[2] if channels[2]
    @r, @g, @b = self.class.hls_to_rgb h, l, s
    @a = channels[3] if channels[3]
  end

  def cmyka; [*self.class.rgb_to_cmyk(@r, @g, @b), @a] end

  def cmyka= channels
    c, m, y, k = self.class.rgb_to_cmyk @r, @g, @b
    c = channels[0] if channels[0]
    m = channels[1] if channels[1]
    y = channels[2] if channels[2]
    k = channels[3] if channels[3]
    @r, @g, @b = self.class.cmyk_to_rgb c, m, y, k
    @a = channels[4] if channels[4]
  end
end

puts 'RGB to HSV'
puts "black   #{Color.rgb_to_hsv   0,   0,   0} =   0,   0,   0"
puts "white   #{Color.rgb_to_hsv 255, 255, 255} =   0,   0, 100"
puts "red     #{Color.rgb_to_hsv 255,   0,   0} =   0, 100, 100"
puts "lime    #{Color.rgb_to_hsv   0, 255,   0} = 120, 100, 100"
puts "blue    #{Color.rgb_to_hsv   0,   0, 255} = 240, 100, 100"
puts "yellow  #{Color.rgb_to_hsv 255, 255,   0} =  60, 100, 100"
puts "cyan    #{Color.rgb_to_hsv   0, 255, 255} = 180, 100, 100"
puts "magenta #{Color.rgb_to_hsv 255,   0, 255} = 300, 100, 100"
puts "silver  #{Color.rgb_to_hsv 192, 192, 192} =   0,   0,  75"
puts "gray    #{Color.rgb_to_hsv 128, 128, 128} =   0,   0,  50"
puts "maroon  #{Color.rgb_to_hsv 128,   0,   0} =   0, 100,  50"
puts "olive   #{Color.rgb_to_hsv 128, 128,   0} =  60, 100,  50"
puts "green   #{Color.rgb_to_hsv   0, 128,   0} = 120, 100,  50"
puts "purple  #{Color.rgb_to_hsv 128,   0, 128} = 300, 100,  50"
puts "teal    #{Color.rgb_to_hsv   0, 128, 128} = 180, 100,  50"
puts "navy    #{Color.rgb_to_hsv   0,   0, 128} = 240, 100,  50"

puts 'HSV to RGB'
puts "black   #{Color.hsv_to_rgb   0,   0,   0} =   0,   0,   0"
puts "white   #{Color.hsv_to_rgb   0,   0, 100} = 255, 255, 255"
puts "red     #{Color.hsv_to_rgb   0, 100, 100} = 255,   0,   0"
puts "lime    #{Color.hsv_to_rgb 120, 100, 100} =   0, 255,   0"
puts "blue    #{Color.hsv_to_rgb 240, 100, 100} =   0,   0, 255"
puts "yellow  #{Color.hsv_to_rgb  60, 100, 100} = 255, 255,   0"
puts "cyan    #{Color.hsv_to_rgb 180, 100, 100} =   0, 255, 255"
puts "magenta #{Color.hsv_to_rgb 300, 100, 100} = 255,   0, 255"
puts "silver  #{Color.hsv_to_rgb   0,   0,  75} = 192, 192, 192"
puts "gray    #{Color.hsv_to_rgb   0,   0,  50} = 128, 128, 128"
puts "maroon  #{Color.hsv_to_rgb   0, 100,  50} = 128,   0,   0"
puts "olive   #{Color.hsv_to_rgb  60, 100,  50} = 128, 128,   0"
puts "green   #{Color.hsv_to_rgb 120, 100,  50} =   0, 128,   0"
puts "purple  #{Color.hsv_to_rgb 300, 100,  50} = 128,   0, 128"
puts "teal    #{Color.hsv_to_rgb 180, 100,  50} =   0, 128, 128"
puts "navy    #{Color.hsv_to_rgb 240, 100,  50} =   0,   0, 128"

puts 'RGB to HLS'
puts "black   #{Color.rgb_to_hls   0,   0,   0} =   0,   0,   0"
puts "white   #{Color.rgb_to_hls 255, 255, 255} =   0, 100,   0"
puts "red     #{Color.rgb_to_hls 255,   0,   0} =   0,  50, 100"
puts "lime    #{Color.rgb_to_hls   0, 255,   0} = 120,  50, 100"
puts "blue    #{Color.rgb_to_hls   0,   0, 255} = 240,  50, 100"
puts "yellow  #{Color.rgb_to_hls 255, 255,   0} =  60,  50, 100"
puts "cyan    #{Color.rgb_to_hls   0, 255, 255} = 180,  50, 100"
puts "magenta #{Color.rgb_to_hls 255,   0, 255} = 300,  50, 100"
puts "silver  #{Color.rgb_to_hls 192, 192, 192} =   0,  75,   0"
puts "gray    #{Color.rgb_to_hls 128, 128, 128} =   0,  50,   0"
puts "maroon  #{Color.rgb_to_hls 128,   0,   0} =   0,  25, 100"
puts "olive   #{Color.rgb_to_hls 128, 128,   0} =  60,  25, 100"
puts "green   #{Color.rgb_to_hls   0, 128,   0} = 120,  25, 100"
puts "purple  #{Color.rgb_to_hls 128,   0, 128} = 300,  25, 100"
puts "teal    #{Color.rgb_to_hls   0, 128, 128} = 180,  25, 100"
puts "navy    #{Color.rgb_to_hls   0,   0, 128} = 240,  25, 100"

puts 'HLS to RGB'
puts "black   #{Color.hls_to_rgb   0,   0,   0} =   0,   0,   0"
puts "white   #{Color.hls_to_rgb   0, 100,   0} = 255, 255, 255"
puts "red     #{Color.hls_to_rgb   0,  50, 100} = 255,   0,   0"
puts "lime    #{Color.hls_to_rgb 120,  50, 100} =   0, 255,   0"
puts "blue    #{Color.hls_to_rgb 240,  50, 100} =   0,   0, 255"
puts "yellow  #{Color.hls_to_rgb  60,  50, 100} = 255, 255,   0"
puts "cyan    #{Color.hls_to_rgb 180,  50, 100} =   0, 255, 255"
puts "magenta #{Color.hls_to_rgb 300,  50, 100} = 255,   0, 255"
puts "silver  #{Color.hls_to_rgb   0,  75,   0} = 192, 192, 192"
puts "gray    #{Color.hls_to_rgb   0,  50,   0} = 128, 128, 128"
puts "maroon  #{Color.hls_to_rgb   0,  25, 100} = 128,   0,   0"
puts "olive   #{Color.hls_to_rgb  60,  25, 100} = 128, 128,   0"
puts "green   #{Color.hls_to_rgb 120,  25, 100} =   0, 128,   0"
puts "purple  #{Color.hls_to_rgb 300,  25, 100} = 128,   0, 128"
puts "teal    #{Color.hls_to_rgb 180,  25, 100} =   0, 128, 128"
puts "navy    #{Color.hls_to_rgb 240,  25, 100} =   0,   0, 128"

puts 'HSV to HLS'
puts "black   #{Color.hsv_to_hls   0,   0,   0} =   0,   0,   0"
puts "white   #{Color.hsv_to_hls   0,   0, 100} =   0, 100,   0"
puts "red     #{Color.hsv_to_hls   0, 100, 100} =   0,  50, 100"
puts "lime    #{Color.hsv_to_hls 120, 100, 100} = 120,  50, 100"
puts "blue    #{Color.hsv_to_hls 240, 100, 100} = 240,  50, 100"
puts "yellow  #{Color.hsv_to_hls  60, 100, 100} =  60,  50, 100"
puts "cyan    #{Color.hsv_to_hls 180, 100, 100} = 180,  50, 100"
puts "magenta #{Color.hsv_to_hls 300, 100, 100} = 300,  50, 100"
puts "silver  #{Color.hsv_to_hls   0,   0,  75} =   0,  75,   0"
puts "gray    #{Color.hsv_to_hls   0,   0,  50} =   0,  50,   0"
puts "maroon  #{Color.hsv_to_hls   0, 100,  50} =   0,  25, 100"
puts "olive   #{Color.hsv_to_hls  60, 100,  50} =  60,  25, 100"
puts "green   #{Color.hsv_to_hls 120, 100,  50} = 120,  25, 100"
puts "purple  #{Color.hsv_to_hls 300, 100,  50} = 300,  25, 100"
puts "teal    #{Color.hsv_to_hls 180, 100,  50} = 180,  25, 100"
puts "navy    #{Color.hsv_to_hls 240, 100,  50} = 240,  25, 100"

puts 'HLS to HSV'
puts "black   #{Color.hls_to_hsv   0,   0,   0} =   0,   0,   0"
puts "white   #{Color.hls_to_hsv   0, 100,   0} =   0,   0, 100"
puts "red     #{Color.hls_to_hsv   0,  50, 100} =   0, 100, 100"
puts "lime    #{Color.hls_to_hsv 120,  50, 100} = 120, 100, 100"
puts "blue    #{Color.hls_to_hsv 240,  50, 100} = 240, 100, 100"
puts "yellow  #{Color.hls_to_hsv  60,  50, 100} =  60, 100, 100"
puts "cyan    #{Color.hls_to_hsv 180,  50, 100} = 180, 100, 100"
puts "magenta #{Color.hls_to_hsv 300,  50, 100} = 300, 100, 100"
puts "silver  #{Color.hls_to_hsv   0,  75,   0} =   0,   0,  75"
puts "gray    #{Color.hls_to_hsv   0,  50,   0} =   0,   0,  50"
puts "maroon  #{Color.hls_to_hsv   0,  25, 100} =   0, 100,  50"
puts "olive   #{Color.hls_to_hsv  60,  25, 100} =  60, 100,  50"
puts "green   #{Color.hls_to_hsv 120,  25, 100} = 120, 100,  50"
puts "purple  #{Color.hls_to_hsv 300,  25, 100} = 300, 100,  50"
puts "teal    #{Color.hls_to_hsv 180,  25, 100} = 180, 100,  50"
puts "navy    #{Color.hls_to_hsv 240,  25, 100} = 240, 100,  50"

puts 'RGB to CMYK'
puts "black   #{Color.rgb_to_cmyk   0,   0,   0} = 0, 0, 0, 1"
puts "white   #{Color.rgb_to_cmyk 255, 255, 255} = 0, 0, 0, 0"
puts "red     #{Color.rgb_to_cmyk 255,   0,   0} = 0, 1, 1, 0"
puts "green   #{Color.rgb_to_cmyk   0, 255,   0} = 1, 0, 1, 0"
puts "blue    #{Color.rgb_to_cmyk   0,   0, 255} = 1, 1, 0, 0"
puts "yellow  #{Color.rgb_to_cmyk 255, 255,   0} = 0, 0, 1, 0"
puts "cyan    #{Color.rgb_to_cmyk   0, 255, 255} = 1, 0, 0, 0"
puts "magenta #{Color.rgb_to_cmyk 255,   0, 255} = 0, 1, 0, 0"

puts 'CMYK to RGB'
puts "black   #{Color.cmyk_to_rgb 0, 0, 0, 1} =   0,   0,   0"
puts "white   #{Color.cmyk_to_rgb 0, 0, 0, 0} = 255, 255, 255"
puts "red     #{Color.cmyk_to_rgb 0, 1, 1, 0} = 255,   0,   0"
puts "green   #{Color.cmyk_to_rgb 1, 0, 1, 0} =   0, 255,   0"
puts "blue    #{Color.cmyk_to_rgb 1, 1, 0, 0} =   0,   0, 255"
puts "yellow  #{Color.cmyk_to_rgb 0, 0, 1, 0} = 255, 255,   0"
puts "cyan    #{Color.cmyk_to_rgb 1, 0, 0, 0} =   0, 255, 255"
puts "magenta #{Color.cmyk_to_rgb 0, 1, 0, 0} = 255,   0, 255"