pythonで色を連続的に変化させる方法
色をシームレスに変化させたい。虹色みたいに。ただそれだけ。
と思っても、実は色についてほとんど知識が無いことに気がつく。RGBは分かるが、それを使ってどう変化させればいいかわからない。RGBのRの値だけを変えても色の赤みが薄くなるか濃くなるかだけで、虹色みたいに変化させるのは難しいのではと思った。
困ったときのウィキペディア。世の中には皆がよく知るRGB以外にも色を表現する方法はあるようだ。というかペイントとかでお世話になっていた。 RGBは赤・緑・青の原色を混ぜ合わせることで色を表現する方法だが、HSV色空間は、Hue(色相)、Saturation(彩度)、Value(明度)の3つのパラメータで表現する方法だ。ウィキペディアを見て、色を連続的に変化させたい = 色相を変化させたい、とやりたいことを明確に言語化できた。
ウィキペディアを見るとHSVからRGBの変換方法まで記載されていたので、そのままhsvからRGBの変換関数を作成してみた。
def hsv_to_rgb(h, s, v): """ Convert hsv color code to rgb color code. Naive implementation of Wikipedia method. See https://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93 Args: h (int): Hue 0 ~ 360 s (int): Saturation 0 ~ 1 v (int): Value 0 ~ 1 """ if s < 0 or 1 < s: raise ValueError("Saturation must be between 0 and 1") if v < 0 or 1 < v: raise ValueError("Value must be between 0 and 1") c = v * s h_dash = h / 60 x = c * (1 - abs(h_dash % 2 - 1)) rgb_dict = { 0: (c, x, 0), 1: (x, c, 0), 2: (0, c, x), 3: (0, x, c), 4: (x, 0, c), 5: (c, 0, x), } default = (0, 0, 0) rgb = [0, 0, 0] for i in range(len(rgb)): rgb[i] = (v - c + rgb_dict.get(int(h_dash), default)[i]) * 255 rgb = map(int, rgb) return tuple(rgb)
あとはhを0~360までfor文で変化させたものをgifにすればトップの色が変化していく画像ができあがる。
for i in range(60): color = hsv_to_rgb(i*6, 1, 1) img = Image.new('RGB', (width, width), (0, 0, 0)) draw = ImageDraw.Draw(img) draw.rectangle((0, 0, width, width), fill=color) images.append(img) images[0].save("./color.gif", save_all=True, append_images=images[1:], optimize=False, duration=5, loop=0)
せっかくだからグラデーションにでもすればもっと見目麗しい画像になった気がする。 あとpillowは簡単にgifが出来て便利。(小並感)