Compare commits
No commits in common. "77f79038da9d1082f7fd069f9f81743f24135b78" and "60b980f4b7cf7b806b241d085bcd1166f2640eb6" have entirely different histories.
77f79038da
...
60b980f4b7
41
01-rename.sh
Executable file
41
01-rename.sh
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
##
|
||||||
|
# Main Program
|
||||||
|
|
||||||
|
dir=$(dirname "$(readlink -f "$0")")
|
||||||
|
origdir="$dir/orig"
|
||||||
|
indir="$dir/in"
|
||||||
|
|
||||||
|
if ! cd "$dir" ; then
|
||||||
|
echo "ERROR: Could not change to directory \"$dir\"; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! test -d "$origdir" ; then
|
||||||
|
echo "ERROR: Directory \"$origdir\" not found; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! mkdir -p "$indir" ; then
|
||||||
|
echo "ERROR: Could not create directory \"$indir\"; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! rm -f -- "$indir/"*.jpg ; then
|
||||||
|
echo "ERROR: Could not remove files in \"$indir\"; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
i=1
|
||||||
|
rv=0
|
||||||
|
|
||||||
|
while read -r jpg ; do
|
||||||
|
renamed=$(printf "%02d" "$i").jpg
|
||||||
|
|
||||||
|
if cp "$jpg" "$indir/$renamed" ; then
|
||||||
|
echo "INFO: Copied \"$jpg\" to \"$renamed\"." >&2
|
||||||
|
else
|
||||||
|
echo "WARNING: Could not copy \"$jpg\" to \"$renamed\"." >&2
|
||||||
|
rv=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
i=$((i+1))
|
||||||
|
done < <(ls --reverse --sort time -- "$origdir/"*.jpg)
|
||||||
|
|
||||||
|
exit "$rv"
|
||||||
|
fi
|
||||||
|
|
192
02-convert.sh
Executable file
192
02-convert.sh
Executable file
@ -0,0 +1,192 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
##
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
# Before morphology analysis, reduce image dimensions by this factor
|
||||||
|
simplify=2
|
||||||
|
|
||||||
|
# Morphology to apply to reduce content to main area
|
||||||
|
morphology="Open:6"
|
||||||
|
morphology_shape="Disk"
|
||||||
|
|
||||||
|
# Number of colors images are quantized to for component detection
|
||||||
|
colors=4
|
||||||
|
|
||||||
|
# Neighbors to evaluate when detecting connected components
|
||||||
|
connected_components=8
|
||||||
|
|
||||||
|
# Area treshold for connected components detection
|
||||||
|
area_treshold=1000
|
||||||
|
|
||||||
|
# Sigmoidal contrast adjustment used when trimming
|
||||||
|
sigmoidal_contrast_trim="30,30%"
|
||||||
|
|
||||||
|
# Sigmoidal contrast adjustment visible in result images
|
||||||
|
sigmoidal_contrast="45,50%"
|
||||||
|
|
||||||
|
# Number of colors result images are quantized to
|
||||||
|
posterize=6
|
||||||
|
|
||||||
|
# Keep intermediate images after processing (note that they will be removed in
|
||||||
|
# any case at the next run of this script)
|
||||||
|
keep_tmpfiles=true
|
||||||
|
|
||||||
|
##
|
||||||
|
# Main Program
|
||||||
|
|
||||||
|
dir="$(dirname "$(readlink -f "$0")")"
|
||||||
|
tmpdir="$dir/tmp"
|
||||||
|
indir="$dir/in"
|
||||||
|
comdir="$dir/com"
|
||||||
|
outdir="$dir/out"
|
||||||
|
resize_percent=$((100/simplify))
|
||||||
|
|
||||||
|
if ! cd "$dir" ; then
|
||||||
|
echo "ERROR: Could not change to directory \"$dir\"; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! mkdir -p "$comdir" "$outdir" "$tmpdir" ; then
|
||||||
|
echo "ERROR: Could not create working directories; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! rm -f -- "$comdir/"*.* ; then
|
||||||
|
echo "ERROR: Could not delete existing component files; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! rm -f -- "$tmpdir/"*.* ; then
|
||||||
|
echo "ERROR: Could not delete existing tempfiles; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! rm -f -- "$outdir/"*.* ; then
|
||||||
|
echo "ERROR: Could not delete existing results; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
rv=0
|
||||||
|
|
||||||
|
for jpg in "$indir/"*.jpg ; do
|
||||||
|
base=$(basename "$jpg" .jpg)
|
||||||
|
tmp1="$tmpdir/$base.tmp1.png"
|
||||||
|
tmp2="$tmpdir/$base.tmp2.png"
|
||||||
|
com="$tmpdir/$base.com.png"
|
||||||
|
trimmed="$tmpdir/$base.trimmed.png"
|
||||||
|
inf="$tmpdir/$base.txt"
|
||||||
|
out="$outdir/$base.png"
|
||||||
|
|
||||||
|
if ! convert \
|
||||||
|
"$jpg" \
|
||||||
|
-colorspace RGB \
|
||||||
|
-sigmoidal-contrast "$sigmoidal_contrast_trim" \
|
||||||
|
-resize "$resize_percent%" \
|
||||||
|
-colors "$colors" \
|
||||||
|
-morphology "$morphology" "$morphology_shape" \
|
||||||
|
"$tmp1"
|
||||||
|
then
|
||||||
|
echo "ERROR: Could not create test image \"$tmp1\"; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
draw=()
|
||||||
|
v=255
|
||||||
|
|
||||||
|
while read -r primitive ; do
|
||||||
|
draw+=("-fill" "rgb($v,$v,$v)" "-draw" "$primitive")
|
||||||
|
v=$((v-2))
|
||||||
|
done < <(
|
||||||
|
convert \
|
||||||
|
"$tmp1" \
|
||||||
|
-define connected-components:verbose=true \
|
||||||
|
-define connected-components:exclude-header=true \
|
||||||
|
-define connected-components:sort-order=increasing \
|
||||||
|
-define connected-components:area-threshold="$area_treshold" \
|
||||||
|
-virtual-pixel None \
|
||||||
|
-connected-components "$connected_components" \
|
||||||
|
-auto-level \
|
||||||
|
"$com" | \
|
||||||
|
perl -e '
|
||||||
|
while(<>){
|
||||||
|
chomp;
|
||||||
|
next unless /(\d+)x(\d+)\+(\d+)\+(\d+)/;
|
||||||
|
printf
|
||||||
|
STDERR
|
||||||
|
"DEBUG: component: $_\n";
|
||||||
|
printf
|
||||||
|
"rectangle %d,%d,%d,%d\n",
|
||||||
|
$1, $2, $1+$3, $2+$4;
|
||||||
|
}
|
||||||
|
|
||||||
|
' | \
|
||||||
|
sort | \
|
||||||
|
uniq
|
||||||
|
)
|
||||||
|
|
||||||
|
printf "DEBUG: connected components in \"%s\":" "$tmp1"
|
||||||
|
for d in "${draw[@]}" ; do
|
||||||
|
printf " \"%s\"" "$d"
|
||||||
|
done
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
|
if ! convert \
|
||||||
|
"$tmp1" \
|
||||||
|
-fill black -colorize 100 \
|
||||||
|
"${draw[@]}" \
|
||||||
|
"$tmp2"
|
||||||
|
then
|
||||||
|
echo "ERROR: Could not convert \"$tmp1\" to \"$tmp2\"; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
elif ! convert \
|
||||||
|
"$tmp2" \
|
||||||
|
-trim info: \
|
||||||
|
> "$inf"
|
||||||
|
then
|
||||||
|
echo "ERROR: Could not determine trim info from \"$tmp2\"; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if "$keep_tmpfiles" ; then
|
||||||
|
if ! convert \
|
||||||
|
"$tmp2" \
|
||||||
|
-trim \
|
||||||
|
"$trimmed"
|
||||||
|
then
|
||||||
|
echo "ERROR: Could not test trim \"$tmp2\"; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# upscale crop area from smaller temporary picture sizes
|
||||||
|
crop=$(simplify=$simplify perl -MEnv -e '
|
||||||
|
while(<>) {
|
||||||
|
chomp();
|
||||||
|
s/(\d+)/$1*${simplify}/eg;
|
||||||
|
/(\d+)x(\d+) \d+x\d+\+(\d+)\+(\d+)/ && do {
|
||||||
|
print $1."x".$2."+".$3."+".$4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' < "$inf")
|
||||||
|
|
||||||
|
if ! "$keep_tmpfiles" ; then
|
||||||
|
if ! rm -f -- "$tmp1" "$tmp2" "$trimmed" "$inf" ; then
|
||||||
|
echo "WARNING: Could not remove temporary files in \"$dir/tmp\"." >&2
|
||||||
|
rv=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Processing $base: crop=$crop ..."
|
||||||
|
|
||||||
|
if ! convert \
|
||||||
|
"$jpg" \
|
||||||
|
-crop "$crop" \
|
||||||
|
-sigmoidal-contrast "$sigmoidal_contrast" \
|
||||||
|
+dither -posterize "$posterize" \
|
||||||
|
"$out"
|
||||||
|
then
|
||||||
|
echo "ERROR: Could not process \"$jpg\"; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit "$rv"
|
||||||
|
fi
|
||||||
|
|
98
03-pdf.sh
Executable file
98
03-pdf.sh
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# shellcheck disable=SC2046
|
||||||
|
|
||||||
|
##
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
# Paper size of all pages
|
||||||
|
paper="a4paper"
|
||||||
|
|
||||||
|
# Offset in page where image should be placed
|
||||||
|
offset="1cm 3cm"
|
||||||
|
|
||||||
|
# Factor to scale image by before placing in page
|
||||||
|
scale=0.75
|
||||||
|
|
||||||
|
# Filename of complete result PDF
|
||||||
|
result="pdf/result.pdf"
|
||||||
|
|
||||||
|
##
|
||||||
|
# Main Program
|
||||||
|
|
||||||
|
dir="$(dirname "$(readlink -f "$0")")"
|
||||||
|
|
||||||
|
if ! cd "$dir" ; then
|
||||||
|
echo "ERROR: Could not change to directory \"$dir\"; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! mkdir -p pdf tmp ; then
|
||||||
|
echo "ERROR: Could not create \"$dir/{pdf,tmp}\"; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
elif ! rm -f -- "pdf/"*.* ; then
|
||||||
|
echo "ERROR: Could not delete existing results in \"$dir/pdf\"; aborted." >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
rv=0
|
||||||
|
|
||||||
|
for png in "out/"*.png ; do
|
||||||
|
echo "INFO: Processing \"$png\" ..." >&2
|
||||||
|
|
||||||
|
read -r width height < <(
|
||||||
|
identify -verbose "$png" | \
|
||||||
|
perl -ne '/Geometry: (\d+)x(\d+)/ && print "$1 $2"'
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ -z $width ]] || [[ -z $height ]] ; then
|
||||||
|
echo "ERROR: Could not identify width or height of \"$png\"; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
elif [[ $width -gt $height ]] ; then
|
||||||
|
backdrop=template/a4paper/landscape.pdf
|
||||||
|
jam_landscape=--landscape
|
||||||
|
else
|
||||||
|
backdrop=template/a4paper/portrait.pdf
|
||||||
|
jam_landscape=--no-landscape
|
||||||
|
fi
|
||||||
|
|
||||||
|
base=$(basename "$png" .png)
|
||||||
|
pdf=tmp/$base.pdf
|
||||||
|
jammed=tmp/$base-pdfjam.pdf
|
||||||
|
backdropped=tmp/$base.backdropped.pdf
|
||||||
|
|
||||||
|
if ! convert "$png" "$pdf" ; then
|
||||||
|
echo "ERROR: Could not convert \"$png\" to PDF; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
elif ! pdfjam \
|
||||||
|
--quiet \
|
||||||
|
--outfile tmp \
|
||||||
|
--paper "$paper" \
|
||||||
|
"$jam_landscape" \
|
||||||
|
--scale "$scale" \
|
||||||
|
--offset "$offset" \
|
||||||
|
"$pdf"
|
||||||
|
then
|
||||||
|
echo "ERROR: Could not align \"$pdf\"; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
elif ! pdftk \
|
||||||
|
"$jammed" \
|
||||||
|
stamp "$backdrop" \
|
||||||
|
output "$backdropped"
|
||||||
|
then
|
||||||
|
echo "ERROR: Could not watermark \"$pdf\"; skipped." >&2
|
||||||
|
rv=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! pdftk $(ls -- "tmp/"*.backdropped.pdf) cat output "$result" ; then
|
||||||
|
echo "ERROR: Could not concatenate \"$result\"." >&2
|
||||||
|
rv=1
|
||||||
|
elif ! rm -f -- "tmp/"*.pdf ; then
|
||||||
|
echo "ERROR: Could not remove tempfiles in \"$dir/tmp\"." >&2
|
||||||
|
rv=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$rv"
|
||||||
|
fi
|
||||||
|
|
24
Makefile
24
Makefile
@ -1,24 +0,0 @@
|
|||||||
NAME=photos2pdf
|
|
||||||
DESTDIR=
|
|
||||||
PREFIX=/usr
|
|
||||||
INSTALL=install
|
|
||||||
|
|
||||||
BINDIR=$(PREFIX)/bin
|
|
||||||
LIBDIR=/var/lib/$(NAME)
|
|
||||||
TEMPLATEDIR=$(LIBDIR)/template
|
|
||||||
|
|
||||||
.PHONY: all install-bin install-template install
|
|
||||||
|
|
||||||
all:
|
|
||||||
@echo "Use \"sudo $(MAKE) install\" to install $(NAME)"
|
|
||||||
|
|
||||||
install-bin:
|
|
||||||
$(INSTALL) -d -m 0755 "$(BINDIR)"
|
|
||||||
$(INSTALL) -m 0755 "$(NAME)" "$(BINDIR)/$(NAME)"
|
|
||||||
|
|
||||||
install-template:
|
|
||||||
$(INSTALL) -d -m 0755 "$(DESTDIR)$(LIBDIR)"
|
|
||||||
$(INSTALL) -d -m 0755 "$(DESTDIR)$(TEMPLATEDIR)"
|
|
||||||
tar cf - -C template --exclude "*.svg" . | (cd "$(DESTDIR)$(TEMPLATEDIR)" && tar xf -)
|
|
||||||
|
|
||||||
install: install-bin install-template
|
|
433
photos2pdf
433
photos2pdf
@ -1,433 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
##
|
|
||||||
# Configuration
|
|
||||||
|
|
||||||
# Before morphology analysis, reduce image dimensions by this factor
|
|
||||||
simplify=2
|
|
||||||
|
|
||||||
# Morphology to apply to reduce content to main area
|
|
||||||
morphology="Open:6"
|
|
||||||
morphology_shape="Disk"
|
|
||||||
|
|
||||||
# Number of colors images are quantized to for component detection
|
|
||||||
colors=4
|
|
||||||
|
|
||||||
# Neighbors to evaluate when detecting connected components
|
|
||||||
connected_components=8
|
|
||||||
|
|
||||||
# Area treshold for connected components detection
|
|
||||||
area_treshold=1000
|
|
||||||
|
|
||||||
# Sigmoidal contrast adjustment used when trimming
|
|
||||||
sigmoidal_contrast_trim="30,30%"
|
|
||||||
|
|
||||||
# Sigmoidal contrast adjustment visible in result images
|
|
||||||
sigmoidal_contrast="45,50%"
|
|
||||||
|
|
||||||
# Number of colors result images are quantized to
|
|
||||||
posterize=6
|
|
||||||
|
|
||||||
# Keep intermediate images after processing
|
|
||||||
keep_tmpfiles=true
|
|
||||||
|
|
||||||
# Paper size of all pages
|
|
||||||
paper="a4paper"
|
|
||||||
|
|
||||||
# Offset in page where image should be placed
|
|
||||||
offset="1cm 3cm"
|
|
||||||
|
|
||||||
# Factor to scale image by before placing in page
|
|
||||||
scale=0.75
|
|
||||||
|
|
||||||
# PDF backdrop template directory
|
|
||||||
templatedir=/var/lib/photos2pdf/template
|
|
||||||
|
|
||||||
# Filename of complete result PDF
|
|
||||||
result_filename="result.pdf"
|
|
||||||
|
|
||||||
# Directory of original files to process (initially unset)
|
|
||||||
dir=
|
|
||||||
|
|
||||||
##
|
|
||||||
# Functions
|
|
||||||
|
|
||||||
log() {
|
|
||||||
level=$1
|
|
||||||
msg=$2
|
|
||||||
|
|
||||||
printf "%s: %s\n" "$level" "$msg" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
error() {
|
|
||||||
log ERROR "$1"
|
|
||||||
|
|
||||||
exit "${2:-1}"
|
|
||||||
}
|
|
||||||
|
|
||||||
warning() {
|
|
||||||
log WARNING "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
info() {
|
|
||||||
log INFO "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_help() {
|
|
||||||
cat << 'EOF'
|
|
||||||
photos2pdf
|
|
||||||
==========
|
|
||||||
|
|
||||||
Description
|
|
||||||
-----------
|
|
||||||
Trim and brighten JPGs, produce PDF containing one photo per page.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
```shell
|
|
||||||
photos2pdf [OPTION ...] DIR
|
|
||||||
```
|
|
||||||
|
|
||||||
Arguments
|
|
||||||
---------
|
|
||||||
* `DIR`: Directory containing the original photos.
|
|
||||||
|
|
||||||
Options
|
|
||||||
-------
|
|
||||||
* `--simplify INT`: Before morphology analysis, reduce
|
|
||||||
image dimensions by this factor
|
|
||||||
(default: 2).
|
|
||||||
* `--morphology STRING`: Morphology to apply for trimming
|
|
||||||
(default "Open:6").
|
|
||||||
* `--morphology-shape STRING`: Shape of morphology to apply for
|
|
||||||
trimming (default: "Disk").
|
|
||||||
* `--colors INT`: Number of colors images are quantized
|
|
||||||
to for component detection (default: 4).
|
|
||||||
* `--connected-components INT`: Neighbors to evaluate when detecting
|
|
||||||
connected components (default: 8).
|
|
||||||
* `--area_treshold INT`: Area treshold for connected components
|
|
||||||
detection (default: 1000).
|
|
||||||
* `--sigmoidal-contrast-trim STRING`: Sigmoidal contrast adjustment
|
|
||||||
used when trimming (default: "30,30%").
|
|
||||||
* `--sigmoidal-contrast STRING`: Sigmoidal contrast adjustment visible
|
|
||||||
in result images (default: "45,50%").
|
|
||||||
* `--posterize INT`: Number of colors result images are
|
|
||||||
quantized to (default: 6).
|
|
||||||
* `--keep-tmpfiles true|false`: Keep temporary files (default: false).
|
|
||||||
* `--paper STRING`: PDF page size (default: "a4paper").
|
|
||||||
* `--offset STRING`: Offset in page where image should be
|
|
||||||
placed (default: "1cm 3cm").
|
|
||||||
* `--scale FLOAT`: Factor to scale image by before placing
|
|
||||||
in page (default: 0.75).
|
|
||||||
* `--templatedir STRING`: PDF backdrop directory (default:
|
|
||||||
"/var/lib/photos2pdf/template").
|
|
||||||
* `--result-filename STRING`: Filename of complete result PDF
|
|
||||||
(default: "result.pdf").
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
##
|
|
||||||
# Arguments
|
|
||||||
|
|
||||||
i=1
|
|
||||||
options_done=false
|
|
||||||
|
|
||||||
while [[ $i -le $# ]] ; do
|
|
||||||
arg=$(eval "echo \$$i")
|
|
||||||
|
|
||||||
if ! "$options_done" ; then
|
|
||||||
case "$arg" in
|
|
||||||
-h|--help)
|
|
||||||
print_help
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
--simplify| \
|
|
||||||
--morphology| \
|
|
||||||
--morphology-shape| \
|
|
||||||
--colors| \
|
|
||||||
--connected-components| \
|
|
||||||
--area-treshold| \
|
|
||||||
--sigmoidal-contrast-trim| \
|
|
||||||
--sigmoidal-contrast| \
|
|
||||||
--posterize| \
|
|
||||||
--keep-tmpfiles| \
|
|
||||||
--paper| \
|
|
||||||
--offset| \
|
|
||||||
--scale| \
|
|
||||||
--templatedir| \
|
|
||||||
--result-filename)
|
|
||||||
var=$(echo "$arg" | sed -e 's|^\-\-||;s|\-|_|g;')
|
|
||||||
i=$((i+1))
|
|
||||||
arg=$(eval "echo \$$i")
|
|
||||||
eval "$var=\"$arg\""
|
|
||||||
i=$((i+1))
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
--)
|
|
||||||
options_done=true
|
|
||||||
i=$((i+1))
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
-*)
|
|
||||||
error "Unknown option \"$arg\"; aborted."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$arg" in
|
|
||||||
*)
|
|
||||||
[[ -n $dir ]] && error "Only one input directory can be specified; aborted."
|
|
||||||
dir=$arg
|
|
||||||
i=$((i+1))
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
[[ -z $dir ]] && error "Usage: $0 [OPTION ..] DIR"
|
|
||||||
|
|
||||||
##
|
|
||||||
# Main Program
|
|
||||||
|
|
||||||
job_id=$(printf "%s" "$origdir" | sha256sum | cut -d" " -f1)
|
|
||||||
|
|
||||||
origdir=$(readlink -f "$dir")
|
|
||||||
|
|
||||||
[[ -d $origdir ]] || error "Directory $dir not found; aborted."
|
|
||||||
|
|
||||||
if [[ -n $TMP ]] ; then
|
|
||||||
tmp_base=$TMP/photos2pdf/$job_id
|
|
||||||
elif [[ -n $XDG_RUNTIME_DIR ]] ; then
|
|
||||||
tmp_base=$XDG_RUNTIME_DIR/photos2pdf/$job_id
|
|
||||||
else
|
|
||||||
tmp_base=/tmp/photos2pdf/$job_id
|
|
||||||
fi
|
|
||||||
|
|
||||||
indir="$tmp_base/in"
|
|
||||||
tmpdir="$tmp_base/tmp"
|
|
||||||
outdir="$tmp_base/out"
|
|
||||||
pdfdir="$tmp_base/pdf"
|
|
||||||
|
|
||||||
if ! test -d "$origdir" ; then
|
|
||||||
error "Directory \"$origdir\" not found; aborted."
|
|
||||||
elif ! mkdir -p "$indir" "$outdir" "$pdfdir" "$tmpdir" ; then
|
|
||||||
error "Could not create working directories; aborted."
|
|
||||||
elif ! rm -f -- "$indir/"*.* ; then
|
|
||||||
error "Could not delete existing input files; aborted."
|
|
||||||
elif ! rm -f -- "$tmpdir/"*.* ; then
|
|
||||||
error "Could not delete existing tempfiles; aborted."
|
|
||||||
elif ! rm -f -- "$outdir/"*.* ; then
|
|
||||||
error "Could not delete existing results; aborted."
|
|
||||||
elif ! rm -f -- "$pdfdir/"*.* ; then
|
|
||||||
error "Could not delete existing PDFs; aborted."
|
|
||||||
fi
|
|
||||||
|
|
||||||
resize_percent=$((100/simplify))
|
|
||||||
|
|
||||||
i=1
|
|
||||||
rv=0
|
|
||||||
|
|
||||||
while read -r jpg ; do
|
|
||||||
renamed=$(printf "%02d" "$i").jpg
|
|
||||||
|
|
||||||
if cp "$jpg" "$indir/$renamed" ; then
|
|
||||||
info "Copied \"$jpg\" to \"$renamed\"."
|
|
||||||
else
|
|
||||||
warning "Could not copy \"$jpg\" to \"$renamed\"."
|
|
||||||
rv=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
i=$((i+1))
|
|
||||||
done < <(ls --reverse --sort time -- "$origdir/"*.jpg)
|
|
||||||
|
|
||||||
if [[ $rv -ne 0 ]] ; then
|
|
||||||
error "One or more errors during input file naming; aborted." "$rv"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for jpg in "$indir/"*.jpg ; do
|
|
||||||
base=$(basename "$jpg" .jpg)
|
|
||||||
tmp1="$tmpdir/$base.tmp1.png"
|
|
||||||
tmp2="$tmpdir/$base.tmp2.png"
|
|
||||||
com="$tmpdir/$base.com.png"
|
|
||||||
trimmed="$tmpdir/$base.trimmed.png"
|
|
||||||
inf="$tmpdir/$base.txt"
|
|
||||||
out="$outdir/$base.png"
|
|
||||||
|
|
||||||
if ! convert \
|
|
||||||
"$jpg" \
|
|
||||||
-colorspace RGB \
|
|
||||||
-sigmoidal-contrast "$sigmoidal_contrast_trim" \
|
|
||||||
-resize "$resize_percent%" \
|
|
||||||
-colors "$colors" \
|
|
||||||
-morphology "$morphology" "$morphology_shape" \
|
|
||||||
"$tmp1"
|
|
||||||
then
|
|
||||||
warning "Could not create test image \"$tmp1\"; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
draw=()
|
|
||||||
v=255
|
|
||||||
|
|
||||||
while read -r primitive ; do
|
|
||||||
draw+=("-fill" "rgb($v,$v,$v)" "-draw" "$primitive")
|
|
||||||
v=$((v-2))
|
|
||||||
done < <(
|
|
||||||
convert \
|
|
||||||
"$tmp1" \
|
|
||||||
-define connected-components:verbose=true \
|
|
||||||
-define connected-components:exclude-header=true \
|
|
||||||
-define connected-components:sort-order=increasing \
|
|
||||||
-define connected-components:mean-color=true \
|
|
||||||
-define connected-components:area-threshold="$area_treshold" \
|
|
||||||
-virtual-pixel None \
|
|
||||||
-connected-components "$connected_components" \
|
|
||||||
-auto-level \
|
|
||||||
"$com" | \
|
|
||||||
perl -e '
|
|
||||||
while(<>){
|
|
||||||
chomp;
|
|
||||||
next unless /(\d+)x(\d+)\+(\d+)\+(\d+)/;
|
|
||||||
printf
|
|
||||||
"rectangle %d,%d,%d,%d\n",
|
|
||||||
$1, $2, $1+$3, $2+$4;
|
|
||||||
}
|
|
||||||
|
|
||||||
' | \
|
|
||||||
sort | \
|
|
||||||
uniq
|
|
||||||
)
|
|
||||||
|
|
||||||
if ! convert \
|
|
||||||
"$tmp1" \
|
|
||||||
-fill black -colorize 100 \
|
|
||||||
"${draw[@]}" \
|
|
||||||
"$tmp2"
|
|
||||||
then
|
|
||||||
warning "Could not convert \"$tmp1\" to \"$tmp2\"; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
elif ! convert \
|
|
||||||
"$tmp2" \
|
|
||||||
-trim info: \
|
|
||||||
> "$inf"
|
|
||||||
then
|
|
||||||
warning "Could not determine trim info from \"$tmp2\"; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
if "$keep_tmpfiles" ; then
|
|
||||||
if ! convert \
|
|
||||||
"$tmp2" \
|
|
||||||
-trim \
|
|
||||||
"$trimmed"
|
|
||||||
then
|
|
||||||
warning "Could not test trim \"$tmp2\"; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# upscale crop area from smaller temporary picture sizes
|
|
||||||
crop=$(simplify=$simplify perl -MEnv -e '
|
|
||||||
while(<>) {
|
|
||||||
chomp();
|
|
||||||
s/(\d+)/$1*${simplify}/eg;
|
|
||||||
/(\d+)x(\d+) \d+x\d+\+(\d+)\+(\d+)/ && do {
|
|
||||||
print $1."x".$2."+".$3."+".$4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
' < "$inf")
|
|
||||||
|
|
||||||
info "Processing $base: crop=$crop ..."
|
|
||||||
|
|
||||||
if ! convert \
|
|
||||||
"$jpg" \
|
|
||||||
-crop "$crop" \
|
|
||||||
-sigmoidal-contrast "$sigmoidal_contrast" \
|
|
||||||
+dither -posterize "$posterize" \
|
|
||||||
"$out"
|
|
||||||
then
|
|
||||||
warning "Could not process \"$jpg\"; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ $rv -ne 0 ]] ; then
|
|
||||||
error "One or more errors during image conversion; aborted." "$rv"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for png in "out/"*.png ; do
|
|
||||||
info "Processing \"$png\" ..."
|
|
||||||
|
|
||||||
read -r width height < <(
|
|
||||||
identify -verbose "$png" | \
|
|
||||||
perl -ne '/Geometry: (\d+)x(\d+)/ && print "$1 $2"'
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ -z $width ]] || [[ -z $height ]] ; then
|
|
||||||
warning "Could not identify width or height of \"$png\"; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
elif [[ $width -gt $height ]] ; then
|
|
||||||
backdrop="$templatedir/a4paper/landscape.pdf"
|
|
||||||
jam_landscape=--landscape
|
|
||||||
else
|
|
||||||
backdrop="$templatedir/a4paper/portrait.pdf"
|
|
||||||
jam_landscape=--no-landscape
|
|
||||||
fi
|
|
||||||
|
|
||||||
base=$(basename "$png" .png)
|
|
||||||
pdf="$tmpdir/$base.pdf"
|
|
||||||
jammed="$tmpdir/$base-pdfjam.pdf"
|
|
||||||
backdropped="$tmpdir/$base.backdropped.pdf"
|
|
||||||
|
|
||||||
if ! convert "$png" "$pdf" ; then
|
|
||||||
warning "Could not convert \"$png\" to PDF; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
elif ! pdfjam \
|
|
||||||
--quiet \
|
|
||||||
--outfile "$tmpdir" \
|
|
||||||
--paper "$paper" \
|
|
||||||
"$jam_landscape" \
|
|
||||||
--scale "$scale" \
|
|
||||||
--offset "$offset" \
|
|
||||||
"$pdf"
|
|
||||||
then
|
|
||||||
warning "Could not align \"$pdf\"; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
elif ! pdftk \
|
|
||||||
"$jammed" \
|
|
||||||
stamp "$backdrop" \
|
|
||||||
output "$backdropped"
|
|
||||||
then
|
|
||||||
warning "Could not watermark \"$pdf\"; skipped."
|
|
||||||
rv=1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
input=()
|
|
||||||
|
|
||||||
while read -r pdf ; do
|
|
||||||
input+=("$pdf")
|
|
||||||
done < <(ls -- "$tmpdir/"*.backdropped.pdf)
|
|
||||||
|
|
||||||
if ! pdftk "${input[@]}" cat output "$pdfdir/$result_filename" ; then
|
|
||||||
warning "Could not concatenate \"$result_filename\"."
|
|
||||||
rv=1
|
|
||||||
elif ! "$keep_tmpfiles" ; then
|
|
||||||
if ! rm -f -- "$tmp_base" ; then
|
|
||||||
warning "Could not remove temporary files."
|
|
||||||
rv=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $rv -ne 0 ]] ; then
|
|
||||||
error "One or more errors; aborted." "$rv"
|
|
||||||
fi
|
|
||||||
|
|
1
template/.gitignore
vendored
Normal file
1
template/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*/*.svg
|
@ -1,131 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
width="210mm"
|
|
||||||
height="297mm"
|
|
||||||
viewBox="0 0 210 297"
|
|
||||||
version="1.1"
|
|
||||||
id="svg8">
|
|
||||||
<defs
|
|
||||||
id="defs2">
|
|
||||||
<rect
|
|
||||||
x="83.672132"
|
|
||||||
y="21.389596"
|
|
||||||
width="119.91071"
|
|
||||||
height="12.019084"
|
|
||||||
id="rect877" />
|
|
||||||
<rect
|
|
||||||
x="5.0111079"
|
|
||||||
y="273.95127"
|
|
||||||
width="164.4764"
|
|
||||||
height="14.510465"
|
|
||||||
id="rect869" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient861">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#b1a923;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop857" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#52b123;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop859" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
xlink:href="#linearGradient861"
|
|
||||||
id="linearGradient863"
|
|
||||||
x1="24.01818"
|
|
||||||
y1="43.293032"
|
|
||||||
x2="85.151292"
|
|
||||||
y2="43.293032"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.50515534,0,0,0.50515534,8.2790422,6.5653451)" />
|
|
||||||
</defs>
|
|
||||||
<metadata
|
|
||||||
id="metadata5">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
id="layer1">
|
|
||||||
<g
|
|
||||||
id="g835"
|
|
||||||
style="fill:#ffffff;stroke:#000000;stroke-width:3.26929;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:0.453543;paint-order:fill markers stroke">
|
|
||||||
<path
|
|
||||||
id="path847"
|
|
||||||
style="fill:#e9e9ff;fill-rule:evenodd;stroke:none;stroke-width:1.6515;stroke-linejoin:round"
|
|
||||||
d="m 29.831629,24.847969 24.766042,-6.466738 v 15.027448 l -24.766042,0.0046 z"
|
|
||||||
points="54.597671,18.381231 54.597671,33.408679 29.831629,33.413292 29.831629,24.847969 " />
|
|
||||||
<path
|
|
||||||
id="path837"
|
|
||||||
style="fill:#353564;fill-rule:evenodd;stroke:none;stroke-width:1.6515;stroke-linejoin:round"
|
|
||||||
d="m 17.026761,23.341926 v 10.070292 l 12.804868,0.0011 v -8.565323 z"
|
|
||||||
points="17.026761,33.412218 29.831629,33.413292 29.831629,24.847969 17.026761,23.341926 " />
|
|
||||||
<path
|
|
||||||
id="path839"
|
|
||||||
style="fill:#4d4d9f;fill-rule:evenodd;stroke:none;stroke-width:1.6515;stroke-linejoin:round"
|
|
||||||
d="m 17.026761,23.341926 20.473451,-10.30488 17.097459,5.344185 -24.766042,6.466738 z"
|
|
||||||
points="37.500212,13.037046 54.597671,18.381231 29.831629,24.847969 17.026761,23.341926 " />
|
|
||||||
<path
|
|
||||||
id="path845"
|
|
||||||
style="fill:#afafde;fill-rule:evenodd;stroke:none;stroke-width:1.6515;stroke-linejoin:round"
|
|
||||||
d="m 17.026761,33.412218 20.473451,-0.0074 17.097459,0.0038 -24.766042,0.0046 z"
|
|
||||||
points="37.500212,33.404866 54.597671,33.408679 29.831629,33.413292 17.026761,33.412218 " />
|
|
||||||
<path
|
|
||||||
id="path843"
|
|
||||||
style="fill:#d7d7ff;fill-rule:evenodd;stroke:none;stroke-width:1.6515;stroke-linejoin:round"
|
|
||||||
d="m 37.500212,13.037046 v 20.36782 l 17.097459,0.0038 V 18.381231 Z"
|
|
||||||
points="37.500212,33.404866 54.597671,33.408679 54.597671,18.381231 37.500212,13.037046 " />
|
|
||||||
<path
|
|
||||||
id="path841"
|
|
||||||
style="fill:#8686bf;fill-rule:evenodd;stroke:none;stroke-width:1.6515;stroke-linejoin:round"
|
|
||||||
d="m 17.026761,23.341926 20.473451,-10.30488 v 20.36782 l -20.473451,0.0074 z"
|
|
||||||
points="37.500212,13.037046 37.500212,33.404866 17.026761,33.412218 17.026761,23.341926 " />
|
|
||||||
</g>
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.56253px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient863);fill-opacity:1;stroke-width:0.264583"
|
|
||||||
x="19.99313"
|
|
||||||
y="27.244293"
|
|
||||||
id="text851"
|
|
||||||
transform="scale(1.0214137,0.97903519)"><tspan
|
|
||||||
id="tspan849"
|
|
||||||
x="19.99313"
|
|
||||||
y="27.244293"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.56253px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:url(#linearGradient863);fill-opacity:1;stroke-width:0.264583">ENTERPRISE</tspan><tspan
|
|
||||||
x="19.99313"
|
|
||||||
y="32.947456"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.56253px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:url(#linearGradient863);fill-opacity:1;stroke-width:0.264583"
|
|
||||||
id="tspan853">LOGO</tspan></text>
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
id="text867"
|
|
||||||
style="font-size:4.93889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect869);"
|
|
||||||
transform="translate(11.600124,-0.57554953)"><tspan
|
|
||||||
x="5.0117188"
|
|
||||||
y="278.32093"><tspan>Copyleft 2023 tk-sls.de
|
|
||||||
</tspan></tspan><tspan
|
|
||||||
x="5.0117188"
|
|
||||||
y="284.49455"><tspan>CC-BY-SA Attribution-ShareAlike 3.0 Unported</tspan></tspan></text>
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
id="text875"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.87778px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect877);"
|
|
||||||
transform="translate(12.639904,2.7987242)"><tspan
|
|
||||||
x="83.671875"
|
|
||||||
y="30.128192"><tspan
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.87778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">Generic Title Text</tspan></tspan></text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 6.5 KiB |
Loading…
Reference in New Issue
Block a user