diff --git a/main.py b/main.py new file mode 100644 index 0000000..f62ef5a --- /dev/null +++ b/main.py @@ -0,0 +1,94 @@ +import io +import itertools +import json +import random +from collections import Counter +from copy import deepcopy +from datetime import datetime +from pathlib import Path + +import matplotlib.pyplot as plt +import numpy as np +import uvicorn +from fastapi import FastAPI, Response +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import StreamingResponse + +app = FastAPI(title="Speckles API", root_path="/images") +origins = [ + "http://localhost", + "http://localhost:3000", + "https://localhost", + "https://0124816.xyz", + "http://0124816.xyz:3001", +] + +app.add_middleware( + CORSMiddleware, + allow_origins=origins, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +MEDIA_TYPES = { + "png": "image/png", + "jpeg": "image/jpeg", + "jpg": "image/jpeg", + "svg": "image/svg+xml", + "pdf": "application/pdf", +} + + +@app.get("/speckles/") +def make_wallpaper( + speckle_colours: str, + dimensions: tuple[float | int, float | int] = (1920, 1080), + density: float | None = 0.12, + fileformat: str = "svg", +): + if not fileformat in MEDIA_TYPES: + return + speckle_colours = speckle_colours.split(",") + background = speckle_colours.pop(0) + x, y = dimensions + speckles_per_colour = int(x / 100 * y / 100 * density) + + fig, ax = plt.subplots(figsize=(x / 100, y / 100), facecolor=background) + ax.set_facecolor(background) + [spine.set_color(background) for spine in ax.spines.values()] + ax.set_xticks([]) + ax.set_yticks([]) + ax.margins(0, 0) + + for color, size in itertools.product( + speckle_colours, + np.logspace(1, 6.6, 8, base=2), + ): + ax.scatter( + [random.random() * x / 8 for _ in range(speckles_per_colour)], + [random.random() * y / 8 for _ in range(speckles_per_colour)], + c=color, + s=size, + ) + + fig.tight_layout() + # plt.xlim(0, x) + # plt.ylim(0, y) + # plt.axis("off") + + buf = io.BytesIO() + fig.savefig( + buf, + format=fileformat, + dpi=128, + bbox_inches="tight", + pad_inches=0, + ) + buf.seek(0) + return StreamingResponse(content=buf, media_type=MEDIA_TYPES[fileformat]) + buf.close() + + +if __name__ == "__main__": + uvicorn.run("main:app", workers=2, port=8099, reload=False)