#! /usr/bin/env dash # shellcheck source=/dev/null SHELL_LIBRARY_VERSION="2.0.13" . %SHELL_LIBRARY_PATH # needed for help() and version # shellcheck disable=2034 AUTHORS="Soispha" # shellcheck disable=2034 YEARS="2023" # shellcheck disable=2034 VERSION="1.0.0" # NAME is from the wrapper # shellcheck disable=SC2269 NAME="$NAME" help() { cat <<EOF Scan images and turn them into a pdf. Usage: $NAME [OPTIONS] --name --device OPTIONS: --out-dir | -o [FILE] Path to place the generated pdf files (default: ./pdf). --name | -n NAME Name for the pdf files (e.g. <NAME>_1.pdf). --num-pages | -p NUM Number of pages to merge into one pdf (default: 1). --device | -d DEVICE Device used for scanning. --method | -m METHOD Method to use for scanning (default: ADF). --help | -h Display this help and exit. --version | -v Display version and copyright information and exit. ARGUMENTS: FILE := [[fd . --max-depth 3]] A name of a file to store, default is: ./pdf NAME | * := [[fd . --max-depth 3]] The basename of the generated files NUM | *([0-9]) := 0 | 1 | 2 | 3 | 4 Possible numbers of pages, can be more than 4 DEVICE := [[$(cat %DEVICE_FUNCTION)]] Possible scanner names METHOD := ADF | Flatbed The scanning method to use, not all scanners support both of these. The default is ADF EOF } scan_adf() { device="$1" sides_per_page="$2" method="ADF" for i in $(seq "$sides_per_page"); do do_until_success \ "scanimage --format=tiff --progress --source='$method' --device='$device' --batch=%d.tif --batch-increment='$sides_per_page' --batch-start='$i'" \ "warn 'Retrying scan, as we assume a network error!'" if [ "$sides_per_page" -ne 1 ]; then msg "Finished turn, please change side!" readp "Press enter to continue" noop fi done } process_images_adf() { tiff_temp_path="$1" output_directory="$2" name="$3" counter=0 pdf_counter=0 image_cache="$(mktmp)" while read -r scanned_image; do dbg "$scanned_image (scanned_image) at $counter (counter)" echo "$scanned_image" >>"$image_cache" : $((counter += 1)) if [ "$counter" = "$number_of_pages" ]; then dbg "$counter == $number_of_pages" counter=0 convert_images "$image_cache" "${name}_$pdf_counter" "$output_directory" : $((pdf_counter += 1)) printf "" >"$image_cache" fi done <"$(tmp_pipe fd . "$tiff_temp_path" "|" sort -V)" } scan_flatbed() { device="$1" number_of_pages"$2" method="Flatbed" for i in $(seq "$number_of_pages"); do do_until_success \ "scanimage --format=tiff --progress --source='$method' --device='$device' --output-file=$i.tiff" \ "warn 'Retrying scan, as we assume a network error!'" if [ "$number_of_pages" -ne 1 ]; then msg "Finished turn, please change side!" readp "Press enter to continue" noop fi done } process_images_flatbed() { tiff_temp_path="$1" output_directory="$2" name="$3" counter=0 image_cache="$(mktmp)" while read -r scanned_image; do echo "$scanned_image" >>"$image_cache" : $((counter += 1)) if [ "$counter" = "$number_of_pages" ]; then counter=0 convert_images "$image_cache" "$name" "$output_directory" printf "" >"$image_cache" fi done <"$(tmp_pipe fd . "$tiff_temp_path" "|" sort -V)" } convert_images() { image_cache="$1" pdf_name="$2" output_dir="$3" set -- while read -r image; do dbg "setting image: $image" set -- "$@" "$image" done <"$image_cache" while [ -e "$output_dir/${pdf_name}.pdf" ]; do pdf_name="${pdf_name}_$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 25)" done dbg "using pdf_name: $pdf_name" convert "$@" -compress jpeg -quality 100 "$output_dir/${pdf_name}.pdf" } scan() { number_of_pages="$1" device="$2" output_directory="$(readlink -f "$3")" name="$4" method="$5" [ -z "$number_of_pages" ] && die "Parameter 'number_of_pages' is not set!" [ -z "$device" ] && die "Parameter 'device' is not set!" [ -z "$output_directory" ] && die "Parameter 'output_directory' is not set!" [ -z "$name" ] && die "Parameter 'name' is not set!" [ -z "$method" ] && die "Parameter 'method' is not set!" tiff_temp_path="$(mktmp -d)" cd "$tiff_temp_path" || die "Bug" msg "Started scanning..." if [ "$method" = "Flatbed" ]; then scan_flatbed "$device" "$number_of_pages" else scan_adf "$device" "$number_of_pages" fi msg "Creating output directory..." mkdir "$output_directory" cd "$output_directory" || die "Bug" msg "Converting images to pdfs..." if [ "$method" = "Flatbed" ]; then process_images_flatbed "$tiff_temp_path" "$output_directory" "$name" else process_images_adf "$tiff_temp_path" "$output_directory" "$name" fi } for input in "$@"; do case "$input" in "--help" | "-h") help exit 0 ;; "--version" | "-v") version exit 0 ;; esac done number_of_pages="1" unset device output_directory="$(pwd)/pdf" unset name method="ADF" while [ "$#" -ne 0 ]; do case "$1" in "--help" | "-h") ;; "--version" | "-v") ;; "--out-dir" | "-o") shift 1 output_directory="$1" ;; "--name" | "-n") shift 1 name="$1" ;; "--num-pages" | "-p") shift 1 number_of_pages="$1" ;; "--device" | "-d") shift 1 device="$1" ;; "--method" | "-m") shift 1 method="$1" ;; *) die "Command line arg $1 does not exist. See --help for a list." ;; esac shift 1 done scan "$number_of_pages" "$device" "$output_directory" "$name" "$method"