151 lines
4.1 KiB
Nix
151 lines
4.1 KiB
Nix
{ pkgs, config, lib ? pkgs.lib }:
|
|
|
|
let
|
|
colors = config.colorScheme.palette;
|
|
mediaImages = config.syscfg.media.main;
|
|
mediaNames = map (image: builtins.baseNameOf (toString image)) mediaImages;
|
|
mediaSourceDir = pkgs.linkFarm "wallpaper-media" (
|
|
map (image: {
|
|
name = builtins.baseNameOf (toString image);
|
|
path = image;
|
|
}) mediaImages
|
|
);
|
|
|
|
dither = "atkinson"; # none | floyd-steinberg | atkinson | jjn | burkes | sierra | sierra-lite
|
|
paletteSize = 0;
|
|
|
|
hexChars = "0123456789abcdef";
|
|
hexMap = {
|
|
"0" = 0; "1" = 1; "2" = 2; "3" = 3;
|
|
"4" = 4; "5" = 5; "6" = 6; "7" = 7;
|
|
"8" = 8; "9" = 9; "a" = 10; "b" = 11;
|
|
"c" = 12; "d" = 13; "e" = 14; "f" = 15;
|
|
};
|
|
|
|
baseColors = [
|
|
colors.base00
|
|
colors.base01
|
|
colors.base02
|
|
colors.base03
|
|
colors.base04
|
|
colors.base05
|
|
colors.base06
|
|
colors.base07
|
|
colors.base08
|
|
colors.base09
|
|
colors.base0A
|
|
colors.base0B
|
|
colors.base0C
|
|
colors.base0D
|
|
colors.base0E
|
|
colors.base0F
|
|
];
|
|
|
|
round = x: builtins.floor (x + 0.5);
|
|
clamp = x:
|
|
if x < 0 then 0 else if x > 255 then 255 else x;
|
|
parseHexByte = byte:
|
|
let
|
|
hi = hexMap.${builtins.substring 0 1 byte};
|
|
lo = hexMap.${builtins.substring 1 1 byte};
|
|
in
|
|
hi * 16 + lo;
|
|
hexToRgb = hex:
|
|
let
|
|
clean = lib.toLower (lib.removePrefix "#" hex);
|
|
in
|
|
{
|
|
r = parseHexByte (builtins.substring 0 2 clean);
|
|
g = parseHexByte (builtins.substring 2 2 clean);
|
|
b = parseHexByte (builtins.substring 4 2 clean);
|
|
};
|
|
componentToHex = value:
|
|
let
|
|
bounded = clamp value;
|
|
hi = builtins.div bounded 16;
|
|
lo = bounded - hi * 16;
|
|
in
|
|
"${builtins.substring hi 1 hexChars}${builtins.substring lo 1 hexChars}";
|
|
rgbToHex = color: "${componentToHex color.r}${componentToHex color.g}${componentToHex color.b}";
|
|
|
|
getTint = c: weight: round (c + (255 - c) * weight);
|
|
getShade = c: weight: round (c * weight);
|
|
tint = color: weight: {
|
|
r = getTint color.r weight;
|
|
g = getTint color.g weight;
|
|
b = getTint color.b weight;
|
|
};
|
|
shade = color: weight: {
|
|
r = getShade color.r weight;
|
|
g = getShade color.g weight;
|
|
b = getShade color.b weight;
|
|
};
|
|
genPalette = color:
|
|
let
|
|
tints =
|
|
if paletteSize == 0
|
|
then [ ]
|
|
else lib.genList (i: tint color ((i + 1.0) / paletteSize)) paletteSize;
|
|
shades =
|
|
if paletteSize == 0
|
|
then [ ]
|
|
else lib.genList (i: shade color (i * 1.0 / paletteSize)) paletteSize;
|
|
in
|
|
lib.reverseList tints ++ [ color ] ++ lib.reverseList shades;
|
|
keepColor = color:
|
|
let
|
|
sum = color.r + color.g + color.b;
|
|
in
|
|
sum > 0 && sum < 765;
|
|
|
|
paletteColors = lib.concatMap (hex: lib.filter keepColor (genPalette (hexToRgb hex))) baseColors;
|
|
paletteHex = lib.concatStringsSep "," (map rgbToHex paletteColors);
|
|
gifPaletteFile = pkgs.writeText "wallpaper-gifpalette.txt" (
|
|
lib.concatMapStringsSep "\n" (color: "${toString color.r} ${toString color.g} ${toString color.b}") paletteColors
|
|
);
|
|
|
|
buildCommands =
|
|
lib.concatMapStringsSep "\n" (name:
|
|
let
|
|
source = "${mediaSourceDir}/${name}";
|
|
target = "build/${name}";
|
|
in
|
|
if lib.hasSuffix ".gif" (lib.toLower name) then ''
|
|
gifsicle --use-colormap ${lib.escapeShellArg (toString gifPaletteFile)} < ${lib.escapeShellArg source} > ${lib.escapeShellArg target}
|
|
'' else ''
|
|
repalette ${lib.escapeShellArg source} ${lib.escapeShellArg target} -p ${lib.escapeShellArg paletteHex} --dither ${lib.escapeShellArg dither}
|
|
''
|
|
) mediaNames;
|
|
in
|
|
assert lib.assertMsg
|
|
(builtins.length mediaNames == builtins.length (lib.unique mediaNames))
|
|
"syscfg.media.main contains duplicate basenames, which would collide in generated wallpaper output.";
|
|
pkgs.stdenv.mkDerivation {
|
|
pname = "generated-wallpaper";
|
|
version = "local";
|
|
dontUnpack = true;
|
|
|
|
nativeBuildInputs = with pkgs; [
|
|
custom.repalette
|
|
gifsicle
|
|
];
|
|
|
|
buildPhase = ''
|
|
runHook preBuild
|
|
|
|
mkdir -p build
|
|
${buildCommands}
|
|
|
|
runHook postBuild
|
|
'';
|
|
|
|
installPhase = ''
|
|
runHook preInstall
|
|
|
|
mkdir -p $out/share/wallpaper
|
|
cp -r build/. $out/share/wallpaper/
|
|
|
|
runHook postInstall
|
|
'';
|
|
}
|