Bash Script to scale and/or resize PDFs from the command line.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 

227 satır
6.4 KiB

  1. #!/usr/bin/env bash
  2. # pdfScale.sh
  3. #
  4. # Scale PDF to specified percentage of original size.
  5. #
  6. # Gutavo Arnosti Neves - 2016 / 07 / 10
  7. #
  8. # This script: https://github.com/tavinus/pdfScale
  9. # Based on: http://ma.juii.net/blog/scale-page-content-of-pdf-files
  10. # And: https://gist.github.com/MichaelJCole/86e4968dbfc13256228a
  11. VERSION="1.2.1"
  12. SCALE="0.95" # scaling factor (0.95 = 95%, e.g.)
  13. VERBOSE=0 # verbosity Level
  14. BASENAME="$(basename $0)" # simplified name of this script
  15. GSBIN="" # Set with which after we check dependencies
  16. BCBIN="" # Set with which after we check dependencies
  17. LC_MEASUREMENT="C" # To make sure our numbers have .decimals
  18. LC_ALL="C" # Some languages use , as decimal token
  19. LC_CTYPE="C"
  20. LC_NUMERIC="C"
  21. printVersion() {
  22. if [[ $1 -eq 2 ]]; then
  23. echo >&2 "$BASENAME v$VERSION"
  24. else
  25. echo "$BASENAME v$VERSION"
  26. fi
  27. }
  28. printHelp() {
  29. printVersion
  30. echo "
  31. Usage: $BASENAME [-v] [-s <factor>] <inFile.pdf> [outfile.pdf]
  32. $BASENAME -h
  33. $BASENAME -V
  34. Parameters:
  35. -v Verbose mode, prints extra information
  36. Use twice for even more information
  37. -h Print this help to screen and exits
  38. -V Prints version to screen and exits
  39. -s <factor> Changes the scaling factor, defaults to 0.95
  40. MUST be a number bigger than zero.
  41. Eg. -s 0.8 for 80% of the original size
  42. Notes:
  43. - Options must be passed before the file names to be parsed
  44. - The output filename is optional. If no file name is passed
  45. the output file will have the same name/destination of the
  46. input file, with .SCALED.pdf at the end (instead of just .pdf)
  47. - Having the extension .pdf on the output file name is optional,
  48. it will be added if not present
  49. - Should handle file names with spaces without problems
  50. - The scaling is centered and using a scale bigger than 1 may
  51. result on cropping parts of the pdf.
  52. Examples:
  53. $BASENAME myPdfFile.pdf
  54. $BASENAME myPdfFile.pdf myScaledPdf
  55. $BASENAME -v -v myPdfFile.pdf
  56. $BASENAME -s 0.85 myPdfFile.pdf myScaledPdf.pdf
  57. $BASENAME -v -v -s 0.7 myPdfFile.pdf
  58. $BASENAME -h
  59. "
  60. }
  61. usage() {
  62. printVersion 2
  63. echo >&2 "Usage: $BASENAME [-v] [-s <factor>] <inFile.pdf> [outfile.pdf]"
  64. echo >&2 "Try: $BASENAME -h # for help"
  65. exit 1
  66. }
  67. vprint() {
  68. [[ $VERBOSE -eq 0 ]] && return 0
  69. timestamp=""
  70. [[ $VERBOSE -gt 1 ]] && timestamp="$(date +%Y-%m-%d:%H:%M:%S) | "
  71. echo "$timestamp$1"
  72. }
  73. printDependency() {
  74. printVersion 2
  75. echo >&2 $'\n'"ERROR! You need to install the package '$1'"$'\n'
  76. echo >&2 "Linux apt-get.: sudo apt-get install $1"
  77. echo >&2 "Linux yum.....: sudo yum install $1"
  78. echo >&2 "MacOS homebrew: brew install $1"
  79. echo >&2 $'\n'"Aborting..."
  80. exit 3
  81. }
  82. parseScale() {
  83. if ! [[ -n "$1" && "$1" =~ ^-?[0-9]*([.][0-9]+)?$ && (($1 > 0 )) ]] ; then
  84. echo >&2 "Invalid factor: $1"
  85. echo >&2 "The factor must be a floating point number greater than 0"
  86. echo >&2 "Example: for 80% use 0.8"
  87. exit 2
  88. fi
  89. SCALE=$1
  90. }
  91. getPageSize() {
  92. # get MediaBox info from PDF file using cat and grep, these are all possible
  93. # /MediaBox [0 0 595 841]
  94. # /MediaBox [ 0 0 595.28 841.89]
  95. # /MediaBox[ 0 0 595.28 841.89 ]
  96. # Get MediaBox data if possible
  97. local mediaBox="$(cat "$INFILEPDF" | grep -a '/MediaBox')"
  98. # If no MediaBox, try BBox
  99. if [[ -z $mediaBox ]]; then
  100. mediaBox="$(cat "$INFILEPDF" | grep -a '/BBox')"
  101. fi
  102. # No page size data available
  103. if [[ -z $mediaBox ]]; then
  104. echo "Error when reading input file!"
  105. echo "Could not determine the page size!"
  106. echo "There is no MediaBox or BBox in the pdf document!"
  107. echo "Aborting..."
  108. exit 15
  109. fi
  110. # remove chars [ and ]
  111. mediaBox="${mediaBox//[}"
  112. mediaBox="${mediaBox//]}"
  113. mediaBox=($mediaBox) # make it an array
  114. mbCount=${#mediaBox[@]} # array size
  115. # sanity
  116. if [[ $mbCount -lt 5 ]]; then
  117. echo "Error when reading the page size!"
  118. echo "The page size information is invalid!"
  119. exit 16
  120. fi
  121. # we are done
  122. PGWIDTH=$(printf '%.0f' "${mediaBox[3]}") # Get Round Width
  123. PGHEIGHT=$(printf '%.0f' "${mediaBox[4]}") # Get Round Height
  124. vprint " Width: $PGWIDTH postscript-points"
  125. vprint " Height: $PGHEIGHT postscript-points"
  126. }
  127. # Parse options
  128. while getopts ":vhVs:" o; do
  129. case "${o}" in
  130. v)
  131. ((VERBOSE++))
  132. ;;
  133. h)
  134. printHelp
  135. exit 0
  136. ;;
  137. V)
  138. printVersion
  139. exit 0
  140. ;;
  141. s)
  142. parseScale ${OPTARG}
  143. ;;
  144. *)
  145. usage
  146. ;;
  147. esac
  148. done
  149. shift $((OPTIND-1))
  150. ######### START EXECUTION
  151. #Intro message
  152. vprint "$(basename $0) v$VERSION - Verbose execution"
  153. # Dependencies
  154. vprint "Checking dependencies"
  155. command -v gs >/dev/null 2>&1 || printDependency 'ghostscript'
  156. command -v bc >/dev/null 2>&1 || printDependency 'bc'
  157. # Get dependency binaries
  158. GSBIN=$(which gs 2>/dev/null)
  159. BCBIN=$(which bc 2>/dev/null)
  160. # Verbose scale info
  161. vprint " Scale factor: $SCALE"
  162. # Validate args
  163. [[ $# -lt 1 ]] && { usage; exit 1; }
  164. INFILEPDF="$1"
  165. [[ "$INFILEPDF" =~ ^..*\.pdf$ ]] || { usage; exit 2; }
  166. vprint " Input file: $INFILEPDF"
  167. # Parse output filename
  168. if [[ -z $2 ]]; then
  169. OUTFILEPDF="${INFILEPDF%.pdf}.SCALED.pdf"
  170. else
  171. OUTFILEPDF="${2%.pdf}.pdf"
  172. fi
  173. vprint " Output file: $OUTFILEPDF"
  174. # Set PGWIDTH and PGHEIGHT
  175. getPageSize
  176. # Compute translation factors (to center page.
  177. XTRANS=$(echo "scale=6; 0.5*(1.0-$SCALE)/$SCALE*$PGWIDTH" | "$BCBIN")
  178. YTRANS=$(echo "scale=6; 0.5*(1.0-$SCALE)/$SCALE*$PGHEIGHT" | "$BCBIN")
  179. vprint " Translation X: $XTRANS"
  180. vprint " Translation Y: $YTRANS"
  181. # Do it.
  182. "$GSBIN" \
  183. -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
  184. -dCompatibilityLevel="1.5" -dPDFSETTINGS="/printer" \
  185. -dColorConversionStrategy=/LeaveColorUnchanged \
  186. -dSubsetFonts=true -dEmbedAllFonts=true \
  187. -dDEVICEWIDTH=$PGWIDTH -dDEVICEHEIGHT=$PGHEIGHT \
  188. -sOutputFile="$OUTFILEPDF" \
  189. -c "<</BeginPage{$SCALE $SCALE scale $XTRANS $YTRANS translate}>> setpagedevice" \
  190. -f "$INFILEPDF"