#!/usr/bin/env python3 import cairo import math import datetime import calendar import random from utils import random_color # dimensions of the output image WIDTH, HEIGHT = 1920, 1080 # how much should the phases be offset? WAVE_OFFSET = math.pi / random.choice([1, 2, 4]) #-1.9 # amplitude of the sine wave #AMPLITUDE = 9 # only 1 color with shades? MONOCHROME = True # works only if monochrome is set - uses todays date as base for the color DATE_BASED_COLOR = True DATE_BASED_AMPLITUDE = True DATE_BASED_COUNT = True # background black? White otherwise: DARK_BG = True # precision of the calculation PRECISION = 10000 def days_color(date): import colorsys # a day between 1 and 365 (inclusive) today = date.timetuple().tm_yday year = date.year days_in_year = 365 + calendar.isleap(year) # between 0 and 1, how far through the year are we? progress = today/days_in_year return colorsys.hsv_to_rgb(progress, 1, 0.9) def days_amp(date, waves): day = date.day days_in_month = calendar.monthrange(date.year, date.month)[1] max_amp = 1/waves/2 return day/days_in_month * max_amp def days_count(date): return date.month def create_wpotd(output): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) ctx = cairo.Context(surface) ctx.scale(WIDTH, HEIGHT) # Normalizing the canvas #ctx.set_antialias(cairo.Antialias.BEST) step_size = 1/PRECISION lastpoints = [(x/PRECISION, 0) for x in range(PRECISION+1)] #date = datetime.datetime.strptime('2021-06-30', '%Y-%m-%d') date = datetime.datetime.today() frequency = random.randint(10, 40) if DATE_BASED_COUNT: waves = days_count(date) else: waves = 12 if DATE_BASED_AMPLITUDE: amplitude = days_amp(date, waves) else: amplitude = 25 if MONOCHROME: if DATE_BASED_COLOR: r, g, b = days_color(date) #datetime.datetime.now()) else: r, g, b = random_color() alpha_step = 1/waves if DARK_BG: # make bg black ctx.rectangle(0, 0, 1, 1) ctx.set_source_rgb(0, 0, 0) ctx.fill() wave_height = 1/waves for num in range(waves+1): if not MONOCHROME: r, g, b = random_color() points = [] x = 0 while x < 1: y = amplitude * math.sin(frequency * x + (num * WAVE_OFFSET) ) points.append((x, ( y + (0.5+num)*wave_height))) x += step_size #print(f'Draw {len(points)} points for curve {num}') if not MONOCHROME: ctx.set_source_rgb(r, g, b) else: ctx.set_source_rgba(r, g, b, 1 - (alpha_step * num)) # make more transparent toward bottom # draw waves ctx.move_to(*points[0]) for p in points[1:]: ctx.line_to(*p) 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() lastpoints = points return surface #surface.write_to_png(output) # Output to PNG def main(): create_wpotd('out/waves.png') if __name__ == '__main__': main()