#!/bin/sh -e #=============================================================== # Filename : prepare # Purpose : Prepare wallpapers for Adélie desktop environments. # Authors : Zach van Rijn # License : Apache 2.0 # Revision : 20231205 #=============================================================== #=============================================================== # README #=============================================================== ## # This script transforms source images, including Adélie logos, # into a set of wallpapers suitable for packaging. # # There are two distinct output products: # # (1) a "core" or "slim" bundle, containing a lightweight set of # default wallpaper(s) and/or branding; and # # (2) a "full" bundle containing all available wallpapers, which # is suitable for use when disk space isn't a major concern. # # # # requirements # ------------ # # * imagemagick # # # usage # ----- # # To process all source images and generate a tarball for upload # to 'distfiles', simply run the following command: # # $ ./prepare # # Any tarball of the same name will be silently overwritten. # #--------------------------------------------------------------- # configuration: source image input #--------------------------------------------------------------- ## # Distfiles mirror. # HOST="https://distfiles.adelielinux.org"; ## # Adélie brand asset bundle version. # # This corresponds to the commit of 'adelie/site-ng' from which # the brand assets were generated. A tarball matching this hash # must exist in the '/source/site-ng-images/' directory. # # See https://git.adelielinux.org/adelie/site-ng for details. # HASH=ca57e2bd46f11bf2efdebbca8c7813235744fd5f; ## # Name of the containing directory and tarball on distfiles. # NAME="site-ng-images"; #--------------------------------------------------------------- # configuration: processed image output #--------------------------------------------------------------- ## # Name of output directory. Please ensure it is in '.gitignore'. # KEEP="output"; ## # Choose an output file type. # TYPE="jpg"; ## # Table of aspect ratios to generate wallpapers for. # # Format: RATIO SCALE [SCALE ...] # # Scale is distributed, e.g.: # # "4:3 640" --> (640*4)x(640*3) = 2560x1920 # # Note that many popular aspect ratios are approximate. We are # only concerned with getting to the right ballpark. # # Table rows MUST BE SORTED FROM GREATEST TO LEAST. # MAKE=$(grep -v ^# <&1 >/dev/null; then printf "E: required utility '%s' not found!\n" "${k}"; exit 1; fi done ## # Tag first, then generate release the tarball. Sanity checks do # not prevent someone from being stupid, but they can avoid some # common errors. We want to reduce surprises/ensure consistency. # if test "${1}" = "--test"; then VTAG="DEV"; else VTAG=$(git describe --tags --abbrev=0 2>/dev/null || true); if test -z "${VTAG}"; then printf "E: you need to tag at least one commit!\n"; exit 1; fi if test $(git rev-list ${VTAG}..HEAD | wc -l) -gt 0; then printf "E: you need to be checked out at a tag!\n"; exit 1; fi if test $(git ls-remote --tags origin ${VTAG} | wc -l) -eq 0; then printf "E: tag '%s' does not exist on origin!\n" "${VTAG}"; exit 1; fi if test $(git status --porcelain | wc -l) -gt 0; then printf "E: tree is not clean; aborting!\n" "${VTAG}"; exit 1; fi fi ## # Name of build directory. Please ensure it is in '.gitignore'. # TEMP="build"; ## # Name of source directory. # IMGS="src"; ## # Ensure that no images have conflicting names. # # FIXME: factor out 'background lockscreen' here and elsewhere. # for k in background lockscreen; do if test -d "${IMGS}"/${k}; then printf "E: not allowed to name image '%s'!\n" "${k}"; exit 1; fi done #--------------------------------------------------------------- # internal: support routines #--------------------------------------------------------------- ## # size_only DIR RATIO SCALE [SCALE ...] # size_only () { data="${1}"; shift; size="${1}"; shift; from="${1}"; # NO SHIFT list="${@}"; ## # FIXME: assumes 'a:b' where 'a' and 'b' are integers. This # should check that this actually holds. # case "${size}" in *:*) ;; *) printf "E: invalid aspect ratio '%s'!\n" "${size}"; exit 1; ;; esac ## # Generated images have known sizes that do not change. # from_x=$((${from}*${size%:*})); from_y=$((${from}*${size#*:})); printf "Processing %s...\n" "${size}"; find "${data}" -mindepth 1 -maxdepth 1 -type d | sort | while read image; do name=$(printf "%s\n" "${image}" | cut -d/ -f3); # sloppy, sorry case "${name}" in background|lockscreen) type="png"; # override for quality ;; *) type="${TYPE}"; ;; esac printf " * %s\n" "${name}"; mkdir -p "${KEEP}"/${name}; for k in ${list}; do x=$((${k}*${size%:*})); y=$((${k}*${size#*:})); printf " - Generating %4sx%4s (scale: %s)\n" "${x}" "${y}" "${k}"; # resized gm convert "${image}/${from_x}x${from_y}.png" -resize ${x}x${y}^ "${KEEP}"/${name}/${x}x${y}.${type} 2>/dev/null; done done } #--------------------------------------------------------------- # internal: core #--------------------------------------------------------------- mkdir -p "${HERE}/${TEMP}"; rm -fr "${HERE}"/${KEEP}; mkdir "${HERE}/${KEEP}"; ## # Fetch the specified brand asset bundle from distfiles. # # TODO: error checking, return codes etc. # ( cd "${TEMP}"; if ! test -e ${NAME}-${HASH}.tar.gz; then curl -O "${HOST}"/source/${NAME}/${NAME}-${HASH}.tar.gz; fi tar -xf ${NAME}-${HASH}.tar.gz; ) #--------------------------------------------------------------- # internal: generate minimal wallpapers #--------------------------------------------------------------- ## # The default "core" or "slim" wallpaper is made on the fly and # not provided as a rasterized image from the start. # # Discrete conversion steps are used for clarity of intent, even # though the same effect can be achieved by combining steps. # # FIXME: the 'MENU' padding needs to be 100px after resizing; we # currently do it before resizing. So we have to do a "reverse" # calculation to determine what is the equivalent of 100px for # the shortest target size for each aspect ratio. 100px is also # just an estimate and is not based on actual facts. # ## # make_fake GRADIENT_FROM GRADIENT_TO XxY TEMPLATE OUTPUT [ARGS] # make_fake () { size="${1}"; shift; # geometry hexa="${1}"; shift; # gradient from hexb="${1}"; shift; # gradient to temp="${1}"; shift; # template name="${1}"; shift; # output filename args="${@}"; # all remaining arguments printf "Generating %5s ('%s')...\n" "${size}" "${name}"; # generate gradient brackground of correct size gm convert \ -define gradient:direction=NorthEast \ -size ${size} \ gradient:"${hexa}"-"${hexb}" \ "${name}" \ ; # polyguin scaled to 80% of Y-MENU, translated +MENU gm convert \ -background none \ -resize ${size%x*}x$(((${size#*x}-${MENU})*80/100)) \ "${TEMP}"/polyguin.svg \ "${name}.tmp.png" \ ; gm composite \ -compose atop \ -gravity southwest \ "${name}.tmp.png" \ -geometry +0+${MENU} \ "${name}" \ "${name}" \ ; # polylogo scaled to 10% of Y-MENU, translated +MENU gm convert \ -background none \ -resize ${size%x*}x$(((${size#*x}-${MENU})*10/100)) \ "${TEMP}"/gen_polylogo_template_${temp}.png \ "${name}.tmp.png" \ ; gm composite \ -compose atop \ -gravity southeast \ "${name}.tmp.png" \ -geometry +50+${MENU} \ "${name}" \ "${name}" \ ; rm "${name}.tmp.png"; # apply any custom transformations gm convert \ ${args} \ "${name}" \ "${name}" \ ; } ## # Generate starting templates. That is, generate the largest one # possible for each aspect ratio. # printf "%s\n" "${MAKE}" | while read ratio scale _; do # compute largest required x=$((${scale}*${ratio%:*})); y=$((${scale}*${ratio#*:})); # background (monochrome) mkdir -p "${TEMP}"/generated/background; make_fake ${x}x${y} \ "#777777" "#dddddd" \ black_x200 \ "${TEMP}"/generated/background/${x}x${y}.png \ -colorspace Gray \ ; # lockscreen (full color) mkdir -p "${TEMP}"/generated/lockscreen; make_fake ${x}x${y} \ "#111111" "#444444" \ white_x200 \ "${TEMP}"/generated/lockscreen/${x}x${y}.png \ ; done #--------------------------------------------------------------- # internal: scale all wallpapers #--------------------------------------------------------------- ## # To generate "real" wallpapers, we simply resize them. This can # be be improved significantly, but that is a future problem. # make_real () { size="${1}"; shift; # geometry temp="${1}"; shift; # template name="${1}"; shift; # output filename # TODO: add filename extension checker? printf "Generating %5s ('%s')...\n" "${size}" "${name}"; gm convert "${file}" -resize ${size}^ "${name}" 2>/dev/null; } ## # Source images may not all be consistent in their aspect ratios # or dimensions. We will scale (crop) source images to match the # sizes of the generated core templates. # printf "%s\n" "${MAKE}" | while read ratio scale _; do # compute largest required x=$((${scale}*${ratio%:*})); y=$((${scale}*${ratio#*:})); find "${IMGS}" -mindepth 1 -maxdepth 1 -type d | sort | while read k; do file="$(find ${k} -type f -name 'image.*')"; if test $(printf "%s\n" "${file}" | wc -l) -ne 1; then printf "E: not exactly one image at '%s'!\n" "${k}"; exit 1; fi # FIXME: is it OK to hard-code '.png' here? name=$(printf "%s\n" "${file}" | cut -d/ -f2); # sloppy, sorry mkdir -p "${TEMP}"/generated/${name}; make_real ${x}x${y} "${file}" "${TEMP}"/generated/${name}/${x}x${y}.png; done done #--------------------------------------------------------------- # output: scale all wallpapers #--------------------------------------------------------------- ## # For each input image, generate a full set of output images. # # Note that this loop includes all columns; rely on 'size_only' # to handle the rest. # printf "%s\n" "${MAKE}" | while read k; do size_only "${TEMP}"/generated ${k}; done #--------------------------------------------------------------- # output: screenshots #--------------------------------------------------------------- find "${TEMP}"/generated -mindepth 1 -maxdepth 1 -type d | sort | while read k; do name=$(printf "%s\n" "${k}" | cut -d/ -f3); # sloppy, sorry printf "Generating screenshot ('%s')...\n" "${KEEP}/${name}/screenshot.jpg"; gm convert "${k}"/1600x1000.png -resize 400x250^ "${KEEP}"/${name}/screenshot.jpg 2>/dev/null; done #--------------------------------------------------------------- # output: metadata #--------------------------------------------------------------- ## # FIXME: make this not ugly # temp=$(mktemp); cat >> "${temp}" <<"EOF" EOF find "${TEMP}"/generated -mindepth 1 -maxdepth 1 -type d | sort | while read k; do name=$(printf "%s\n" "${k}" | cut -d/ -f3); # sloppy, sorry # fix structure mv "${KEEP}"/${name} "${KEEP}"/${name}.tmp; mkdir -p "${KEEP}"/${name}/contents; mv "${KEEP}"/${name}.tmp "${KEEP}"/${name}/contents/images; # compute metadata case "${name}" in background) description="Default Background"; author_name="Adélie Platform Team"; ;; lockscreen) description="Default Lockscreen"; author_name="Adélie Platform Team"; ;; *) . "${IMGS}"/${name}/MANIFEST; ;; esac # write metadata to 'manifest.desktop' # FIXME: we can do better than 'tr' below, but also what are # the actual requirements? I'm just emulating what exists... cat > "${KEEP}"/${name}/metadata.desktop <> "${temp}" < ${description} /usr/share/wallpapers/${name}/contents/images/${file##*/} zoom EOF done done ## # FIXME: make this not ugly # cat >> "${temp}" < EOF #--------------------------------------------------------------- # output: create tarball #--------------------------------------------------------------- rm -fr adelie-wallpapers-${VTAG}; mkdir -p adelie-wallpapers-${VTAG}/usr/share; # wallpapers mv "${KEEP}" adelie-wallpapers-${VTAG}/usr/share/wallpapers; # gnome-background-properties mkdir -p adelie-wallpapers-${VTAG}/usr/share/gnome-background-properties; mv "${temp}" adelie-wallpapers-${VTAG}/usr/share/gnome-background-properties/Adelie.xml; # generate tarball rm -f adelie-wallpapers-${VTAG}.tar.xz; tar -pcJf adelie-wallpapers-${VTAG}.tar.xz adelie-wallpapers-${VTAG}; # clean up rm -fr "${TEMP}"/generated; rm -fr adelie-wallpapers-${VTAG};