まくろぐ
更新: / 作成:

とあるコーディングにおいて、色を滑らかに変化させる必要があったのでメモメモ。

RGB ではなく HSV で考える

何らかのプログラミング言語から虹色のグラデーションを作る必要がある場合、RGB の色空間で色調整を行うのは大変ですが、HSV の色空間で考えると簡単に表現することができます。

/p/4cbbh6o/hsv.png
図: HSV 色空間

HSV はそれぞれ下記のような情報を表しており、

  • 色相 (Hue): 0~360
  • 彩度 (Saturation・Chroma): 0~1
  • 明度 (Value・Brightness): 0~1

このうち、色相 (Hue) の値を 0~360 の間で変化させてやることでレインボーカラーを表現することができます。

プログラムのサンプル

/p/4cbbh6o/rainbow-bar.png
図: 虹色グラデーションの描画

例えば、Android では、android.graphics.Color.HSVToColor() という関数を使用すると、HSV 色空間における値を、描画に使用するカラーデータに変換することができます。

下記の ColorGenerator クラスの nextColor() メソッドを連続して呼び出すと、徐々に変わっていく色をひとつずつ取り出すことができます。 やっていることは、メソッドの呼び出しごとに、色相 (Hue) の値を少しずつ変化させているだけです。 色相 (Hue) が、何度の nextColor() 呼び出しで一周するかは、コンストラクタの steps パラメータで指定できるようにしています。

ColorGenerator.kt
class ColorGenerator(val steps: Int, initialHue: Float = 0.0F) {
    private val hueStep: Float = 360F / steps
    private var currentHue = initialHue

    fun nextColor(): Int {
        val hsv = floatArrayOf(currentHue, 1.0F, 1.0F)
        val color: Int = Color.HSVToColor(255, hsv)
        currentHue = (currentHue + hueStep) % 360F
        return color
    }
}

次のコードは、このクラスを使って、虹色のグラデーション(細い矩形の連続)を描画するコードの抜粋です。 ここでは、色を 30 段階に分けて描画しています。

虹色の矩形を描画する(抜粋)
val colorGen = ColorGenerator(30)

override fun onDraw(canvas: Canvas){
    var left = 0F
    val paint = Paint()
    for (i in 0 until colorGen.steps) {
        paint.color = colorGen.nextColor()
        c.drawRect(left, 0F, left + 10, 100F, paint)
        left += 10
    }
}

関連記事

まくろぐ
サイトマップまくへのメッセージ