.
This commit is contained in:
81
back.py
81
back.py
@@ -1,81 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate a top-to-bottom linear gradient PNG from three hex colors.
|
||||
|
||||
Matches: linear-gradient(#2a1a5e, #8b4789, #f4a261)
|
||||
|
||||
Usage:
|
||||
python gradient_to_png.py --width 1920 --height 1080 --out bg.png
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from PIL import Image
|
||||
|
||||
def hex_to_rgb(h: str):
|
||||
"""Convert #rrggbb or rrggbb to (r,g,b)."""
|
||||
h = h.strip()
|
||||
if h.startswith("#"):
|
||||
h = h[1:]
|
||||
if len(h) != 6:
|
||||
raise ValueError("Hex color must be 6 hex digits, got: " + h)
|
||||
return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
|
||||
|
||||
def lerp(a: int, b: int, t: float) -> int:
|
||||
"""Linear interpolation between integers a and b, t in [0,1]."""
|
||||
return int(round(a + (b - a) * t))
|
||||
|
||||
def mix_color(c1, c2, t: float):
|
||||
"""Interpolate between two RGB colors (tuple of 3 ints)."""
|
||||
return (lerp(c1[0], c2[0], t),
|
||||
lerp(c1[1], c2[1], t),
|
||||
lerp(c1[2], c2[2], t))
|
||||
|
||||
def make_three_stop_vertical_gradient(width: int, height: int, hex1: str, hex2: str, hex3: str) -> Image.Image:
|
||||
"""
|
||||
Create a Pillow Image with a vertical gradient going through three colors evenly:
|
||||
- color1 at top (0%)
|
||||
- color2 at 50%
|
||||
- color3 at bottom (100%)
|
||||
This mirrors `linear-gradient(color1, color2, color3)` in CSS with no explicit stops.
|
||||
"""
|
||||
c1 = hex_to_rgb(hex1)
|
||||
c2 = hex_to_rgb(hex2)
|
||||
c3 = hex_to_rgb(hex3)
|
||||
|
||||
img = Image.new("RGB", (width, height))
|
||||
pixels = img.load()
|
||||
|
||||
# For each row compute color:
|
||||
for y in range(height):
|
||||
t = y / float(max(1, height - 1)) # 0.0..1.0
|
||||
if t <= 0.5:
|
||||
# interpolate between c1 and c2 (0.0..0.5 -> 0.0..1.0)
|
||||
local_t = t / 0.5
|
||||
color = mix_color(c1, c2, local_t)
|
||||
else:
|
||||
# interpolate between c2 and c3 (0.5..1.0 -> 0.0..1.0)
|
||||
local_t = (t - 0.5) / 0.5
|
||||
color = mix_color(c2, c3, local_t)
|
||||
|
||||
# fill the row with the computed color
|
||||
for x in range(width):
|
||||
pixels[x, y] = color
|
||||
|
||||
return img
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Render a 3-stop vertical CSS-like gradient to PNG")
|
||||
parser.add_argument("--width", "-W", type=int, default=1920, help="Output image width in pixels")
|
||||
parser.add_argument("--height", "-H", type=int, default=1080, help="Output image height in pixels")
|
||||
parser.add_argument("--out", "-o", default="gradient.png", help="Output PNG filename")
|
||||
parser.add_argument("--c1", default="#2a1a5e", help="Top color (hex)")
|
||||
parser.add_argument("--c2", default="#8b4789", help="Middle color (hex)")
|
||||
parser.add_argument("--c3", default="#f4a261", help="Bottom color (hex)")
|
||||
args = parser.parse_args()
|
||||
|
||||
img = make_three_stop_vertical_gradient(args.width, args.height, args.c1, args.c2, args.c3)
|
||||
img.save(args.out, "PNG")
|
||||
print(f"Saved {args.out} ({args.width}x{args.height})")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user