You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.9 KiB
Python

3 years ago
#!/usr/bin/env python3
import cairo
import math
2 months ago
from datetime import datetime
import calendar
import random
2 months ago
import colorsys
3 years ago
from utils import random_color
# dimensions of the output image
# how much should the phases be offset?
WAVE_OFFSET = math.pi / random.choice([1, 2, 4]) #-1.9
# background black? White otherwise:
DARK_BG = True
3 years ago
# precision of the calculation
PRECISION = 10000
3 years ago
def get_color_from_date(date: datetime) -> tuple[float, float, float]:
2 months ago
'''Return a color based on the progress through the year.'''
# a day between 1 and 365 (inclusive)
today = date.timetuple().tm_yday
2 months ago
days_in_year = 365 + calendar.isleap(date.year)
# between 0 and 1, how far through the year are we?
progress = today/days_in_year
3 years ago
return colorsys.hsv_to_rgb(progress, 1, 0.9)
def get_amplitude_from_date(date: datetime, waves) -> float:
2 months ago
'''Return the amplitude of waves, based on progress through the month.'''
days_in_month = calendar.monthrange(date.year, date.month)[1]
max_amp = 1/waves/2
2 months ago
return date.day/days_in_month * max_amp
def create_wpotd(width: int, height: int, date: datetime = datetime.now(), dark: bool = True) -> cairo.ImageSurface:
2 months ago
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
3 years ago
ctx = cairo.Context(surface)
2 months ago
ctx.scale(width, height) # Normalizing the canvas
3 years ago
#ctx.set_antialias(cairo.Antialias.BEST)
3 years ago
3 years ago
lastpoints = [(x/PRECISION, 0) for x in range(PRECISION+1)]
frequency = random.randint(10, 40)
waves = date.month
amplitude = get_amplitude_from_date(date, waves)
r, g, b = get_color_from_date(date)
2 months ago
alpha_step = 1/waves
ctx.rectangle(0, 0, 1, 1)
if dark:
3 years ago
# make bg black
ctx.set_source_rgb(0, 0, 0)
else:
ctx.set_source_rgb(255, 255, 255)
ctx.fill()
wave_height = 1/waves
2 months ago
step_size = 1/PRECISION
for wave_index in range(waves+1):
3 years ago
points = []
x = 0
while x < 1:
2 months ago
# step along, create points along the wave
y = amplitude * math.sin(frequency * x + (wave_index * WAVE_OFFSET))
points.append((x, (y + (0.5 + wave_index)*wave_height)))
3 years ago
x += step_size
3 years ago
#print(f'Draw {len(points)} points for curve {num}')
else:
2 months ago
# make more transparent toward bottom
ctx.set_source_rgba(r, g, b, 1 - (alpha_step * wave_index))
3 years ago
# draw waves
3 years ago
ctx.move_to(*points[0])
for p in points[1:]:
ctx.line_to(*p)
3 years ago
ctx.set_line_width(0.0004)
ctx.stroke_preserve()
for p in reversed(lastpoints):
ctx.line_to(*p)
ctx.line_to(*points[0])
ctx.fill()
3 years ago
lastpoints = points
2 months ago
return surface
#surface.write_to_png(output) # Output to PNG
3 years ago
3 years ago
def main():
output = create_wpotd(1920, 1080, dark=False)
2 months ago
output.write_to_png('out/waves.png')
3 years ago
if __name__ == '__main__':
main()