#!/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