#!/bin/sh
#
# Copyright (C) 2022 by Friedemann Bartels
#
# This file may be distributed and/or modified under the
# conditions of the LaTeX Project Public License, either
# version 1.3c of this license or (at your option) any later
# version. The latest version of this license is in:
#
# http://www.latex-project.org/lppl.txt
#
# and version 1.3c or later is part of all distributions of
# LaTeX version 2008/05/04 or later.
#
version=1.0.2
_convert() {
turbo=$1
filename=$2
filenamecache=$3
fileextcache=$4
originalwidthsp=$5
originalheightsp=$6
originalcropleftsp=$7
originalcroprightsp=$8
originalcroptopsp=$9
originalcropbottomsp=${10}
density=${11}
displaywidth=${12}
displayheight=${13}
resizethreshold=${14}
unsharp=${15}
quality="${16}"
mkdir -p cache/"$filenamecache"
originalwidth=$( magick identify -ping -format %w "$filename" )
originalheight=$( magick identify -ping -format %h "$filename" )
width=$(( (10 * originalwidth * (originalwidthsp - originalcropleftsp - originalcroprightsp) / originalwidthsp + 5) / 10 ))
height=$(( (10 * originalheight * (originalheightsp - originalcroptopsp - originalcropbottomsp) / originalheightsp + 5) / 10 ))
cropleft=$(( (10 * originalwidth * originalcropleftsp / originalwidthsp + 5) / 10 ))
croptop=$(( (10 * originalheight * originalcroptopsp / originalheightsp + 5) / 10 ))
resizewidth=$(( (10 * displaywidth * 100 * density / 473628672 + 5) / 10 ))
if [ $(( resizewidth * resizethreshold / 100 )) -gt $width ]; then
resizewidth=$width
resizeheight=$height
else
resizeheight=$(( resizewidth * height / width + 1 ))
fi
x="x"
if [ $turbo = 1 ]; then
export MAGICK_THREAD_LIMIT=1
fi
if [ "$quality" != "" ]; then
quality="-quality $quality"
fi
if [ "$unsharp" != "" ]; then
unsharp="-unsharp $unsharp"
fi
magick "$filename" -crop $width$x$height+$cropleft+$croptop -resize $resizewidth$x$resizeheight $unsharp $quality "cache/$filenamecache/.g$fileextcache"
mv "cache/$filenamecache/.g$fileextcache" "cache/$filenamecache/g$fileextcache"
}
_startbatchprocess() {
success=0
for file in cache/*; do
if [ -f "$file" ]; then
success=1
name=$( basename "${file}" )
mv "$file" "cache/.$name" 2> /dev/null
if [ $? -eq 0 ]; then
line=$(head -n 1 "cache/.$name")
IFS="%"
set -- $line
IFS=" "
_convert 1 "$@"
rm "cache/.$name"
break
fi
fi
done
if [ $success -eq 1 ]; then
_startbatchprocess
fi
}
getwidth() {
if command -v magick >/dev/null 2>&1; then
filename=$1
originalwidth=$( magick identify -ping -format %w "$filename" )
echo $originalwidth
else
echo errormagicknotinstalled
fi
}
optimize() {
if command -v magick >/dev/null 2>&1; then
filenamecache=$2
fileextcache=$3
if [ -f cache/"$filenamecache" ]; then
mv cache/"$filenamecache" cache/."$filenamecache" 2> /dev/null
if [ $? -eq 0 ]; then
line=$(head -n 1 "cache/.$filenamecache")
IFS="%"
set -- $line
IFS=" "
_convert 1 "$@"
rm "cache/.$filenamecache"
else
while [ ! -f cache/"$filenamecache"/g"$fileextcache" ]; do
sleep 0.05
done
fi
elif [ -d cache/"$filenamecache" ]; then
while [ ! -f cache/"$filenamecache"/g"$fileextcache" ]; do
sleep 0.05
done
else
_convert 0 "$@"
fi
echo ok
else
echo errormagicknotinstalled
fi
}
makeshadow() {
if command -v magick >/dev/null 2>&1; then
filename=$1
stdDeviation=$2
opacity=$3
fill=$4
width=$5
height=$6
framewidth=$7
frameheight=$8
frameborder=$9
frameradius=${10}
[ ! -d cache ] && mkdir cache
mkdir -p cache/$filename
echo "
" > cache/$filename/s.svg
inkscape cache/$filename/s.svg --export-dpi=600 --export-filename cache/$filename/s.pdf
rm cache/$filename/s.svg
echo ok
else
echo errorinkscapenotinstalled
fi
}
import() {
if [ -d import ]; then
importdir=import
elif [ "$XPUT_IMPORT_DIRECTORY" != "" ]; then
if [ -d "$XPUT_IMPORT_DIRECTORY" ]; then
importdir="$XPUT_IMPORT_DIRECTORY"
else
echo $XPUT_IMPORT_DIRECTORY
exit
fi
else
echo errornoimportdir
exit
fi
defaultdirectory=$( echo $1 | sed -e 's/^{//g' | sed -e 's/}{.*//g' )
directorylist=$( echo $1 | sed -e 's/^{//g' | sed -e 's/}$//g' | sed -e 's/}{/$/g' )
for entry in "$importdir"/*.*
do
if [ -f "$entry" ]; then
name=$( basename "${entry}" )
if [ "$directorylist" != "" ]; then
echo "$directorylist" | tr '$' '\n' | while read directory; do
if [ -f "$directory$name" ]; then
mv "$entry" "$directory"
fi
done
fi
if [ -f "$entry" ]; then
if [ -d "$defaultdirectory" ]; then
mv "$entry" "$defaultdirectory"
else
mv "$entry" .
fi
fi
cachename=$( echo "$name" | sed -e 's/\.[a-zA-Z]*$//g' )
rm -rf cache/"$cachename"*
fi
done
}
startturbo() {
file="$(echo $1 | sed -e 's/\.pdflatex$//g')"
if [ -f $file.tex ]; then
tmpdir=$( mktemp -d 2>/dev/null )/xputturbo$( date "+%Y%m%d%H%M%S" )$RANDOM
mkdir $tmpdir
cp $file.tex $tmpdir/xputturbobatchoptimizexyz.tex
command=$(echo $(ps -p $PPID -o command ))
engine=$(echo $command | sed -e 's/^[A-Z ]*//g' | sed -e 's/ .*//g' | tr -d '\n')
case "$command" in
*-shell-escape*)
shellescape="--shell-escape"
;;
esac
if [ "$engine" = "xelatex" ]; then
nopdf="-no-pdf"
fi
$engine $shellescape -interaction=batchmode $nopdf --output-directory $tmpdir $tmpdir/xputturbobatchoptimizexyz.tex > /dev/null
rm -rf $tmpdir
fi
}
batchoptimize() {
[ ! -d cache ] && mkdir cache
length=$(( $# / 15 ))
cores=$( nproc )
[ $cores -gt $length ] && cores=$length
while [ $length -gt 0 ]; do
filenamecache="$2"
if [ ! -e cache/"$filenamecache" ]; then
index=0
while [ $index -lt 15 ]; do
if [ $index -eq 0 ]; then
item="$1"
else
item="$item%$1"
fi
shift
index=$(( index + 1 ))
done
echo $item > cache/"$filenamecache"
else
shift 15
fi
length=$(( length - 1 ))
done
cores=$(( cores - 1 ))
while [ $cores -gt 0 ]; do
_startbatchprocess &
sleep 0.01
cores=$(( cores - 1 ))
done
}
usage() {
cat <= 100)
UNSHARP unsharp filter (eg. 2x1)
QUALITY quality (integer > 0, <= 100)
STANDARDDEVIATION standard deviation (decimal > 0.0)
OPACITY opacity (decimal >= 0.0, <= 1.0)
COLOR color string (eg. pink)
GRAPHICSPATH list of directories (eg. {images/}{tmp/})
JOBNAME LaTeX filename without extension (eg. my-document)
BATCHLIST a flat list of batch items where each batch item is
a flat list of the 15 parameters required by the
command \`xputserver optimize\`
All other parameters are length dimensions.
The command \`xputserver optimize\` expects integer values in the LaTeX
unit sp (eg. 65536).
The command \`xputserver makeshadow\` expects decimal values in a SVG
compatible unit (eg. 420.0pt).
Running \`xputserver getwidth\` returns the width in pixels for the given
image file.
Running \`xputserver optimize\` creates a cropped, rezised, sharpend and
compressed image and stores it in the cache directory.
Running \`xputserver makeshadow\` creates a shadow image and stores it in
the cache directory.
Running \`xputserver start\` with the import parameter triggers the image
import (see xputmanual.pdf chapter "Image Optimization").
Running the command with the parameter turbo, where the jobname is the
filename of the Xput document, processes the document in a special batch
mode, that creates a batch list and calls the command
\`xputserver batchoptimize\`.
Running \`xputserver batchoptimize\` optimizes multiple images in parallel.
Running \`xputserver --help\` returns this man page.
Running \`xputserver --version\` returns the Xput version.
HELP_USAGE
}
if [ "$1" = --version ]; then
echo Xput Server $version
exit
fi
input=$( echo "$@" | sed -e 's/\\//g' | sed -e 's/ %/%/g' | sed -e 's/% /%/g' )
IFS="%"
set -- $input
IFS=" "
case "$1" in
getwidth)
shift
getwidth "$1"
;;
optimize)
shift
optimize "$@"
;;
makeshadow)
shift
makeshadow "$@"
;;
start)
shift
if [ "$1" = "import" ]; then
shift
import "$1"
shift
fi
if [ "$1" = "turbo" ]; then
shift
startturbo "$1" &
fi
echo ok
;;
batchoptimize)
shift
batchoptimize "$@" &
echo ok
;;
*)
usage
esac