Use Canon CanoScan 9000F Mark II to digitize slides and prints on Linux

Some time ago I collected some boxes of slides from my parents and parents-in-law. The pictures were taken in the 70s and 80s and it would be a shame to disregard them, so I set out to create a workflow to digitize them. I bought a CanoScan 9000F Mark II because the Linux support is good – this piece of technology can scan with 4800 dpi which should be sufficient even for advanced use. I confined myself to 1200 dpi which gave me pictures of 1650 x 1080 pixels. The process took 35 seconds for 4 pictures (scanned in one go).

Here’s the script I wrote for scanning slides – it uses scanimage (from package libsane) and convert (from package imagemagick):

#!/bin/bash

if [ -z "$1" ]; then
   echo "no valid name for the slide magazine given"
   exit 1
fi

RESOLUTION=1200
echo ""
TARGETDIR="/home/user/Pictures/slide/$1"
mkdir -p "$TARGETDIR"
echo "target directory for this slide magazine: $TARGETDIR"
TEMPDIR=$(mktemp -d -t diascan.XXXXXX)
echo "temporary directory for this slide magazine: $TEMPDIR"

echo "IS THE GLASS CLEAN?"

while true; do
	echo ""
	echo "to scan the next 4 slides: press enter"
	echo "OR enter slide count (1-4), then press enter"
	echo "OR if the magazine is done: press Ctrl-C"
	read imagecount
	
	# depending on $imagecount smaller scans and different partitioning
	if [ "$imagecount" == "1" ]; then
		scanimage -d pixma:04A9190D --source 'Transparency Unit' --resolution $RESOLUTION --format=tiff --mode Color \
			-l 90 -t 32 -x 38 -y 36 \
        	>$TEMPDIR/original_0.tiff
	elif [ "$imagecount" == "2" ]; then
		scanimage -d pixma:04A9190D --source 'Transparency Unit' --resolution $RESOLUTION --format=tiff --mode Color \
			-l 90 -t 32 -x 38 -y 92 \
        	| convert tiff:- -crop 1x2-0-850@\! +repage +adjoin $TEMPDIR/original_%d.tiff
	elif [ "$imagecount" == "3" ]; then
		scanimage -d pixma:04A9190D --source 'Transparency Unit' --resolution $RESOLUTION --format=tiff --mode Color \
			-l 90 -t 32 -x 38 -y 148 \
        	| convert tiff:- -crop 1x3-0-850@\! +repage +adjoin $TEMPDIR/original_%d.tiff
	else
		scanimage -d pixma:04A9190D --source 'Transparency Unit' --resolution $RESOLUTION --format=tiff --mode Color \
			-l 90 -t 32 -x 38 -y 205 \
        	| convert tiff:- -crop 1x4-0-850@\! +repage +adjoin $TEMPDIR/original_%d.tiff
    fi
    
    ls $TEMPDIR/original_*.tiff | while read file; do
    	newfile=$(echo $file | sed -e 's#original_#edited_#' -e 's#tiff$#jpg#')
    	convert "$file" -contrast -fuzz 3% -trim -gamma 3 -modulate 100,250,100 -quality 100 "$newfile"
    done

    # move images from $TEMPDIR/edited_*.jpg and $TEMPDIR/original_*.jpg to $TARGETDIR (with reasonable naming)
    i=$(ls "$TARGETDIR"/original_*.tiff 2>/dev/null | tail -n 1 | sed -e 's#^.*original_0\?0\?##' -e 's#.tiff$##')
    if [ "$i" == "" ]; then
    	i=0
    else
    	((i++))
    fi
    
    ls $TEMPDIR/original_*.tiff | while read originalfile; do
    	neworiginalfile=$(printf "$TARGETDIR/original_%03d.tiff" $i)
    	mv "$originalfile" "$neworiginalfile"
    	editedfile=$(echo $originalfile | sed -e 's#original_#edited_#' -e 's#tiff$#jpg#')
    	neweditedfile=$(printf "$TARGETDIR/edited_%03d.jpg" $i)
    	mv "$editedfile" "$neweditedfile"
    	((i++))
    done
done

I called the script with the name of the directory for the scans, put the slide onto the scanner and pressed enter as many times as needed. The images ended up in proper order in the denoted directory.

Some of the tricks I used were inspired by https://www.rigacci.org/wiki/doku.php/doc/appunti/hardware/canoscan_9000f_mark_ii – thanks Niccolo!


Bonus: After all the slides, I scanned some paper prints I still had lying around from the past. I modified the script as follows:

#!/bin/bash

if [ -z "$1" ]; then
   echo "no valid directory name given"
   exit 1
fi

RESOLUTION=600
echo ""
TARGETDIR="/home/user/Pictures/paper/$1"
mkdir -p "$TARGETDIR"
echo "target directory: $TARGETDIR"
TEMPDIR=$(mktemp -d -t fotoscan.XXXXXX)
echo "temporary directory: $TEMPDIR"

while true; do
	echo ""
	echo "to scan the next paper print: press enter"
	echo "OR if done: press Ctrl-C"
	read
	
	scanimage -d pixma:04A9190D --source 'Flatbed' --resolution $RESOLUTION \
	--format=tiff --mode Color -l 2 -t 1 -x 151 -y 152 \
	| convert tiff:- -bordercolor white -border 1x1 -fuzz 30% -trim +repage -quality 100 "$TEMPDIR/scan.jpg"

    # move images from $TEMPDIR/scan*.jpg to $TARGETDIR (with reasonable naming)
    i=$(ls "$TARGETDIR"/image-*.jpg 2>/dev/null | tail -n 1 | sed -e 's#^.*image-0\?0\?0\?##' -e 's#.jpg$##')
    if [ "$i" == "" ]; then
    	i=0
    else
    	((i++))
    fi
    
    ls $TEMPDIR/scan*.jpg | while read file; do
    	newfile=$(printf "$TARGETDIR/image-%04d.jpg" $i)
    	mv "$file" "$newfile"
    	((i++))
    done
done

As before, I just had to change the picture and press enter. ImageMagick’s convert did the cropping automatically (as with the slides).