basic package structure
This commit is contained in:
parent
c69c5482f0
commit
927011f624
182
bin/huepaper
Executable file
182
bin/huepaper
Executable file
@ -0,0 +1,182 @@
|
|||||||
|
from huepaper import (
|
||||||
|
get_base_color,
|
||||||
|
create_colors,
|
||||||
|
create_base_image,
|
||||||
|
add_lines,
|
||||||
|
add_pixelation,
|
||||||
|
add_emblem,
|
||||||
|
save_image,
|
||||||
|
)
|
||||||
|
import argparse
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
|
||||||
|
def print_greeter():
|
||||||
|
greeter = """
|
||||||
|
.lk.
|
||||||
|
cO.
|
||||||
|
cO.;:lc. ,c. .cc .,',c; .,c.;coc. ;,.,c. ':l.:lo: '',:c. '::.lo.
|
||||||
|
cO' kd .O; dO ,x...,Ox cO; lO: ;x xk OO. .kO. x;...x0' 0x. .
|
||||||
|
cO. xx .O; dO ko...... :O. Ox .,..xO kk ;0;;0...... 0d
|
||||||
|
cO. xx .O; xO dO. .. :O. .O; dk xO kk :O.'0o , 0d
|
||||||
|
.dk, .kk. okc;,ox' ckxllc. :Oc'.,l' oOl;'dO:. kO;..:l. ,xOolc; ,Ox.
|
||||||
|
:O. kk
|
||||||
|
lO, OO
|
||||||
|
OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO00O0000000000000000;
|
||||||
|
"""
|
||||||
|
print(greeter)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Create wallpapers based on color hues."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--size",
|
||||||
|
default="1920x1080",
|
||||||
|
help="size of huepaper in the form WIDTHxHEIGHT (default: 1920x1080)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-c",
|
||||||
|
"--color",
|
||||||
|
help="color, the huepaper is generated from (uses a random color if not given)",
|
||||||
|
)
|
||||||
|
parser.add_argument("-p", "--preview", action="store_true", help="preview huepaper")
|
||||||
|
parser.add_argument(
|
||||||
|
"-o", "--output", help="file where to save the huepaper to (default: None)"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-l",
|
||||||
|
"--lines",
|
||||||
|
nargs="?",
|
||||||
|
const=0.3,
|
||||||
|
type=float,
|
||||||
|
help="include one to three random lines in base color with given opacity in range [0, 1] (default: 0.3)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-lb",
|
||||||
|
"--lines_bright",
|
||||||
|
nargs="?",
|
||||||
|
const=0.1,
|
||||||
|
type=float,
|
||||||
|
help="include one to three bright random lines with given opacity in range [0, 1] (default: 0.1)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-ld",
|
||||||
|
"--lines_dark",
|
||||||
|
nargs="?",
|
||||||
|
const=0.1,
|
||||||
|
type=float,
|
||||||
|
help="include one to three dark random lines with given opacity in range [0, 1] (default: 0.1)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-P",
|
||||||
|
"--pixelate",
|
||||||
|
nargs="?",
|
||||||
|
const="16x9",
|
||||||
|
help="pixelate image with WIDTHxHEIGHT (default: 16x9)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-e", "--emblem", help="emblem to add in the center of the huepaper"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-hue",
|
||||||
|
default=0.1,
|
||||||
|
type=float,
|
||||||
|
help="maximum hue to differ from given color in range [0, 1] (default: 0.1)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-smin",
|
||||||
|
default=0.2,
|
||||||
|
type=float,
|
||||||
|
help="minimum satisfaction for colors in range [0, 1] (default: 0.2)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-smax",
|
||||||
|
default=1.0,
|
||||||
|
type=float,
|
||||||
|
help="maximum satisfaction for colors in range [0, 1] (default: 1.0)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-lmin",
|
||||||
|
default=0.2,
|
||||||
|
type=float,
|
||||||
|
help="minimum luminance for colors in range [0, 1] (default: 0.2)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-lmax",
|
||||||
|
default=0.9,
|
||||||
|
type=float,
|
||||||
|
help="maximum luminance for colors in range [0, 1] (default: 0.9)",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get args
|
||||||
|
args = parser.parse_args()
|
||||||
|
size = args.size
|
||||||
|
color = args.color
|
||||||
|
preview = args.preview
|
||||||
|
output = args.output
|
||||||
|
lines = args.lines
|
||||||
|
lines_bright = args.lines_bright
|
||||||
|
lines_dark = args.lines_dark
|
||||||
|
emblem = args.emblem
|
||||||
|
pixelate = args.pixelate
|
||||||
|
hue_max = args.hue
|
||||||
|
sat_min = args.smin
|
||||||
|
sat_max = args.smax
|
||||||
|
lum_min = args.lmin
|
||||||
|
lum_max = args.lmax
|
||||||
|
|
||||||
|
# Get size
|
||||||
|
try:
|
||||||
|
values = size.split("x")
|
||||||
|
width = int(values[0])
|
||||||
|
height = int(values[1])
|
||||||
|
except:
|
||||||
|
parser.error("The size must be given in form: 1920x1080")
|
||||||
|
|
||||||
|
# Check preconditions
|
||||||
|
if not preview and not output:
|
||||||
|
parser.error("You must either set -p (--preview) or -o (--output)")
|
||||||
|
if pixelate:
|
||||||
|
try:
|
||||||
|
values = pixelate.split("x")
|
||||||
|
px = int(values[0])
|
||||||
|
py = int(values[1])
|
||||||
|
except:
|
||||||
|
parser.error("Pixelation value must be set in form: 42x42")
|
||||||
|
|
||||||
|
print_greeter()
|
||||||
|
base_color = get_base_color(color, sat_min, sat_max, lum_min, lum_max)
|
||||||
|
c1, c2, c3, c4 = create_colors(
|
||||||
|
base_color, hue_max, sat_min, sat_max, lum_min, lum_max
|
||||||
|
)
|
||||||
|
image = create_base_image(c1, c2, c3, c4, width, height)
|
||||||
|
|
||||||
|
if lines:
|
||||||
|
image = add_lines(image, base_color.rgb + (lines,))
|
||||||
|
if lines_bright:
|
||||||
|
image = add_lines(image, (1.0, 1.0, 1.0, lines_bright))
|
||||||
|
if lines_dark:
|
||||||
|
image = add_lines(image, (0.0, 0.0, 0.0, lines_dark))
|
||||||
|
|
||||||
|
if pixelate:
|
||||||
|
image = add_pixelation(image, px, py)
|
||||||
|
|
||||||
|
if emblem:
|
||||||
|
image = add_emblem(image, emblem)
|
||||||
|
|
||||||
|
image.mode = "RGB"
|
||||||
|
|
||||||
|
if preview:
|
||||||
|
image.show()
|
||||||
|
if not output:
|
||||||
|
save = input("Do you want to save the image? [y/N] ")
|
||||||
|
if save == "y" or save == "Y":
|
||||||
|
path = input("Enter the path where the wallpaper shall be saved: ")
|
||||||
|
save_image(image, path)
|
||||||
|
|
||||||
|
if output:
|
||||||
|
save_image(image, output)
|
377
huepaper.py
377
huepaper.py
@ -1,377 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from PIL import Image, ImageDraw, ImageOps
|
|
||||||
from colour import Color
|
|
||||||
import argparse
|
|
||||||
import os.path
|
|
||||||
import random
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def print_logo():
|
|
||||||
logo = """
|
|
||||||
.lk.
|
|
||||||
cO.
|
|
||||||
cO.;:lc. ,c. .cc .,',c; .,c.;coc. ;,.,c. ':l.:lo: '',:c. '::.lo.
|
|
||||||
cO' kd .O; dO ,x...,Ox cO; lO: ;x xk OO. .kO. x;...x0' 0x. .
|
|
||||||
cO. xx .O; dO ko...... :O. Ox .,..xO kk ;0;;0...... 0d
|
|
||||||
cO. xx .O; xO dO. .. :O. .O; dk xO kk :O.'0o , 0d
|
|
||||||
.dk, .kk. okc;,ox' ckxllc. :Oc'.,l' oOl;'dO:. kO;..:l. ,xOolc; ,Ox.
|
|
||||||
:O. kk
|
|
||||||
lO, OO
|
|
||||||
OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO00O0000000000000000;
|
|
||||||
"""
|
|
||||||
print(logo)
|
|
||||||
|
|
||||||
|
|
||||||
def get_base_color(color_string=None):
|
|
||||||
|
|
||||||
global sat_min, sat_max, lum_min, lum_max
|
|
||||||
|
|
||||||
# If no color string is given, create a random color
|
|
||||||
if not color_string:
|
|
||||||
hue = random.uniform(0, 1)
|
|
||||||
sat = random.uniform(sat_min, sat_max)
|
|
||||||
lum = random.uniform(lum_min, lum_max)
|
|
||||||
base_color = Color(hue=hue, saturation=sat, luminance=lum)
|
|
||||||
print("Selected random base color: {}".format(base_color.hex))
|
|
||||||
|
|
||||||
# Else try to parse string
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
base_color = Color(color_string)
|
|
||||||
except:
|
|
||||||
print("Not a valid color expression: {}".format(color_string))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
return base_color
|
|
||||||
|
|
||||||
|
|
||||||
def create_colors(base_color):
|
|
||||||
|
|
||||||
global max_hue, sat_min, sat_max, lum_min, lum_max
|
|
||||||
|
|
||||||
colors = []
|
|
||||||
|
|
||||||
max_sat_diff = 0.1
|
|
||||||
max_lum_diff = 0.1
|
|
||||||
|
|
||||||
# Create four random colors similar to the given base_color
|
|
||||||
for i in range(0, 4):
|
|
||||||
|
|
||||||
tmp_hue = base_color.hue + random.uniform(-max_hue / 2.0, max_hue / 2.0)
|
|
||||||
if tmp_hue > 1.0:
|
|
||||||
tmp_hue -= 1
|
|
||||||
|
|
||||||
tmp_sat = base_color.saturation + random.uniform(-max_sat_diff, max_sat_diff)
|
|
||||||
tmp_sat = min(sat_max, max(sat_min, tmp_sat))
|
|
||||||
|
|
||||||
tmp_lum = base_color.luminance + random.uniform(-max_lum_diff, max_lum_diff)
|
|
||||||
tmp_lum = min(lum_max, max(lum_min, tmp_lum))
|
|
||||||
|
|
||||||
color = Color(hue=tmp_hue, saturation=tmp_sat, luminance=tmp_lum)
|
|
||||||
colors.append(color.rgb)
|
|
||||||
|
|
||||||
return tuple(colors)
|
|
||||||
|
|
||||||
|
|
||||||
# c1 - top left
|
|
||||||
# c2 - top right
|
|
||||||
# c3 - bottom right
|
|
||||||
# c4 - bottom left
|
|
||||||
def create_base_image(c1, c2, c3, c4):
|
|
||||||
|
|
||||||
global width, height
|
|
||||||
|
|
||||||
# Lambda for adding four colors
|
|
||||||
add = lambda c1, c2, c3, c4: (
|
|
||||||
c1[0] + c2[0] + c3[0] + c4[0],
|
|
||||||
c1[1] + c2[1] + c3[1] + c4[1],
|
|
||||||
c1[2] + c2[2] + c3[2] + c4[2],
|
|
||||||
)
|
|
||||||
|
|
||||||
# Lambda for multiplying a color with a factor
|
|
||||||
mul = lambda c, x: (c[0] * x, c[1] * x, c[2] * x)
|
|
||||||
|
|
||||||
# Lambda for scaling a color from [0 , 1] to [0, 255]
|
|
||||||
cor = lambda c: (int(c[0] * 255), int(c[1] * 255), int(c[2] * 255))
|
|
||||||
|
|
||||||
# Lambda for calculating a color at x and y in range [0, 1]
|
|
||||||
# Color limits are set at creation
|
|
||||||
col = lambda x, y, c1=c1, c2=c2, c3=c3, c4=c4: cor(
|
|
||||||
add(
|
|
||||||
mul(c1, (1.0 - x) * (1.0 - y)),
|
|
||||||
mul(c2, x * (1.0 - y)),
|
|
||||||
mul(c3, x * y),
|
|
||||||
mul(c4, (1.0 - x) * y),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create image
|
|
||||||
image = Image.new("RGBA", (width, height))
|
|
||||||
pixels = image.load()
|
|
||||||
|
|
||||||
for x in range(0, width):
|
|
||||||
for y in range(0, height):
|
|
||||||
pixels[x, y] = col(x / (width - 1), y / (height - 1))
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def add_lines(image, color):
|
|
||||||
|
|
||||||
global width, height
|
|
||||||
|
|
||||||
line_image = Image.new("RGBA", (width, height), (0, 0, 0, 0))
|
|
||||||
draw = ImageDraw.Draw(line_image)
|
|
||||||
|
|
||||||
# Set color
|
|
||||||
color = tuple(map(lambda x: int(x * 255), color))
|
|
||||||
|
|
||||||
# Generate lines
|
|
||||||
number_of_lines = random.randint(1, 3)
|
|
||||||
scale = width / 100.0
|
|
||||||
base_width = random.randint(int(2 * scale), int(5 * scale))
|
|
||||||
rand_width = lambda base_width=base_width: base_width + random.randint(
|
|
||||||
-base_width // 2, base_width // 2
|
|
||||||
)
|
|
||||||
space = rand_width() // 2
|
|
||||||
offset = random.randint(0, space)
|
|
||||||
for i in range(0, number_of_lines):
|
|
||||||
line_width = rand_width()
|
|
||||||
x = offset + space + (line_width // 2)
|
|
||||||
draw.line((x, 0, x, height), fill=color, width=line_width)
|
|
||||||
offset += space + line_width
|
|
||||||
|
|
||||||
# Mirror line image eventually
|
|
||||||
orientation = random.randrange(2)
|
|
||||||
if orientation == 1:
|
|
||||||
line_image = ImageOps.mirror(line_image)
|
|
||||||
|
|
||||||
# Add line image to input image
|
|
||||||
image.alpha_composite(line_image, (0, 0))
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def add_pixelation(image, x, y):
|
|
||||||
|
|
||||||
global width, height
|
|
||||||
|
|
||||||
image = image.resize((x, y))
|
|
||||||
image = image.resize((width, height), Image.BOX)
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def add_emblem(image, filepath):
|
|
||||||
|
|
||||||
global width, height
|
|
||||||
|
|
||||||
# Load image
|
|
||||||
try:
|
|
||||||
emblem_image = Image.open(filepath)
|
|
||||||
except Exception as e:
|
|
||||||
print("Failed to load emblem: {}".format(e))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Exit if emblem is too big
|
|
||||||
if emblem_image.size[0] > width or emblem_image.size[1] > height:
|
|
||||||
print("Emblem can't be bigger than the wallpaper")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Insert emblem in the center
|
|
||||||
offset = (
|
|
||||||
(image.size[0] - emblem_image.size[0]) // 2,
|
|
||||||
(image.size[1] - emblem_image.size[1]) // 2,
|
|
||||||
)
|
|
||||||
image.alpha_composite(emblem_image, offset)
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def save_image(filepath, image):
|
|
||||||
|
|
||||||
save = True
|
|
||||||
|
|
||||||
# Check whether file exists
|
|
||||||
if os.path.isfile(filepath):
|
|
||||||
overwrite = input(
|
|
||||||
"The file {} already exists. Do you want to overwrite it? [y/N] ".format(
|
|
||||||
filepath
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if overwrite != "y" and overwrite != "Y":
|
|
||||||
save = False
|
|
||||||
|
|
||||||
if save:
|
|
||||||
|
|
||||||
stop = False
|
|
||||||
while not stop:
|
|
||||||
try:
|
|
||||||
image.save(filepath)
|
|
||||||
stop = True
|
|
||||||
except Exception as e:
|
|
||||||
print("Failed to save wallpaper: {}".format(e))
|
|
||||||
again = input("Do you want to try again? [Y/n] ")
|
|
||||||
if again == "n" or again == "N":
|
|
||||||
stop = True
|
|
||||||
else:
|
|
||||||
filepath = input(
|
|
||||||
"Please enter new path where the wallpaper shall be saved: "
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
|
|
||||||
global width, height, max_hue, sat_min, sat_max, lum_min, lum_max
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="Create wallpapers based on color hues."
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-s",
|
|
||||||
"--size",
|
|
||||||
default="1920x1080",
|
|
||||||
help="size of huepaper in the form WIDTHxHEIGHT (default: 1920x1080)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-c",
|
|
||||||
"--color",
|
|
||||||
help="color, the huepaper is generated from (uses a random color if not given)",
|
|
||||||
)
|
|
||||||
parser.add_argument("-p", "--preview", action="store_true", help="preview huepaper")
|
|
||||||
parser.add_argument(
|
|
||||||
"-o", "--output", help="file where to save the huepaper to (default: None)"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-l",
|
|
||||||
"--lines",
|
|
||||||
nargs="?",
|
|
||||||
const=0.3,
|
|
||||||
type=float,
|
|
||||||
help="include one to three random lines in base color with given opacity in range [0, 1] (default: 0.3)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-lb",
|
|
||||||
"--lines_bright",
|
|
||||||
nargs="?",
|
|
||||||
const=0.1,
|
|
||||||
type=float,
|
|
||||||
help="include one to three bright random lines with given opacity in range [0, 1] (default: 0.1)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-ld",
|
|
||||||
"--lines_dark",
|
|
||||||
nargs="?",
|
|
||||||
const=0.1,
|
|
||||||
type=float,
|
|
||||||
help="include one to three dark random lines with given opacity in range [0, 1] (default: 0.1)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-P",
|
|
||||||
"--pixelate",
|
|
||||||
nargs="?",
|
|
||||||
const="16x9",
|
|
||||||
help="pixelate image with WIDTHxHEIGHT (default: 16x9)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-e", "--emblem", help="emblem to add in the center of the huepaper"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-hue",
|
|
||||||
default=0.1,
|
|
||||||
type=float,
|
|
||||||
help="maximum hue to differ from given color in range [0, 1] (default: 0.1)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-smin",
|
|
||||||
default=0.2,
|
|
||||||
type=float,
|
|
||||||
help="minimum satisfaction for colors in range [0, 1] (default: 0.2)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-smax",
|
|
||||||
default=1.0,
|
|
||||||
type=float,
|
|
||||||
help="maximum satisfaction for colors in range [0, 1] (default: 1.0)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-lmin",
|
|
||||||
default=0.2,
|
|
||||||
type=float,
|
|
||||||
help="minimum luminance for colors in range [0, 1] (default: 0.2)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-lmax",
|
|
||||||
default=0.9,
|
|
||||||
type=float,
|
|
||||||
help="maximum luminance for colors in range [0, 1] (default: 0.9)",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get args
|
|
||||||
args = parser.parse_args()
|
|
||||||
size = args.size
|
|
||||||
color = args.color
|
|
||||||
preview = args.preview
|
|
||||||
output = args.output
|
|
||||||
lines = args.lines
|
|
||||||
lines_bright = args.lines_bright
|
|
||||||
lines_dark = args.lines_dark
|
|
||||||
emblem = args.emblem
|
|
||||||
pixelate = args.pixelate
|
|
||||||
max_hue = args.hue
|
|
||||||
sat_min = args.smin
|
|
||||||
sat_max = args.smax
|
|
||||||
lum_min = args.lmin
|
|
||||||
lum_max = args.lmax
|
|
||||||
|
|
||||||
# Get size
|
|
||||||
try:
|
|
||||||
values = size.split("x")
|
|
||||||
width = int(values[0])
|
|
||||||
height = int(values[1])
|
|
||||||
except:
|
|
||||||
parser.error("The size must be given in form: 1920x1080")
|
|
||||||
|
|
||||||
# Check preconditions
|
|
||||||
if not preview and not output:
|
|
||||||
parser.error("You must either set -p (--preview) or -o (--output)")
|
|
||||||
if pixelate:
|
|
||||||
try:
|
|
||||||
values = pixelate.split("x")
|
|
||||||
px = int(values[0])
|
|
||||||
py = int(values[1])
|
|
||||||
except:
|
|
||||||
parser.error("Pixelation value must be set in form: 42x42")
|
|
||||||
|
|
||||||
print_logo()
|
|
||||||
base_color = get_base_color(color)
|
|
||||||
c1, c2, c3, c4 = create_colors(base_color)
|
|
||||||
image = create_base_image(c1, c2, c3, c4)
|
|
||||||
|
|
||||||
if lines:
|
|
||||||
image = add_lines(image, base_color.rgb + (lines,))
|
|
||||||
if lines_bright:
|
|
||||||
image = add_lines(image, (1.0, 1.0, 1.0, lines_bright))
|
|
||||||
if lines_dark:
|
|
||||||
image = add_lines(image, (0.0, 0.0, 0.0, lines_dark))
|
|
||||||
|
|
||||||
if pixelate:
|
|
||||||
image = add_pixelation(image, px, py)
|
|
||||||
|
|
||||||
if emblem:
|
|
||||||
image = add_emblem(image, emblem)
|
|
||||||
|
|
||||||
image.mode = "RGB"
|
|
||||||
|
|
||||||
if preview:
|
|
||||||
image.show()
|
|
||||||
if not output:
|
|
||||||
save = input("Do you want to save the image? [y/N] ")
|
|
||||||
if save == "y" or save == "Y":
|
|
||||||
path = input("Enter the path where the wallpaper shall be saved: ")
|
|
||||||
save_image(path, image)
|
|
||||||
|
|
||||||
if output:
|
|
||||||
save_image(output, image)
|
|
209
huepaper/__init__.py
Normal file
209
huepaper/__init__.py
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw, ImageOps
|
||||||
|
from colour import Color
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
def get_base_color(
|
||||||
|
color_string=None, sat_min=0.2, sat_max=1.0, lum_min=0.2, lum_max=0.9
|
||||||
|
):
|
||||||
|
"""Get base color for a huepaper by color string."""
|
||||||
|
# If no color string is given, create a random color
|
||||||
|
if not color_string:
|
||||||
|
hue = random.uniform(0, 1)
|
||||||
|
sat = random.uniform(sat_min, sat_max)
|
||||||
|
lum = random.uniform(lum_min, lum_max)
|
||||||
|
base_color = Color(hue=hue, saturation=sat, luminance=lum)
|
||||||
|
print("Selected random base color: {}".format(base_color.hex))
|
||||||
|
|
||||||
|
# Else try to parse string
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
base_color = Color(color_string)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
base_color = Color("#{}".format(color_string))
|
||||||
|
except:
|
||||||
|
print("Not a valid color expression: {}".format(color_string))
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
return base_color
|
||||||
|
|
||||||
|
|
||||||
|
def create_colors(
|
||||||
|
base_color=None, hue_max=0.1, sat_min=0.2, sat_max=1.0, lum_min=0.2, lum_max=0.9
|
||||||
|
):
|
||||||
|
"""Create four corner colors for a huepaper by an optional base color."""
|
||||||
|
if not base_color:
|
||||||
|
base_color = get_base_color(None, sat_min, sat_max, lum_min, lum_max)
|
||||||
|
|
||||||
|
colors = []
|
||||||
|
|
||||||
|
max_sat_diff = 0.1
|
||||||
|
max_lum_diff = 0.1
|
||||||
|
|
||||||
|
# Create four random colors similar to the given base_color
|
||||||
|
for i in range(0, 4):
|
||||||
|
|
||||||
|
tmp_hue = base_color.hue + random.uniform(-hue_max / 2.0, hue_max / 2.0)
|
||||||
|
if tmp_hue > 1.0:
|
||||||
|
tmp_hue -= 1
|
||||||
|
|
||||||
|
tmp_sat = base_color.saturation + random.uniform(-max_sat_diff, max_sat_diff)
|
||||||
|
tmp_sat = min(sat_max, max(sat_min, tmp_sat))
|
||||||
|
|
||||||
|
tmp_lum = base_color.luminance + random.uniform(-max_lum_diff, max_lum_diff)
|
||||||
|
tmp_lum = min(lum_max, max(lum_min, tmp_lum))
|
||||||
|
|
||||||
|
color = Color(hue=tmp_hue, saturation=tmp_sat, luminance=tmp_lum)
|
||||||
|
colors.append(color.rgb)
|
||||||
|
|
||||||
|
return tuple(colors)
|
||||||
|
|
||||||
|
|
||||||
|
def create_base_image(c1, c2, c3, c4, width=1920, height=1080):
|
||||||
|
"""Create a base huepaper by four corner colors.
|
||||||
|
|
||||||
|
c1 - top left
|
||||||
|
c2 - top right
|
||||||
|
c3 - bottom right
|
||||||
|
c4 - bottom left
|
||||||
|
"""
|
||||||
|
# Lambda for adding four colors
|
||||||
|
add = lambda c1, c2, c3, c4: (
|
||||||
|
c1[0] + c2[0] + c3[0] + c4[0],
|
||||||
|
c1[1] + c2[1] + c3[1] + c4[1],
|
||||||
|
c1[2] + c2[2] + c3[2] + c4[2],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Lambda for multiplying a color with a factor
|
||||||
|
mul = lambda c, x: (c[0] * x, c[1] * x, c[2] * x)
|
||||||
|
|
||||||
|
# Lambda for scaling a color from [0 , 1] to [0, 255]
|
||||||
|
cor = lambda c: (int(c[0] * 255), int(c[1] * 255), int(c[2] * 255))
|
||||||
|
|
||||||
|
# Lambda for calculating a color at x and y in range [0, 1]
|
||||||
|
# Color limits are set at creation
|
||||||
|
col = lambda x, y, c1=c1, c2=c2, c3=c3, c4=c4: cor(
|
||||||
|
add(
|
||||||
|
mul(c1, (1.0 - x) * (1.0 - y)),
|
||||||
|
mul(c2, x * (1.0 - y)),
|
||||||
|
mul(c3, x * y),
|
||||||
|
mul(c4, (1.0 - x) * y),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create image
|
||||||
|
image = Image.new("RGBA", (width, height))
|
||||||
|
pixels = image.load()
|
||||||
|
|
||||||
|
for x in range(0, width):
|
||||||
|
for y in range(0, height):
|
||||||
|
pixels[x, y] = col(x / (width - 1), y / (height - 1))
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def add_lines(image, color):
|
||||||
|
"""Add one to three random lines to an image with given color."""
|
||||||
|
width, height = image.size
|
||||||
|
|
||||||
|
line_image = Image.new("RGBA", (width, height), (0, 0, 0, 0))
|
||||||
|
draw = ImageDraw.Draw(line_image)
|
||||||
|
|
||||||
|
# Set color
|
||||||
|
color = tuple(map(lambda x: int(x * 255), color))
|
||||||
|
|
||||||
|
# Generate lines
|
||||||
|
number_of_lines = random.randint(1, 3)
|
||||||
|
scale = width / 100.0
|
||||||
|
base_width = random.randint(int(2 * scale), int(5 * scale))
|
||||||
|
rand_width = lambda base_width=base_width: base_width + random.randint(
|
||||||
|
-base_width // 2, base_width // 2
|
||||||
|
)
|
||||||
|
space = rand_width() // 2
|
||||||
|
offset = random.randint(0, space)
|
||||||
|
for i in range(0, number_of_lines):
|
||||||
|
line_width = rand_width()
|
||||||
|
x = offset + space + (line_width // 2)
|
||||||
|
draw.line((x, 0, x, height), fill=color, width=line_width)
|
||||||
|
offset += space + line_width
|
||||||
|
|
||||||
|
# Mirror line image eventually
|
||||||
|
orientation = random.randrange(2)
|
||||||
|
if orientation == 1:
|
||||||
|
line_image = ImageOps.mirror(line_image)
|
||||||
|
|
||||||
|
# Add line image to input image
|
||||||
|
image.alpha_composite(line_image, (0, 0))
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def add_pixelation(image, x=16, y=9):
|
||||||
|
"""Pixelate an image."""
|
||||||
|
width, height = image.size
|
||||||
|
|
||||||
|
image = image.resize((x, y))
|
||||||
|
image = image.resize((width, height), Image.BOX)
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def add_emblem(image, filepath):
|
||||||
|
"""Add an amblem to an image by filepath."""
|
||||||
|
width, height = image.size
|
||||||
|
|
||||||
|
# Load image
|
||||||
|
try:
|
||||||
|
emblem_image = Image.open(filepath)
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to load emblem: {}".format(e))
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# Exit if emblem is too big
|
||||||
|
if emblem_image.size[0] > width or emblem_image.size[1] > height:
|
||||||
|
print("Emblem can't be bigger than the wallpaper")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# Insert emblem in the center
|
||||||
|
offset = (
|
||||||
|
(image.size[0] - emblem_image.size[0]) // 2,
|
||||||
|
(image.size[1] - emblem_image.size[1]) // 2,
|
||||||
|
)
|
||||||
|
image.alpha_composite(emblem_image, offset)
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def save_image(image, filepath):
|
||||||
|
"""Save an image at given filepath."""
|
||||||
|
save = True
|
||||||
|
|
||||||
|
# Check whether file exists
|
||||||
|
if os.path.isfile(filepath):
|
||||||
|
overwrite = input(
|
||||||
|
"The file {} already exists. Do you want to overwrite it? [y/N] ".format(
|
||||||
|
filepath
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if overwrite != "y" and overwrite != "Y":
|
||||||
|
save = False
|
||||||
|
|
||||||
|
if save:
|
||||||
|
|
||||||
|
stop = False
|
||||||
|
while not stop:
|
||||||
|
try:
|
||||||
|
image.save(filepath)
|
||||||
|
stop = True
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to save wallpaper: {}".format(e))
|
||||||
|
again = input("Do you want to try again? [Y/n] ")
|
||||||
|
if again == "n" or again == "N":
|
||||||
|
stop = True
|
||||||
|
else:
|
||||||
|
filepath = input(
|
||||||
|
"Please enter new path where the wallpaper shall be saved: "
|
||||||
|
)
|
@ -1,3 +1,2 @@
|
|||||||
colour
|
colour
|
||||||
pillow
|
pillow
|
||||||
wheel
|
|
||||||
|
15
setup.py
Normal file
15
setup.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="huepaper",
|
||||||
|
version="0.0.1",
|
||||||
|
author="Denis Lehmann",
|
||||||
|
author_email="denis@opaque.tech",
|
||||||
|
scripts=["bin/huepaper"],
|
||||||
|
packages=["huepaper"],
|
||||||
|
url="https://git.opaque.tech/denis/huepaper",
|
||||||
|
license="LICENSE",
|
||||||
|
description="A colorful wallpaper generator",
|
||||||
|
long_description=open("README.org").read(),
|
||||||
|
install_requires=["colour", "pillow"],
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user