commit d057c6bf029b1abfb330df1baf33fa24b6f17988 Author: cqql Date: Wed Jul 3 19:13:19 2024 +0200 Initial commit diff --git a/README.md b/README.md new file mode 100755 index 0000000..afe4fee --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +![an autogenerated 10print pattern in blue](examples/palette_1.png) + +# Generative Banner +#### a little fun thing i made back in early 2023 +A bit of code that generates a 10 print pattern in one on the specified color palettes and sets the result as the banner on a Pleroma account. I made it run as a cronjob every day at midnight. + +You can see some generated examples in the [examples](examples) folder. + +## Usage + +In [generate_set_banner.py](generate_set_banner.py): +1. Set the OAuth token used to access the Pleroma API with privileges to edit your account. I used [this site](https://tinysubversions.com/notes/mastodon-bot/). +2. Set the base url of the Pleroma instance. +```py +OAUTH_TOKEN = 'OAUTH_TOKEN' +base_url = 'https://example.com' +``` + +Run +``` +python3 generate_set_banner.py +``` + +This will generate a banner using a randomly picked color palette from a list in the code and set it as the banner on your fedi account. \ No newline at end of file diff --git a/examples/palette_0.png b/examples/palette_0.png new file mode 100755 index 0000000..663ad5d Binary files /dev/null and b/examples/palette_0.png differ diff --git a/examples/palette_1.png b/examples/palette_1.png new file mode 100755 index 0000000..71d9510 Binary files /dev/null and b/examples/palette_1.png differ diff --git a/examples/palette_2.png b/examples/palette_2.png new file mode 100755 index 0000000..7568a0d Binary files /dev/null and b/examples/palette_2.png differ diff --git a/examples/palette_3.png b/examples/palette_3.png new file mode 100755 index 0000000..b8cdb07 Binary files /dev/null and b/examples/palette_3.png differ diff --git a/examples/palette_4.png b/examples/palette_4.png new file mode 100755 index 0000000..f3b3f2c Binary files /dev/null and b/examples/palette_4.png differ diff --git a/examples/palette_5.png b/examples/palette_5.png new file mode 100755 index 0000000..1c1e879 Binary files /dev/null and b/examples/palette_5.png differ diff --git a/generate_set_banner.py b/generate_set_banner.py new file mode 100755 index 0000000..c652ac2 --- /dev/null +++ b/generate_set_banner.py @@ -0,0 +1,63 @@ +import requests +import tenprint_gradient +from io import BytesIO + +OAUTH_TOKEN = 'OAUTH_TOKEN' # OAuth token to access your account through the Pleroma API + +base_url = 'https://example.com' # The base URL of the Pleroma instance + +# The list of color palettes. It contains tuples, where the first two elements +# of each tuple are the colors for the background gradient and the last two are +# the foreground (slashes) gradient colors. +# I put them in separate lists grouped by the 4 colors they use so that there is an equal +# probability of getting each 4-color scheme. And only then the color tuple is picked, +# determining the orientations of the gradients. +palettes = [ + [ + (0xef5d60,0xec4067,0xa01a7d,0x311847), + ], + [ + (0x0a1128,0x001f54,0x034078,0x1282a2), + ], + [ + (0x212d40,0x11151c,0xb9314f,0xedddd4), + ], + [ + (0x191d32,0x282f44,0x453a49,0x6d3b47), + ], + [ + (0x0b3c49,0x731963,0xfffdfd,0xcbd2d0), + (0x0b3c49,0x731963,0xcbd2d0,0xfffdfd), + (0x731963,0x0b3c49,0xcbd2d0,0xfffdfd), + (0x731963,0x0b3c49,0xfffdfd,0xcbd2d0) + ], + [ + (0xfffdfd,0xcbd2d0,0x0b3c49,0x731963), + (0xcbd2d0,0xfffdfd,0x0b3c49,0x731963), + (0xcbd2d0,0xfffdfd,0x731963,0x0b3c49), + (0xfffdfd,0xcbd2d0,0x731963,0x0b3c49) + ] +] + + +print('Picking palette') +palette_index, palette_orientation, palette = tenprint_gradient.get_random_palette(palettes) +print(f'Using palette {palette_index}/{palette_orientation} - {palette}') + +print('Generating banner') +# This will generate a banner 31 cells wide, 11 cells tall, with each cell being 100 by 100 pixels, and with 0 margin +banner_image = tenprint_gradient.generate_gradiented_10print(31, 11, 100, 0, palette) + +print('Getting banner bytes') +banner_bytes = None +with BytesIO() as output: + banner_image.save(output, 'PNG') + banner_bytes = output.getvalue() + +print(f'Requesting banner update at {base_url}') +response = requests.patch(f'{base_url}/api/v1/accounts/update_credentials', files={ + 'header': banner_bytes +}, headers={'Authorization': f'Bearer {OAUTH_TOKEN}'}) + +print('Response') +print(response.text) diff --git a/tenprint.py b/tenprint.py new file mode 100755 index 0000000..7cc1185 --- /dev/null +++ b/tenprint.py @@ -0,0 +1,35 @@ +from PIL import Image, ImageDraw +import random + +bgcolor = (255,255,255) +fgcolor = (0,0,0) + +def draw_slash(d, x, y, cellsize, flip, thickness=0.16): + if flip: + slash = [ + (x+cellsize*(1-thickness), y), + (x+cellsize, y), + (x+cellsize, y+cellsize*thickness), + (x+cellsize*thickness, y+cellsize), + (x, y+cellsize), + (x, y+cellsize*(1-thickness)) + ] + else: + slash = [ + (x, y), + (x+cellsize*thickness, y), + (x+cellsize, y+cellsize*(1-thickness)), + (x+cellsize, y+cellsize), + (x+cellsize*(1-thickness), y+cellsize), + (x, y+cellsize*thickness) + ] + d.polygon(slash, fill=fgcolor) + +def make_image(width, height, cellsize_px, margin=0): + image = Image.new("RGB", (int(cellsize_px*margin + width*(cellsize_px*(1+margin))), int(cellsize_px*margin + height*(cellsize_px*(1+margin)))), bgcolor) + draw = ImageDraw.Draw(image) + for x in range(width): + for y in range(height): + draw_slash(draw, cellsize_px*margin + x*(cellsize_px+margin*cellsize_px), cellsize_px*margin + y*(cellsize_px+margin*cellsize_px), cellsize_px, random.random() > 0.5) + return image + diff --git a/tenprint_gradient.py b/tenprint_gradient.py new file mode 100755 index 0000000..45c7907 --- /dev/null +++ b/tenprint_gradient.py @@ -0,0 +1,45 @@ +import tenprint +import random + +def get_rgb_from_int(color): + r = (color>>16) & 255 + g = (color>>8) & 255 + b = color & 255 + return (r,g,b) + +def get_gradient(color1, color2, between): + new_color = [] + for p1, p2 in zip(color1, color2): + new_color.append(int(p1*between + p2*(1-between))) + return tuple(new_color) + +def get_palette_rgb_from_palette_int(palette_raw): + return [ + get_rgb_from_int(c) for c in + palette_raw + ] + + +def generate_gradiented_10print(width, height, cellsize, margin, palette): + image = tenprint.make_image(width, height, cellsize, margin) + pixels = image.load() + + width_px = image.size[0] + height_px = image.size[1] + + bg_gradient = palette[0:2] + fg_gradient = palette[2:4] + + for x in range(width_px): + for y in range(height_px): + if pixels[x,y] == tenprint.bgcolor: + pixels[x,y] = get_gradient(bg_gradient[0], bg_gradient[1], y/height_px) + if pixels[x,y] == tenprint.fgcolor: + pixels[x,y] = get_gradient(fg_gradient[0], fg_gradient[1], y/height_px) + + return image + +def get_random_palette(palettes): + palette_index, palette_rotations = random.choice(tuple(enumerate(palettes))) + palette_rotation, palette = random.choice(tuple(enumerate(palette_rotations))) + return palette_index, palette_rotation, get_palette_rgb_from_palette_int(palette)