Compare commits

..

1 commit

Author SHA1 Message Date
fede603b99 first Nim draft 2021-07-27 19:11:07 +02:00
9 changed files with 177 additions and 61 deletions

View file

@ -1,4 +1,7 @@
* huepaper - a colorful wallpaper generator
:PROPERTIES:
:CUSTOM_ID: huepaper
:END:
#+caption: Logo
[[./images/logo.png]]
@ -6,38 +9,56 @@
*huepaper* creates wallpapers based on color hues. Bring a little color in your life by randomness, because every huepaper is truly unique.
You can find [[#examples][examples]] below.
For more examples visit the Mastodon [[https://botsin.space/@huebot][huebot]].
** Installation
:PROPERTIES:
:CUSTOM_ID: installation
:END:
*** Nix
:PROPERTIES:
:CUSTOM_ID: nix
:END:
This project is a [[https://nixos.wiki/wiki/Flakes][Nix Flake]].
If you have a recent version of the [[https://nixos.org/][Nix package manager]] installed and Flakes are enabled, run huepaper like this:
If you have a recent version of the [[https://nixos.org/][Nix package manager]] installed and flakes are enabled, run huepaper like this:
: $ nix run github:Deleh/huepaper
#+begin_example sh
nix run github:Deleh/huepaper
#+end_example
Parameters can be passed by appending a double-dash:
: $ nix run github:Deleh/huepaper -- -hue 0.5 --color lightblue
#+begin_example sh
nix run github:Deleh/huepaper -- -hue 0.5 --color lightblue
#+end_example
Global installation can be done by including this flake in your flaked NixOS configuration as always :)
*** Legacy
:PROPERTIES:
:CUSTOM_ID: legacy
:END:
Execute the following steps to run huepaper:
: $ pip install -r requirements.txt
: $ ./huepaper.py
#+begin_example sh
pip install -r requirements.txt
./huepaper.py
#+end_example
To install it in your Python environment run:
: $ python setup.py install
#+begin_example sh
python setup.py install
#+end_example
** Usage
:PROPERTIES:
:CUSTOM_ID: usage
:END:
#+begin_example
#+begin_example text
usage: huepaper [-h] [-s SIZE] [-c COLOR] [-np] [-o OUTPUT] [-l [LINES]] [-lb [LINES_BRIGHT]] [-ld [LINES_DARK]] [-P [PIXELATE]] [-e EMBLEM] [-hue HUE] [-smin SMIN] [-smax SMAX] [-lmin LMIN] [-lmax LMAX]
Create wallpapers based on color hues.
@ -56,18 +77,18 @@
include one to three bright random lines with given opacity in range [0, 1] (default: 0.1)
-ld [LINES_DARK], --lines_dark [LINES_DARK]
include one to three dark random lines with given opacity in range [0, 1] (default: 0.1)
-p [PIXELATE], --pixelate [PIXELATE]
-P [PIXELATE], --pixelate [PIXELATE]
pixelate image with WIDTHxHEIGHT (default: 16x9)
-e EMBLEM, --emblem EMBLEM
emblem to add in the center of the huepaper
-hue HUE maximum hue to differ from given color in range [0, 1] (default: 0.1)
-smin SMIN minimum saturation for colors in range [0, 1] (default: 0.2)
-smax SMAX maximum saturation for colors in range [0, 1] (default: 1.0)
-smin SMIN minimum satisfaction for colors in range [0, 1] (default: 0.2)
-smax SMAX maximum satisfaction for colors in range [0, 1] (default: 1.0)
-lmin LMIN minimum luminance for colors in range [0, 1] (default: 0.2)
-lmax LMAX maximum luminance for colors in range [0, 1] (default: 0.9)
#+end_example
All image operations are called in order of the help file. E.g. pixelate (=-p=) is called after adding lines (=-l=).
All image operations are called in order of the help file. E.g. pixelate (=-P=) is called after adding lines (=-l=).
If you set the color via =-c= it is not guaranteed, that it is included in the huepaper.
Colors, similar to the given one are chosen.
@ -81,9 +102,9 @@
If you want an offset, e.g. put it in the left bottom corner, provide an emblem file with the size of the huepaper, transparent background and your emblem in the bottom left corner.
** Examples
:properties:
:custom_id: examples
:end:
:PROPERTIES:
:CUSTOM_ID: examples
:END:
Please note, that every huepaper call generates a new random image.
You will never get the same huepaper twice.
@ -93,39 +114,39 @@
#+caption: Huepaper 1
[[./images/huepaper_1.png]]
: $ huepaper
=huepaper=
-----
--------------
#+caption: Huepaper 1
[[./images/huepaper_2.png]]
: $ huepaper -c lightgreen
=huepaper -c lightgreen=
-----
--------------
#+caption: Huepaper 3
[[./images/huepaper_3.png]]
: $ huepaper -c "#ff7f50" -lb 0.05
=huepaper -c "#ff7f50" -lb 0.05=
-----
--------------
#+caption: Huepaper 4
[[./images/huepaper_4.png]]
: $ huepaper -hue 1.0 -lmin 0.3 -lmax 0.6 -smin 0.8 -smax 1.0
=huepaper -hue 1.0 -lmin 0.3 -lmax 0.6 -smin 0.8 -smax 1.0=
-----
--------------
#+caption: Huepaper 5
[[./images/huepaper_5.png]]
: $ huepaper -hue 0.3 -lmin 0.5 -lmax 0.5 -l 0.5 -P 64x36
=huepaper -hue 0.3 -lmin 0.5 -lmax 0.5 -l 0.5 -P 64x36=
-----
--------------
#+caption: Huepaper 6
[[./images/huepaper_6.png]]
: $ huepaper -l -lb -ld -e nixos.png
=huepaper -l -lb -ld -e nixos.png=

23
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"lastModified": 1623875721,
"narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"rev": "f7e004a55b120c02ecb6219596820fcd32ca8772",
"type": "github"
},
"original": {
@ -17,18 +17,15 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1676300157,
"narHash": "sha256-1HjRzfp6LOLfcj/HJHdVKWAkX9QRAouoh6AjzJiIerU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "545c7a31e5dedea4a6d372712a18e00ce097d462",
"type": "github"
"lastModified": 1625919529,
"narHash": "sha256-Epn7JRegnKN81hQh4hGx1FOwfp3fBxDCIuSZDgqaBQ4=",
"path": "/nix/store/yh05k932arpkhblqrxnjcp28fpqh7nia-source",
"rev": "cf59fbd539681f5ec2f4a82cf77aae7ab827a03f",
"type": "path"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {

View file

@ -3,10 +3,7 @@
nixConfig.bash-prompt = "\[\\e[1m\\e[34mhuepaper-dev\\e[0m:\\w\]$ ";
inputs = {
nixpkgs.url = github:nixos/nixpkgs/nixos-unstable;
flake-utils.url = github:numtide/flake-utils;
};
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }:
@ -24,7 +21,6 @@
src = self;
propagatedBuildInputs = with pkgs; [
python3Packages.colour
python3Packages.numpy
python3Packages.pillow
];
};
@ -42,7 +38,6 @@
buildInputs = with pkgs; [
python3
python3Packages.colour
python3Packages.numpy
python3Packages.pillow
python3Packages.pip
python3Packages.setuptools

7
huepaper.nim Normal file
View file

@ -0,0 +1,7 @@
import huepaperlib
let bc = getBaseColor()
let cols = createColors(bc, hueMax = 0.5)
let img = createBaseHuepaper(cols, 1920, 1080)
img.saveHuepaper("test.png")

View file

@ -107,7 +107,7 @@ if __name__ == "__main__":
help="include one to three dark random lines with given opacity in range [0, 1] (default: 0.1)",
)
parser.add_argument(
"-p",
"-P",
"--pixelate",
nargs="?",
const="16x9",
@ -126,13 +126,13 @@ if __name__ == "__main__":
"-smin",
default=0.2,
type=float,
help="minimum saturation for colors in range [0, 1] (default: 0.2)",
help="minimum satisfaction for colors in range [0, 1] (default: 0.2)",
)
parser.add_argument(
"-smax",
default=1.0,
type=float,
help="maximum saturation for colors in range [0, 1] (default: 1.0)",
help="maximum satisfaction for colors in range [0, 1] (default: 1.0)",
)
parser.add_argument(
"-lmin",

View file

@ -2,7 +2,6 @@
from PIL import Image, ImageDraw, ImageOps
from colour import Color
import numpy as np
import random
@ -69,18 +68,37 @@ def create_base_image(c1, c2, c3, c4, width=1920, height=1080):
c3 - bottom right
c4 - bottom left
"""
r = np.linspace(
np.linspace(c1[0], c4[0], height), np.linspace(c2[0], c3[0], height), width
)
g = np.linspace(
np.linspace(c1[1], c4[1], height), np.linspace(c2[1], c3[1], height), width
)
b = np.linspace(
np.linspace(c1[2], c4[2], height), np.linspace(c2[2], c3[2], height), width
# 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],
)
im_arr = np.array([r, g, b]).T
image = Image.fromarray(np.uint8(im_arr * 255)).convert("RGBA")
# 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

79
huepaperlib.nim Normal file
View file

@ -0,0 +1,79 @@
import chroma, pixie, random
proc getBaseColor*(colorString: string = "", satMin: float = 0.2,
satMax: float = 1.0, lumMin: float = 0.2, lumMax: float = 0.9): ColorHSL =
## Get base HSL color for a huepaper by `colorString`.
# If no color string is given, create a random color
if colorString == "":
randomize()
let
hue = 360 * rand(1.0)
sat = 100 * (satMin + rand(satMax - satMin))
lum = 100 * (lumMin + rand(lumMax - lumMin))
result = hsl(hue, sat, lum)
# Else try to parse string
else:
try:
result = colorString.parseHtmlColor.hsl
except InvalidColor:
result = ("#" & colorString).parseHtmlColor.hsl
proc createColors*(baseColor: ColorHSL, hueMax: float = 0.1,
satMin: float = 0.2, satMax: float = 1.0, lumMin: float = 0.2,
lumMax: float = 0.9): array[4, ColorRGB] =
## Create four RGB corner colors for a huepaper based on a HSL `baseColor`.
randomize()
let
maxSatDiff = 0.1
maxLumDiff = 0.1
# Create four random colors similar to the given base_color
for i in 0 .. 3:
var
tmpHue = baseColor.h + 360 * (-hueMax / 2.0 + rand(hueMax))
tmpSat = baseColor.s + 100 * (-maxSatDiff + rand(2.0 * maxSatDiff))
tmpLum = baseColor.l + 100 * (-maxLumDiff + rand(2.0 * maxLumDiff))
# Correct hue
if tmpHue > 360.0:
tmpHue -= 360.0
# Clip saturation and luminance
tmpSat = min(100 * satMax, max(100 * satMin, tmpSat))
tmpLum = min(100 * lumMax, max(100 * lumMin, tmpLum))
result[i] = hsl(tmpHue, tmpSat, tmpLum).color.rgb
func blend(c1, c2: ColorRGB, factor: float): ColorRGB =
## Blends color `c1` to color `c2` with a `factor` from 0 to 1.
result.r = (uint8)((1.0 - factor) * (float)c1.r) + (uint8)(factor * (float)c2.r)
result.g = (uint8)((1.0 - factor) * (float)c1.g) + (uint8)(factor * (float)c2.g)
result.b = (uint8)((1.0 - factor) * (float)c1.b) + (uint8)(factor * (float)c2.b)
func createBaseHuepaper*(colors: array[4, ColorRGB], width,
height: int): Image =
## Creates a base huepaper with given `width` and `height`.
## The `colors` are placed in clockwise order, beginning from top left.
result = newImage(width, height)
var
leftColor: ColorRGB
rightColor: ColorRGB
for y in 0 ..< height:
leftColor = colors[0].blend(colors[3], y / (height - 1))
rightColor = colors[1].blend(colors[2], y / (height - 1))
for x in 0 ..< width:
result[x, y] = leftColor.blend(rightColor, x / (width - 1))
proc saveHuepaper*(huepaper: Image, filePath: string) =
## Save `huepaper` at `filePath`.
huepaper.writeFile(filePath)

View file

@ -1,3 +1,2 @@
colour
numpy
pillow

View file

@ -17,5 +17,5 @@ setup(
license="LICENSE",
description="A colorful wallpaper generator",
long_description=open("README.org").read(),
install_requires=["colour", "numpy", "pillow"],
install_requires=["colour", "pillow"],
)