diff --git a/pdfScale.sh b/pdfScale.sh index 1c4d5ba..d8ea3c4 100755 --- a/pdfScale.sh +++ b/pdfScale.sh @@ -48,6 +48,8 @@ ADAPTIVEMODE=$TRUE # Automatically try to guess best mode AUTOMATIC_SCALING=$TRUE # Default scaling in $SCALE, override by resize mode MODE="" RESIZE_PAPER_TYPE="" +CUSTOM_RESIZE_PAPER=$FALSE +FLIP_DETECTION=$TRUE PGWIDTH="" PGHEIGHT="" RESIZE_WIDTH="" @@ -76,7 +78,7 @@ EXIT_INVALID_PAPER_SIZE=50 # Main function called at the end main() { printVersion 1 'verbose' - loadDeps + checkDeps vprint " Input file: $INFILEPDF" vprint " Output file: $OUTFILEPDF" getPageSize @@ -118,7 +120,7 @@ main() { ########################## INITIALIZER ########################## # Loads external dependencies and checks for errors -loadDeps() { +initDeps() { GSBIN="$(which gs 2>/dev/null)" BCBIN="$(which bc 2>/dev/null)" IDBIN=$(which identify 2>/dev/null) @@ -128,8 +130,11 @@ loadDeps() { vprint "Checking for ghostscript and bcmath" if notIsAvailable "$GSBIN"; then printDependency 'ghostscript'; fi if notIsAvailable "$BCBIN"; then printDependency 'bc'; fi - - if [[ $MODE = "IDENTIFY" ]]; then +} + +# Checks for dependencies errors, run after getting options +checkDeps() { + if [[ $MODE = "IDENTIFY" ]]; then vprint "Checking for imagemagick's identify" if notIsAvailable "$IDBIN"; then printDependency 'imagemagick'; fi fi @@ -150,7 +155,7 @@ loadDeps() { # Parse options getOptions() { - while getopts ":vhVs:m:r:p" o; do + while getopts ":vhVs:m:r:pf" o; do case "${o}" in v) ((VERBOSE++)) @@ -176,6 +181,9 @@ getOptions() { printPaperInfo exit $EXIT_SUCCESS ;; + f) + FLIP_DETECTION=$FALSE + ;; *) initError "Invalid Option: -$OPTARG" $EXIT_INVALID_OPTION ;; @@ -206,15 +214,16 @@ getOptions() { # Parses and validates the scaling factor parseScale() { AUTOMATIC_SCALING=$FALSE - if ! [[ -n "$1" && "$1" =~ ^-?[0-9]*([.][0-9]+)?$ && (($1 > 0 )) ]] ; then + if ! isFloatBiggerThanZero "$1"; then printError "Invalid factor: $1" printError "The factor must be a floating point number greater than 0" printError "Example: for 80% use 0.8" exit $EXIT_INVALID_SCALE fi - SCALE=$1 + SCALE="$1" } + ###################### GHOSTSCRIPT CALLS ####################### # Runs the ghostscript scaling script @@ -241,16 +250,16 @@ pageScale() { # Runs the ghostscript paper resize script pageResize() { - getGSPaperSize "$RESIZE_PAPER_TYPE" + isNotCustomPaper && getGSPaperSize "$RESIZE_PAPER_TYPE" local tmpInverter="" - if [[ $PGWIDTH -gt $PGHEIGHT && $RESIZE_WIDTH -lt $RESIZE_HEIGHT ]]; then + if [[ $FLIP_DETECTION -eq $TRUE && $PGWIDTH -gt $PGHEIGHT && $RESIZE_WIDTH -lt $RESIZE_HEIGHT ]]; then vprint " Flip Detect: Wrong orientation!" vprint " Inverting Width <-> Height" tmpInverter=$RESIZE_HEIGHT RESIZE_HEIGHT=$RESIZE_WIDTH RESIZE_WIDTH=$tmpInverter fi - vprint " Resizing to: $(uppercase $RESIZE_PAPER_TYPE) ( $RESIZE_WIDTH x $RESIZE_HEIGHT )" + vprint " Resizing to: $(uppercase $RESIZE_PAPER_TYPE) ( $RESIZE_WIDTH x $RESIZE_HEIGHT ) pts" # Change page size "$GSBIN" \ @@ -267,7 +276,6 @@ pageResize() { } - ################### PDF PAGE SIZE DETECTION #################### # Parse a forced mode of operation @@ -611,7 +619,8 @@ flsa flse halfletter hagaki) printPaperNames() { isEmpty "$paperNames" && getPaperNames for i in "${!paperNames[@]}"; do - [[ $i -ne 0 && $((i % 5)) -eq 0 ]] && echo "" + [[ $i -eq 0 ]] && echo -n -e ' ' + [[ $i -ne 0 && $((i % 5)) -eq 0 ]] && echo -n -e $'\n ' ppN="$(uppercase ${paperNames[i]})" printf "%-14s" "$ppN" done @@ -677,8 +686,62 @@ printPaperTable() { parsePaperResize() { isEmpty "$1" && initError 'Invalid Paper Type: (empty)' $EXIT_INVALID_PAPER_SIZE local lowercasePaper="$(lowercase $1)" - isPaperName "$lowercasePaper" || initError "Invalid Paper Type: $1" $EXIT_INVALID_PAPER_SIZE - RESIZE_PAPER_TYPE="$lowercasePaper" + if [[ "$1" = 'custom' ]]; then + if isNotValidMeasure "$2" || ! isFloatBiggerThanZero "$3" || ! isFloatBiggerThanZero "$4"; then + initError "Invalid Custom Paper Definition!"$'\n'"Use: -r 'custom '"$'\n'"Measurements: mm, in, pts" $EXIT_INVALID_OPTION + fi + RESIZE_PAPER_TYPE="custom" + CUSTOM_RESIZE_PAPER=$TRUE + if isMilimeter "$2"; then + RESIZE_WIDTH="$(milimetersToPoints "$3")" + RESIZE_HEIGHT="$(milimetersToPoints "$4")" + elif isInch "$2"; then + RESIZE_WIDTH="$(inchesToPoints "$3")" + RESIZE_HEIGHT="$(inchesToPoints "$4")" + elif isPoint "$2"; then + RESIZE_WIDTH="$3" + RESIZE_HEIGHT="$4" + else + initError "Invalid Custom Paper Definition!"$'\n'"Use: -r 'custom '"$'\n'"Measurements: mm, in, pts" $EXIT_INVALID_OPTION + fi + else + isPaperName "$lowercasePaper" || initError "Invalid Paper Type: $1" $EXIT_INVALID_PAPER_SIZE + RESIZE_PAPER_TYPE="$lowercasePaper" + fi +} + +# Returns $TRUE if $1 is a valid measurement for a custom paper, $FALSE otherwise +isNotValidMeasure() { + isMilimeter "$1" || isInch "$1" || isPoint "$1" && return $FALSE + return $TRUE +} + +# Returns $TRUE if $1 is a valid milimeter string, $FALSE otherwise +isMilimeter() { + [[ "$1" = 'mm' || "$1" = 'milimeters' || "$1" = 'milimeter' ]] && return $TRUE + return $FALSE +} + +# Returns $TRUE if $1 is a valid inch string, $FALSE otherwise +isInch() { + [[ "$1" = 'in' || "$1" = 'inch' || "$1" = 'inches' ]] && return $TRUE + return $FALSE +} + +# Returns $TRUE if $1 is a valid point string, $FALSE otherwise +isPoint() { + [[ "$1" = 'pt' || "$1" = 'pts' || "$1" = 'point' || "$1" = 'points' ]] && return $TRUE + return $FALSE +} + +# Returns $TRUE if a custom paper is being used, $FALSE otherwise +isCustomPaper() { + return $CUSTOM_RESIZE_PAPER +} + +isNotCustomPaper() { + isCustomPaper && return $FALSE + return $TRUE } # Returns $TRUE if the scale was set manually, $FALSE if we are using automatic scaling @@ -747,10 +810,22 @@ uppercase() { done } +# Prints the postscript points rounded equivalent from $1 mm +milimetersToPoints() { + local pts=$(echo "scale=6; $1 * 72 / 25.4" | "$BCBIN") + printf '%.0f' "$pts" # Print rounded conversion +} + +# Prints the postscript points rounded equivalent from $1 mm +inchesToPoints() { + local pts=$(echo "scale=6; $1 * 72" | "$BCBIN") + printf '%.0f' "$pts" # Print rounded conversion +} + ########################## VALIDATORS ########################## -# Returns $TRUE if $PGWIDTH OR $PGWIDTH are empty or NOT an Integer, false otherwise +# Returns $TRUE if $PGWIDTH OR $PGWIDTH are empty or NOT an Integer, $FALSE otherwise pageSizeIsInvalid() { if isNotAnInteger "$PGWIDTH" || isNotAnInteger "$PGHEIGHT"; then return $TRUE @@ -759,33 +834,33 @@ pageSizeIsInvalid() { } -# Return $TRUE if adaptive mode is enabled, false otherwise +# Return $TRUE if adaptive mode is enabled, $FALSE otherwise isAdaptiveMode() { return $ADAPTIVEMODE } -# Return $TRUE if adaptive mode is disabled, false otherwise +# Return $TRUE if adaptive mode is disabled, $FALSE otherwise isNotAdaptiveMode() { isAdaptiveMode && return $FALSE return $TRUE } -# Return $TRUE if $1 is empty, false otherwise +# Return $TRUE if $1 is empty, $FALSE otherwise isEmpty() { [[ -z "$1" ]] && return $TRUE return $FALSE } -# Return $TRUE if $1 is NOT empty, false otherwise +# Return $TRUE if $1 is NOT empty, $FALSE otherwise isNotEmpty() { [[ -z "$1" ]] && return $FALSE return $TRUE } - +# Returns $TRUE if $1 is an integer, $FALSE otherwise isAnInteger() { case $1 in ''|*[!0-9]*) return $FALSE ;; @@ -793,7 +868,7 @@ isAnInteger() { esac } - +# Returns $TRUE if $1 is NOT an integer, $FALSE otherwise isNotAnInteger() { case $1 in ''|*[!0-9]*) return $TRUE ;; @@ -801,6 +876,17 @@ isNotAnInteger() { esac } +# Returns $TRUE if $1 is a floating point number (or an integer), $FALSE otherwise +isFloat() { + [[ -n "$1" && "$1" =~ ^-?[0-9]*([.][0-9]+)?$ ]] && return $TRUE + return $FALSE +} + +# Returns $TRUE if $1 is a floating point number bigger than zero, $FALSE otherwise +isFloatBiggerThanZero() { + isFloat "$1" && [[ (( $1 > 0 )) ]] && return $TRUE + return $FALSE +} # Returns $TRUE if $1 has a .pdf extension, false otherwsie isPDF() { @@ -892,30 +978,32 @@ Parameters: Eg. -s 0.8 for 80% of the original size -r Triggers the Resize Paper Mode Resize PDF paper proportionally - Must be a valid Ghostscript paper name + A valid paper name or a custom defined paper + -f Disables the flip detection, paper will not be + rotated to landscape when needed (resize-only) -p Prints Ghostscript paper info tables to screen Scaling Mode: -The default mode of operation is scaling mode with fixed paper -size and scaling pre-set to $SCALE. By not using the resize mode -you are using scaling mode. + The default mode of operation is scaling mode with fixed paper + size and scaling pre-set to $SCALE. By not using the resize mode + you are using scaling mode. Resize Paper Mode: -Disables the default scaling factor! ($SCALE) -Alternative mode of operation to change the PDF paper -proportionally. Will fit-to-page. + Disables the default scaling factor! ($SCALE) + Alternative mode of operation to change the PDF paper + proportionally. Will fit-to-page. Mixed Mode: -In mixed mode both the -s option and -r option must be specified. -The PDF will be both scaled and have the paper type changed. + In mixed mode both the -s option and -r option must be specified. + The PDF will be first resized then scaled. Output filename: -The output filename is optional. If no file name is passed -the output file will have the same name/destination of the -input file with added suffixes: - .SCALED.pdf is added to scaled files - ..pdf is added to resized files - ..SCALED.pdf is added in mixed mode + The output filename is optional. If no file name is passed + the output file will have the same name/destination of the + input file with added suffixes: + .SCALED.pdf is added to scaled files + ..pdf is added to resized files + ..SCALED.pdf is added in mixed mode Page Detection Modes: a, adaptive Default mode, tries all the methods below @@ -927,6 +1015,14 @@ Page Detection Modes: Valid Ghostscript Paper Names: $paperList +Custom Paper Size: + Paper size can be set manually in Milimeters, Inches or Points. + Use: $PDFSCALE_NAME -r 'custom ' + Ex: $PDFSCALE_NAME -r 'custom mm 210 297' + Measurements can be: mm, inch, pts. + Custom paper definition MUST be quoted into a single parameter. + Actual size is applied in points (mms and inches are transformed). + Notes: - Adaptive Page size detection will try different modes until it gets a page size. You can force a mode with -m 'mode'. @@ -939,11 +1035,13 @@ Notes: Examples: $PDFSCALE_NAME myPdfFile.pdf - $PDFSCALE_NAME myPdfFile.pdf myScaledPdf + $PDFSCALE_NAME myPdfFile.pdf \"My Scaled Pdf\" $PDFSCALE_NAME -v -v myPdfFile.pdf - $PDFSCALE_NAME -s 0.85 myPdfFile.pdf myScaledPdf.pdf + $PDFSCALE_NAME -s 0.85 myPdfFile.pdf My\\ Scaled\\ Pdf.pdf $PDFSCALE_NAME -m pdfinfo -s 0.80 -v myPdfFile.pdf $PDFSCALE_NAME -v -v -m i -s 0.7 myPdfFile.pdf + $PDFSCALE_NAME -r A4 myPdfFile.pdf + $PDFSCALE_NAME -v -v -r \"custom mm 252 356\" -s 0.9 -f \"../input file.pdf\" \"../my new pdf\" $PDFSCALE_NAME -h " } @@ -1001,6 +1099,7 @@ printError() { ########################## EXECUTION ########################### +initDeps getOptions "${@}" main exit $?