Update: credit to David in the comments of my previous post, there's a much fancier implementation of this here: https://github.com/flozz/cover-thumbnailer
Going further in my delight at belatedly discovering the "metadata::custom-icon" GVFS attribute used by Nautilus, I extended beyond just music album covers to write a script that did a fun 2x2 grid for photo album covers.
From this:
To this:
This script is uglier, so maybe write your own, but you can have a look-see to see what I did. I learned some new syntax for ImageMagick in the process (using ^ when scaling to treat the geometry as a minimum rather than a maximum, using "-gravity center" to crop from the center, etc.),
#!/bin/sh # Run in a directory containing photo album folders. Will generate 2x2 grid thumbnail images of photos within, and set them as the # folder icon. (Recurses down through all subfolders.) # set GVFS attribute "metadata::custom-icon" # e.g. gio set /path/to/album/dir "metadata::custom-icon" "file:///home/USER/files/music/ARTIST NAME/ALBUM NAME/cover.jpg" # to reset it: # gio set /path/to/album/dir "metadata::custom-icon" -d function crop { FILE="${1}"; DIM="${2}"; # e.g. "200x200" # scale so that the min-dimension is 200 (we'll crop out whatever exceeds it in the max dimension) # so if we're given an 400x1000 photo here, we'll scale it to 200x500, thanks to ^ convert "${FILE}" -scale "${DIM}+0+0^" "${FILE}.scaled"; # crop a 200x200 square from the center, so if we have a 200x500, we'll lose the top and bottom 50 convert "${FILE}.scaled" -gravity center -crop "${DIM}+0+0" "${FILE}.cropped" # now we have a nice 200x200 version, centered # emit the name of the newly cropped file echo "${FILE}.cropped"; } # provide a '-f' option to regenerate existing photo album covers; by default, it skips dirs where one already exists if [ "${1}" == -f ]; then FORCE=1 else FORCE=0 fi find ./ -type d | while read DIR; do # skip . hidden directories if basename "${DIR}" | grep "^\."; then continue; fi echo "${DIR}..."; # check if a generated photo album already exists and skip redoing it (unless -f set) if [ -f "${DIR}/.npac_cover.jpg" ] && [ "${FORCE}" -eq 0 ]; then echo " Already generated, skipping (use -f to force regeneration)"; continue; fi # create a temporary directory to do image cropping and stitching in TMPDIR="$(mktemp -d)"; # find 4 images below dir for potential thumbnailing; use 'sort -R' to randomize the list find "${DIR}" -regextype egrep -iregex ".*\.(jpg|jpeg|png|webp)$" | sort -R | while read COVER_PART; do # because I sometimes have duplicate files for various reasons, and # I don't want an image repeated, I work with them using their hash HASH="$(md5sum "${COVER_PART}" | cut -b 1-32)"; if ! [ -f "${TMPDIR}/${HASH}" ]; then echo " ${COVER_PART}"; cp "${COVER_PART}" "${TMPDIR}/${HASH}.part" fi if [ "$(ls "${TMPDIR}" | wc -l)" -ge 4 ]; then break; fi done; # lets create a 2x2 grid of 4 images, but also support fewer if necessary ( cd "${TMPDIR}"; NUM_PARTS="$(ls | wc -l)"; P1="$(ls | head -n 1 | tail -n 1)"; P2="$(ls | head -n 2 | tail -n 1)"; P3="$(ls | head -n 3 | tail -n 1)"; P4="$(ls | head -n 4 | tail -n 1)"; if [ "${NUM_PARTS}" -ge 3 ]; then # stitch the first two together side-by-side for the top half of a 3 or 4 grid convert "$(crop "${P1}" 200x200)" "$(crop "${P2}" 200x200)" -background black +append "top.jpg" if [ "${NUM_PARTS}" -ge 4 ]; then # stitch two together for the bottom, then stitch top and bottom together for the grid, yay convert "$(crop "${P3}" 200x200)" "$(crop "${P4}" 200x200)" -background black +append "bottom.jpg" convert "top.jpg" "bottom.jpg" -background black -append "grid.jpg" elif [ "${NUM_PARTS}" -eq 3 ]; then # only have 3 images, so make the 3rd one take up the whole bottom convert "top.jpg" "$(crop "${P3}" 400x200)" -background black -append "grid.jpg" fi elif [ "${NUM_PARTS}" -eq 2 ]; then # only have two, so stack them vertically convert "$(crop "${P1}" 400x200)" "$(crop "${P2}" 400x200)" -background black -append "grid.jpg" elif [ "${NUM_PARTS}" -eq 1 ]; then # only have one, so it'll be the whole grid! cp "$(crop "${P1}" 400x400)" grid.jpg else echo "WARNING: nautilus_photo_album_cover.sh: no images found for dir '${DIR}' in tmpdir '${TMPDIR}'."; fi ) # if we successfully generated a grid of images, copy it to the photo album dir as a # hidden thumbnail image (.npac_cover.jpg), set "metadata::custom-icon" in GVFS, and then remove the temp dir if [ -f "${TMPDIR}/grid.jpg" ]; then cp "${TMPDIR}/grid.jpg" "${DIR}/.npac_cover.jpg" gio set "${DIR}" metadata::custom-icon "file://$(realpath "${DIR}/.npac_cover.jpg")"; rm -rf "${TMPDIR}" fi done
To do:
- Add a cute folder emblem to the bottom right of the 2x2 icons, and maybe put a border around it, to make it more obviously still a folder!
- It fails on some folders for some reason, look into it :D
- Correct orientation issues