|
|
@ -2,9 +2,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
import cairo
|
|
|
|
import cairo
|
|
|
|
import math
|
|
|
|
import math
|
|
|
|
import datetime
|
|
|
|
from datetime import datetime
|
|
|
|
import calendar
|
|
|
|
import calendar
|
|
|
|
import random
|
|
|
|
import random
|
|
|
|
|
|
|
|
import colorsys
|
|
|
|
from utils import random_color
|
|
|
|
from utils import random_color
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -25,53 +26,49 @@ DARK_BG = True
|
|
|
|
# precision of the calculation
|
|
|
|
# precision of the calculation
|
|
|
|
PRECISION = 10000
|
|
|
|
PRECISION = 10000
|
|
|
|
|
|
|
|
|
|
|
|
def days_color(date):
|
|
|
|
def days_color(date: datetime) -> tuple[float, float, float]:
|
|
|
|
import colorsys
|
|
|
|
'''Return a color based on the progress through the year.'''
|
|
|
|
# a day between 1 and 365 (inclusive)
|
|
|
|
# a day between 1 and 365 (inclusive)
|
|
|
|
today = date.timetuple().tm_yday
|
|
|
|
today = date.timetuple().tm_yday
|
|
|
|
year = date.year
|
|
|
|
days_in_year = 365 + calendar.isleap(date.year)
|
|
|
|
days_in_year = 365 + calendar.isleap(year)
|
|
|
|
|
|
|
|
# between 0 and 1, how far through the year are we?
|
|
|
|
# between 0 and 1, how far through the year are we?
|
|
|
|
progress = today/days_in_year
|
|
|
|
progress = today/days_in_year
|
|
|
|
return colorsys.hsv_to_rgb(progress, 1, 0.9)
|
|
|
|
return colorsys.hsv_to_rgb(progress, 1, 0.9)
|
|
|
|
|
|
|
|
|
|
|
|
def days_amp(date, waves):
|
|
|
|
def days_amp(date: datetime, waves) -> float:
|
|
|
|
day = date.day
|
|
|
|
'''Return the amplitude of waves, based on progress through the month.'''
|
|
|
|
days_in_month = calendar.monthrange(date.year, date.month)[1]
|
|
|
|
days_in_month = calendar.monthrange(date.year, date.month)[1]
|
|
|
|
max_amp = 1/waves/2
|
|
|
|
max_amp = 1/waves/2
|
|
|
|
return day/days_in_month * max_amp
|
|
|
|
return date.day/days_in_month * max_amp
|
|
|
|
|
|
|
|
|
|
|
|
def days_count(date):
|
|
|
|
def create_wpotd(width: int, height: int):
|
|
|
|
return date.month
|
|
|
|
#TODO: return a `file`-like object
|
|
|
|
|
|
|
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
|
|
|
|
def create_wpotd(output):
|
|
|
|
|
|
|
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
|
|
|
|
|
|
|
|
ctx = cairo.Context(surface)
|
|
|
|
ctx = cairo.Context(surface)
|
|
|
|
|
|
|
|
|
|
|
|
ctx.scale(WIDTH, HEIGHT) # Normalizing the canvas
|
|
|
|
ctx.scale(width, height) # Normalizing the canvas
|
|
|
|
#ctx.set_antialias(cairo.Antialias.BEST)
|
|
|
|
#ctx.set_antialias(cairo.Antialias.BEST)
|
|
|
|
|
|
|
|
|
|
|
|
step_size = 1/PRECISION
|
|
|
|
|
|
|
|
lastpoints = [(x/PRECISION, 0) for x in range(PRECISION+1)]
|
|
|
|
lastpoints = [(x/PRECISION, 0) for x in range(PRECISION+1)]
|
|
|
|
|
|
|
|
|
|
|
|
#date = datetime.datetime.strptime('2021-06-30', '%Y-%m-%d')
|
|
|
|
date = datetime.today()
|
|
|
|
date = datetime.datetime.today()
|
|
|
|
|
|
|
|
frequency = random.randint(10, 40)
|
|
|
|
frequency = random.randint(10, 40)
|
|
|
|
if DATE_BASED_COUNT:
|
|
|
|
if DATE_BASED_COUNT:
|
|
|
|
waves = days_count(date)
|
|
|
|
# generate as many waves as the number of the current month
|
|
|
|
|
|
|
|
waves = date.month
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
waves = 12
|
|
|
|
waves = 12
|
|
|
|
if DATE_BASED_AMPLITUDE:
|
|
|
|
if DATE_BASED_AMPLITUDE:
|
|
|
|
amplitude = days_amp(date, waves)
|
|
|
|
amplitude = days_amp(date, waves)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
amplitude = 25
|
|
|
|
amplitude = 25
|
|
|
|
|
|
|
|
|
|
|
|
if MONOCHROME:
|
|
|
|
if MONOCHROME:
|
|
|
|
if DATE_BASED_COLOR:
|
|
|
|
if DATE_BASED_COLOR:
|
|
|
|
r, g, b = days_color(date) #datetime.datetime.now())
|
|
|
|
r, g, b = days_color(date) #datetime.datetime.now())
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
r, g, b = random_color()
|
|
|
|
r, g, b = random_color()
|
|
|
|
alpha_step = 1/waves
|
|
|
|
alpha_step = 1/waves
|
|
|
|
|
|
|
|
|
|
|
|
if DARK_BG:
|
|
|
|
if DARK_BG:
|
|
|
|
# make bg black
|
|
|
|
# make bg black
|
|
|
|
ctx.rectangle(0, 0, 1, 1)
|
|
|
|
ctx.rectangle(0, 0, 1, 1)
|
|
|
@ -79,20 +76,24 @@ def create_wpotd(output):
|
|
|
|
ctx.fill()
|
|
|
|
ctx.fill()
|
|
|
|
|
|
|
|
|
|
|
|
wave_height = 1/waves
|
|
|
|
wave_height = 1/waves
|
|
|
|
for num in range(waves+1):
|
|
|
|
step_size = 1/PRECISION
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for wave_index in range(waves+1):
|
|
|
|
if not MONOCHROME:
|
|
|
|
if not MONOCHROME:
|
|
|
|
r, g, b = random_color()
|
|
|
|
r, g, b = random_color()
|
|
|
|
points = []
|
|
|
|
points = []
|
|
|
|
x = 0
|
|
|
|
x = 0
|
|
|
|
while x < 1:
|
|
|
|
while x < 1:
|
|
|
|
y = amplitude * math.sin(frequency * x + (num * WAVE_OFFSET) )
|
|
|
|
# step along, create points along the wave
|
|
|
|
points.append((x, ( y + (0.5+num)*wave_height)))
|
|
|
|
y = amplitude * math.sin(frequency * x + (wave_index * WAVE_OFFSET))
|
|
|
|
|
|
|
|
points.append((x, (y + (0.5 + wave_index)*wave_height)))
|
|
|
|
x += step_size
|
|
|
|
x += step_size
|
|
|
|
#print(f'Draw {len(points)} points for curve {num}')
|
|
|
|
#print(f'Draw {len(points)} points for curve {num}')
|
|
|
|
if not MONOCHROME:
|
|
|
|
if not MONOCHROME:
|
|
|
|
ctx.set_source_rgb(r, g, b)
|
|
|
|
ctx.set_source_rgb(r, g, b)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
ctx.set_source_rgba(r, g, b, 1 - (alpha_step * num)) # make more transparent toward bottom
|
|
|
|
# make more transparent toward bottom
|
|
|
|
|
|
|
|
ctx.set_source_rgba(r, g, b, 1 - (alpha_step * wave_index))
|
|
|
|
# draw waves
|
|
|
|
# draw waves
|
|
|
|
ctx.move_to(*points[0])
|
|
|
|
ctx.move_to(*points[0])
|
|
|
|
for p in points[1:]:
|
|
|
|
for p in points[1:]:
|
|
|
@ -104,11 +105,12 @@ def create_wpotd(output):
|
|
|
|
ctx.line_to(*points[0])
|
|
|
|
ctx.line_to(*points[0])
|
|
|
|
ctx.fill()
|
|
|
|
ctx.fill()
|
|
|
|
lastpoints = points
|
|
|
|
lastpoints = points
|
|
|
|
#return surface
|
|
|
|
return surface
|
|
|
|
surface.write_to_png(output) # Output to PNG
|
|
|
|
#surface.write_to_png(output) # Output to PNG
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
def main():
|
|
|
|
create_wpotd('out/waves.png')
|
|
|
|
output = create_wpotd(1920, 1080)
|
|
|
|
|
|
|
|
output.write_to_png('out/waves.png')
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|
|
|
|
main()
|
|
|
|