Adding Support for Custom (non-raw) Image Formats
Since version 1.6, ART provides the ability to add reading and writing support for additional (non-raw) image formats via a simple plugin mechanism.
Similarly to User Commands, the mechanism is based on interacting with external programs defined using configuration files, where an external handler is a program that converts to/from tiff files with floating-point data.
How to define custom image handlers
Image handlers are simple text files in the same syntax used by the
arp sidecar files (but with
placed in the
imageio subdirectory directory of ART config folder (typically
$HOME/.config/ART on Linux and
%LOCALAPPDATA%\\ART on Windows),
that must comply with the following specifications:
They must contain a single group of options, called
They must include the following mandatory definitions:
Extension: the (case-insensitive) file extension of the image type handled.
ReadCommand: the command used for loading images of the given type. The path can be either absolute or relative to the current directory; the command can also contain extra arguments (the input files will be appended to the list of arguments); The command will be called with the following arguments:
input_file: path to the image to read
output_file: path to the tiff file to generate.
width_hint: (optional), a hint about the desired image width. This can be used to optimize the reading, assuming that the image will be resized to be at most
width_hintpixels wide. If absent or zero, then the image is needed at its maximum resolution. The command is free to ignore the hint and always return the fullsize image.
height_hint: (optional), analogous to
They can include the following optional definitions:
WriteCommand: the command used for saving images of the given type. It will be called with the following arguments:
input_file: path to a 32-bit float tiff representation of the image to generate.
output_file: path to the file to generate.
Format: the format to use for the intermediate files used to communicate with ART. Possible values are:
png: 8-bit PNG
png16: 16-bit PNG
tiff: 16-bit integer TIFF
float: 32-bit floating-point TIFF (default)
Label: A short description of the image format to be used in the GUI for selecting the given output type. If absent, the uppercase version of
Extensionwill be used.
NOTE: you should also add the appropriate extension to the preferences (in Preferences -> File Browser -> Parsed Extensions) in order for ART to show the pictures in the file browser.
Here is a complete example of a handler for HEIC images that exploits libheif and Exiftool. The script works on Linux, and assumes that
exiftool installed and in the
First, we define the following handler
heic.txt, putting in in
$HOME/.config/ART/imageio (create the directory if it doesn't exist):
[ART ImageIO] # the file extension of the type handled Extension=heic # communicate via 16-bit PNG files Format=png16 # the command for loading ReadCommand=./heif-io.sh load # the command for saving WriteCommand=./heif-io.sh save # the label for the GUI Label=HEIC (via libheif)
The bulk of the work is performed by the companion
heif-io.sh script, which will be put in the same directory (
#!/bin/sh mode=$1 shift if [ "$mode" = "load" ]; then # loading: convert from the input to a png # resize if hints are given if [ "$4" != "" -a "$3" != "0" -a "$4" != "0" ]; then heif-thumbnailer -s "$3x$4" "$1" "$2" else heif-convert -q 100 "$1" "$2" fi test -f "$2" elif [ "$mode" = "save" ]; then # saving: convert from 16-bit png to the output heif-enc -o "$2" "$1" if [ -f "$2" ]; then # copy also the metadata with exiftool exiftool -tagsFromFile "$1" -overwrite_original "$2" fi test -f "$2" else # unknown operating mode, exit with error echo "Unknown operating mode \"$mode\"!" exit 1 fi
Here is the same example handler above written in Python, which might be more suitable for Windows users. It assumes that all the applications (Python, the libheif tools and exiftool) are in the
%PATH% (Windows binaries for libheif tools can be downloaded from here):
[ART ImageIO] # the file extension of the type handled Extension=heic # communicate via 16-bit PNG files Format=png16 # the command for loading ReadCommand=python.exe ./heif-io.py load # the command for saving WriteCommand=python.exe ./heif-io.py save # the label for the GUI Label=HEIC (via libheif)
import os, subprocess, argparse def getopts(): p = argparse.ArgumentParser() p.add_argument("mode", choices=["load", "save"]) p.add_argument("input") p.add_argument("output") p.add_argument("maxwidth", type=int, nargs='?', default=0) p.add_argument("maxheight", type=int, nargs='?', default=0) return p.parse_args() def main(): opts = getopts() if opts.mode == "load": if opts.maxwidth > 0 and opts.maxheight > 0: subprocess.run([ "heif-thumbnailer", "-s", "%sx%s" % (opts.maxwidth, opts.maxheight), opts.input, opts.output], check=True) else: subprocess.run([ "heif-convert", "-q", "100", opts.input, opts.output], check=True) else: # opts.mode == "save" subprocess.run(["heif-enc", "-o", opts.output, opts.input], check=True) subprocess.run(["exiftool", "-tagsFromFile", opts.input, "-overwrite_original", opts.output]) if __name__ == "__main__": main()
Here is another example, using ImageMagick to perform the conversion. In this case, we can handle multiple custom formats with the same script, simply by defining multiple
.txt files with the proper parameter.
For example, here is one for WebP (let's call it
webp.txt, and put it in
[ART ImageIO] Extension=webp ReadCommand=./magick-io.sh load WriteCommand=./magick-io.sh save Label=WebP (via ImageMagick)
And here is another one for EXR (let's call it
[ART ImageIO] Extension=exr ReadCommand=./magick-io.sh load WriteCommand=./magick-io.sh save Label=EXR (via ImageMagick)
In both cases, we call the same
#!/bin/bash mode=$1 shift if [ "$mode" = "load" ]; then # loading: convert from the input to a floating-point tiff file # resize if hints are given sz="" if [ "$4" != "" -a "$3" != "0" -a "$4" != "0" ]; then sz="-thumbnail $3x$4" fi magick convert "$1" $sz -colorspace sRGB -define quantum:format=floating-point -depth 32 -compress none "$2" test -f "$2" elif [ "$mode" = "save" ]; then # saving: convert from floating-point tiff to the output magick convert "$1" "$2" if [ -f "$2" ]; then # copy also the metadata with exiftool exiftool -tagsFromFile "$1" -overwrite_original "$2" fi test -f "$2" else # unknown operating mode, exit with error echo "Unknown operating mode \"$mode\"!" exit 1 fi
(NOTE: this assumes that you have a version of ImageMagick that is properly configured to handle WebP and EXR, of course.)