16 Aug, 2023
I have a hard disk full of old files, some of which are photos.
I've written a script to take find the photos and store a de-duplicated copy (based on sha256) into a drive.
I then re-generate the original folder structure so that I can browse them as before, using a hard link to the sha256 copy.
Now I'd like to be able to browse that folder structure quickly using Gnome's built in file manager. To do that I need to generate all the thumbnails in advance.
WARNING: This is quickly jotted down as a note to myself rather than a full, tested tutorial, your mileage may vary.
Before I go into some code, here are some related links:
It turns out there is an entire infrastructure for thumbnailing.
I amend my /usr/share/thumbnailers/gdk-pixbuf-thumbnailer.thumbnailer
file to this to support more file types:
[Thumbnailer Entry]
TryExec=/usr/bin/gdk-pixbuf-thumbnailer
Exec=/usr/bin/gdk-pixbuf-thumbnailer -s %s %u %o
MimeType=image/png;image/jpeg;image/bmp;image/x-bmp;image/x-MS-bmp;image/gif;image/x-icon;image/x-ico;image/x-win-bitmap;image/vnd.microsoft.icon;application/ico;image/ico;image/icon;text/ico;application/x-navi-animation;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/tiff;image/x-xpixmap;image/x-xbitmap;image/x-tga;image/x-icns;image/x-quicktime;image/qtif;image/x-canon-cr2;image/x-sony-arw;image/x-canon-crw;image/x-kodak-dcr;image/x-adobe-dng;image/x-epson-erf;image/x-kodak-k25;image/x-kodak-kdc;image/x-minolta-mrw;image/x-nikon-nef;image/x-olympus-orf;image/x-pentax-pef;image/x-sony-sr2;image/x-sony-srf;image/x-sigma-x3f;
This doesn't seem to work for Fuji or Lumix cameras so I create a new /usr/share/thumbnailers/raf.thumbnailer
like this:
[Thumbnailer Entry]
TryExec=/usr/local/bin/raf-thumbnailer
Exec=/usr/local/bin/raf-thumbnailer %i %o %s
MimeType=image/x-fuji-raf;image/x-raf;image/x-panasonic-raw;
Where the /usr/local/bin/raf-thumbnailer
file looks like this:
#!/bin/bash
# Thumbnailer for Fujifilm RAF files
# This script depends on the following packages:
# - exiv2 for exiv2
# - imagemagick for convert
# Check for correct number of command-line arguments
if [ $# -eq 3 ]
then
# First argument is path to RAW file (convert from URI to normal path)
RAW="$1"
# Second argument is output path for thumbnail file
OUT="$2"
# Third argument is image size
SIZE="$3"
# Remove directory from path
NAME="${RAW##*/}"
# Remove extension from file name
BASE="${NAME%.*}"
# Compose path to thumbnail as composed by exiv2
PREV="/tmp/${BASE}-preview2.jpg"
# Extract preview image from RAW file
exiv2 -l /tmp -ep2 -f "${RAW}"
# Convert preview image into thumbnail
convert -auto-orient -scale "${SIZE}x${SIZE}" "${PREV}" "${OUT}"
# Delete preview image
rm -f "${PREV}"
fi
Checking the permissions:
ls -la /usr/share/thumbnailers/raf.thumbnailer /usr/local/bin/raf-thumbnailer
-rw-r--r-- 1 james james 1828 Aug 16 09:21 /home/james/Desktop/thumbs/thumbs.py
-rwxr-xr-x 1 root root 901 Aug 16 09:35 /usr/local/bin/raf-thumbnailer
-rw-r--r-- 1 root root 143 Aug 16 09:25 /usr/share/thumbnailers/raf.thumbnailer
Now, thumbnails should be correctly generated as I browse, but I want to convert them all upfront.
Here's a script to run the thumbnailer infrastructure (adjust the paths for bits you want to skip):
import os
import sys
from gi.repository import Gio, GnomeDesktop
def make_thumbnail(factory, filename):
mtime = os.path.getmtime(filename)
# Use Gio to determine the URI and mime type
f = Gio.file_new_for_path(filename)
uri = f.get_uri()
if uri.startswith('file:///media/james/src') or uri.startswith('file:///media/james/target/'):
# print("SKIP %s" % uri)
return False
info = f.query_info(
'standard::content-type', Gio.FileQueryInfoFlags.NONE, None)
mime_type = info.get_content_type()
if factory.lookup(uri, mtime) is not None:
print("FRESH %s" % uri)
return False
if not factory.can_thumbnail(uri, mime_type, mtime):
print("UNSUPPORTED %s" % uri)
return False
try:
thumbnail = factory.generate_thumbnail(uri, mime_type)
if thumbnail is None:
print("ERROR %s" % uri)
return False
except BaseException as e:
print("ERROR %s" % uri)
print(e)
return False
time.sleep(0.05)
print("OK %s" % uri)
factory.save_thumbnail(thumbnail, uri, mtime)
return True
def thumbnail_folder(factory, folder):
for dirpath, dirnames, filenames in os.walk(folder):
for filename in filenames:
make_thumbnail(factory, os.path.join(dirpath, filename))
def main(argv):
factory = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.LARGE)
for filename in argv[1:]:
if os.path.isdir(filename):
thumbnail_folder(factory, filename)
else:
make_thumbnail(factory, filename)
if __name__ == '__main__':
sys.exit(main(sys.argv))
When I run this all thumbnails are generated.
Gnome is quite keen at purging them all though, so I back them all up and restore them as needed.
mkdir -p /home/james/Desktop/thumbs/cache/large
rsync -aHv /home/james/.cache/thumbnails/large/ /home/james/Desktop/thumbs/cache/large/
du -hs /home/james/Desktop/thumbs/cache/large
I can find any misgenerated ones, or work their types with commands similar to this:
find ~/.cache/thumbnails/large/ -type f -size -4096c -exec ls -la {} \;
xdg-mime query filetype INPUT_FILE
Be the first to comment.
Copyright James Gardner 1996-2020 All Rights Reserved. Admin.