こんにちは!
12月は季節柄、クリスマスツリーを飾る家庭が多いと思います。
我が家でもツリーを飾っているのですが、片付けが面倒、と思うこともしばしば。
そこで今回は、Pythonの豊富なライブラリを利用して、クリスマスツリーを描いてみることにしました。
ツリーを出さなくていいレベルになるか分かりませんが、やってみます。
やりたいこと
- クリスマスツリーを描く
- ライトをチカチカ光らせる
- 雪を降らせる
- GIFアニメーションとして保存する
環境構築
Pythonの仮想環境を作ります。
python -m venv tree-art
cd tree-art
ディレクトリに移動した直後の状態
$ ls
bin/ include/ lib/ pyvenv.cfg
仮想環境の有効化
source bin/activate
必要なライブラリのインストール
pip install Pillow
Pillowとは
Pythonに画像処理機能を追加するライブラリです。
様々な画像形式に対応しており、読み込んだ画像の編集もできます。
コード
main.py
import random
import math
from PIL import Image, ImageDraw
frames = []
number_of_frames = 20
# RGBカラーコードで明るい色を定義
led_colors = [
(255, 128, 128), # 赤
(0, 255, 128), # 緑
(0, 128, 255), # 青
(128, 128, 255), # 紫
(255, 255, 64), # 黄
]
# 星の描画
def draw_star(draw, center, size, color):
x, y = center
outer = size
inner = size / 2.5
points = []
angle = 0
for i in range(5):
outer_x = x + outer * math.cos(math.radians(angle))
outer_y = y - outer * math.sin(math.radians(angle))
points.append((outer_x, outer_y))
angle += 36
inner_x = x + inner * math.cos(math.radians(angle))
inner_y = y - inner * math.sin(math.radians(angle))
points.append((inner_x, inner_y))
angle += 36
draw.polygon(points, fill=color)
# 画像の設定
width, height = 500, 700
for frame_number in range(number_of_frames):
# 画像と描画オブジェクトの生成
image = Image.new('RGB', (width, height), color='RGB(0, 0, 110)')
draw = ImageDraw.Draw(image)
# 背景に雪を降らせる
for _ in range(200): # 雪の数
snow_x = random.randint(0, width)
snow_y = random.randint(0, height)
snow_size = random.randint(2, 5)
draw.ellipse([snow_x - snow_size, snow_y - snow_size,
snow_x + snow_size, snow_y + snow_size], fill="RGB(256, 256, 256)")
# ツリーの描画
tree_color = 'RGB(0, 88, 88)'
tree_positions = [(250, 450), (250, 350), (250, 250)]
# ツリーの各層を描画
for i, (x, y) in enumerate(tree_positions):
size = 250 - i * 50
draw.polygon([x - size, y, x, y - size * 1.5, x + size, y], fill=tree_color)
# 雪を積もらせる
draw.rectangle([0, 550, width, height], fill='RGB(256, 256, 256)')
# ツリーの幹の描画
draw.rectangle([230, 450, 270, 550], fill='RGB(101, 67, 33)')
total_ornaments = 0
for i, (x, y) in enumerate(tree_positions):
size = 250 - i * 50
ornaments_count = 50 - i * 3 * 5
total_ornaments += ornaments_count
for _ in range(ornaments_count):
# ツリーの層の形に基づいて装飾を配置するための計算
rand_y = random.uniform(y - size * 1.5, y)
# Y座標に基づいてX座標の最大オフセットを計算
max_x_offset = (size * 1.5 - (y - rand_y)) / 1.5
rand_x = random.uniform(x - max_x_offset, x + max_x_offset)
ornament_color = random.choice(led_colors)
ornament_size = random.randint(3, 8)
draw.ellipse((rand_x - ornament_size, rand_y - ornament_size,
rand_x + ornament_size, rand_y + ornament_size),
fill=ornament_color)
# 星の描画
draw_star(draw, (250, 50), 40, 'gold')
# 生成したフレームをリストに追加
frames.append(image)
# GIFアニメーションとして保存
frames[0].save('christmas_tree_animation.gif',
save_all=True,
append_images=frames[1:],
duration=1500, # フレームごとの表示時間(ミリ秒)
loop=0) # アニメーションを無限ループ
実行結果
Pythonで描いたツリーはこちらです!
今回はこれが限界でございます🎅
これはPythonではなく、作成者のデザインセンスの問題ですね。
まとめ
今回は、Pythonでクリスマスツリーを描いてみました🎄
自宅では今年もツリーを出すことになりそうですが、いつの日か、本物のツリーがいらなくなるくらいの精度に仕上げようと思います🎅
みなさんも一緒に頑張りましょう!