Bash Script to scale and/or resize PDFs from the command line.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 

1282 rindas
42 KiB

  1. #!/usr/bin/env bash
  2. # pdfScale.sh
  3. #
  4. # Scale PDF to specified percentage of original size.
  5. #
  6. # Gustavo Arnosti Neves - 2016 / 07 / 10
  7. # Latest Version - 2017 / 05 / 14
  8. #
  9. # This script: https://github.com/tavinus/pdfScale
  10. # Based on: http://ma.juii.net/blog/scale-page-content-of-pdf-files
  11. # And: https://gist.github.com/MichaelJCole/86e4968dbfc13256228a
  12. VERSION="2.0.0"
  13. ###################### EXTERNAL PROGRAMS #######################
  14. GSBIN="" # GhostScript Binary
  15. BCBIN="" # BC Math Binary
  16. IDBIN="" # Identify Binary
  17. PDFINFOBIN="" # PDF Info Binary
  18. MDLSBIN="" # MacOS mdls Binary
  19. ##################### ENVIRONMENT SET-UP #######################
  20. LC_MEASUREMENT="C" # To make sure our numbers have .decimals
  21. LC_ALL="C" # Some languages use , as decimal token
  22. LC_CTYPE="C"
  23. LC_NUMERIC="C"
  24. TRUE=0 # Silly stuff
  25. FALSE=1
  26. ########################### GLOBALS ############################
  27. SCALE="0.95" # scaling factor (0.95 = 95%, e.g.)
  28. VERBOSE=0 # verbosity Level
  29. PDFSCALE_NAME="$(basename $0)" # simplified name of this script
  30. OSNAME="$(uname 2>/dev/null)" # Check where we are running
  31. JUST_IDENTIFY=$FALSE # Flag to just show PDF info
  32. ADAPTIVEMODE=$TRUE # Automatically try to guess best mode
  33. AUTOMATIC_SCALING=$TRUE # Default scaling in $SCALE, override by resize mode
  34. MODE="" # Which page size detection to use
  35. RESIZE_PAPER_TYPE="" # Pre-defined paper to use
  36. CUSTOM_RESIZE_PAPER=$FALSE # If we are using a custom-defined paper
  37. FLIP_DETECTION=$TRUE # If we shoudl run the Flip-detection
  38. FLIP_FORCE=$FALSE # If we should force Flipping
  39. AUTO_ROTATION='/PageByPage' # GS cal auto-rotation setting
  40. PGWIDTH="" # Input PDF Page Width
  41. PGHEIGHT="" # Input PDF Page Height
  42. RESIZE_WIDTH="" # Resized PDF Page Width
  43. RESIZE_HEIGHT="" # Resized PDF Page Height
  44. ########################## EXIT FLAGS ##########################
  45. EXIT_SUCCESS=0
  46. EXIT_ERROR=1
  47. EXIT_INVALID_PAGE_SIZE_DETECTED=10
  48. EXIT_FILE_NOT_FOUND=20
  49. EXIT_INPUT_NOT_PDF=21
  50. EXIT_INVALID_OPTION=22
  51. EXIT_NO_INPUT_FILE=23
  52. EXIT_INVALID_SCALE=24
  53. EXIT_MISSING_DEPENDENCY=25
  54. EXIT_IMAGEMAGIK_NOT_FOUND=26
  55. EXIT_MAC_MDLS_NOT_FOUND=27
  56. EXIT_PDFINFO_NOT_FOUND=28
  57. EXIT_TEMP_FILE_EXISTS=40
  58. EXIT_INVALID_PAPER_SIZE=50
  59. ############################# MAIN #############################
  60. # Main function called at the end
  61. main() {
  62. checkDeps
  63. printPDFSizes
  64. vprint " Input File: $INFILEPDF"
  65. vprint " Output File: $OUTFILEPDF"
  66. getPageSize
  67. vPrintPageSizes ' Source'
  68. local finalRet=$EXIT_ERROR
  69. local tempFile=""
  70. local tempSuffix="$RANDOM$RANDOM""_TEMP_$RANDOM$RANDOM.pdf"
  71. if isMixedMode; then
  72. outputFile="$OUTFILEPDF" # backup outFile name
  73. tempFile="${OUTFILEPDF%.pdf}.$tempSuffix" # set a temp file name
  74. if isFile "$tempFile"; then
  75. printError $'Error! Temporary file name already exists!\n'"File: $tempFile"$'\nAborting execution to avoid overwriting the file.\nPlease Try again...'
  76. exit $EXIT_TEMP_FILE_EXISTS
  77. fi
  78. OUTFILEPDF="$tempFile" # set output to tmp file
  79. pageResize # resize to tmp file
  80. finalRet=$?
  81. INFILEPDF="$tempFile" # get tmp file as input
  82. OUTFILEPDF="$outputFile" # reset final target
  83. PGWIDTH=$RESIZE_WIDTH # we already know the new page size
  84. PGHEIGHT=$RESIZE_HEIGHT # from the last command (Resize)
  85. vPrintPageSizes ' New'
  86. vPrintScaleFactor
  87. pageScale # scale the resized pdf
  88. finalRet=$(($finalRet+$?))
  89. # remove tmp file
  90. rm "$tempFile" >/dev/null 2>&1 || printError "Error when removing temporary file: $tempFile"
  91. elif isResizeMode; then
  92. vPrintScaleFactor "Disabled (resize only)"
  93. pageResize
  94. finalRet=$?
  95. else
  96. local scaleMode=""
  97. isManualScaledMode && scaleMode='(manual)' || scaleMode='(auto)'
  98. vPrintScaleFactor "$SCALE $scaleMode"
  99. pageScale
  100. finalRet=$?
  101. fi
  102. if [[ finalRet -eq $EXIT_SUCCESS ]]; then
  103. vprint " Final Status: File created successfully"
  104. else
  105. vprint " Final Status: Errors were detected. Exit status: $finalRet"
  106. fi
  107. return $finalRet
  108. }
  109. # Prints PDF Info and exits with $EXIT_SUCCESS, but only if $JUST_IDENTIFY is $TRUE
  110. printPDFSizes() {
  111. if [[ $JUST_IDENTIFY -eq $TRUE ]]; then
  112. VERBOSE=0
  113. printVersion 3 " - Paper Sizes"
  114. getPageSize || initError "Could not get pagesize!"
  115. local paperType="$(getGSPaperName $PGWIDTH $PGHEIGHT)"
  116. isEmpty "$paperType" && paperType="NOT Detected"
  117. printf " File: %s\n" "$(basename "$INFILEPDF")"
  118. printf " Paper Type: %s\n" "$paperType"
  119. printf '%s\n' "------------+----WIDTH-+-HEIGHT-----------"
  120. printf " Points | %+8s | %-8s\n" "$PGWIDTH" "$PGHEIGHT"
  121. printf " Milimeters | %+8s | %-8s\n" "$(pointsToMilimeters $PGWIDTH)" "$(pointsToMilimeters $PGHEIGHT)"
  122. printf " Inches | %+8s | %-8s\n" "$(pointsToInches $PGWIDTH)" "$(pointsToInches $PGHEIGHT)"
  123. exit $EXIT_SUCCESS
  124. fi
  125. return $EXIT_SUCCESS
  126. }
  127. ###################### GHOSTSCRIPT CALLS #######################
  128. # Runs the ghostscript scaling script
  129. pageScale() {
  130. # Compute translation factors (to center page).
  131. XTRANS=$(echo "scale=6; 0.5*(1.0-$SCALE)/$SCALE*$PGWIDTH" | "$BCBIN")
  132. YTRANS=$(echo "scale=6; 0.5*(1.0-$SCALE)/$SCALE*$PGHEIGHT" | "$BCBIN")
  133. vprint " Translation X: $XTRANS"
  134. vprint " Translation Y: $YTRANS"
  135. local increase=$(echo "scale=0; (($SCALE - 1) * 100)/1" | "$BCBIN")
  136. vprint " Run Scaling: $increase %"
  137. # Scale page
  138. "$GSBIN" \
  139. -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
  140. -dCompatibilityLevel="1.5" -dPDFSETTINGS="/printer" \
  141. -dColorConversionStrategy=/LeaveColorUnchanged \
  142. -dSubsetFonts=true -dEmbedAllFonts=true \
  143. -dDEVICEWIDTHPOINTS=$PGWIDTH -dDEVICEHEIGHTPOINTS=$PGHEIGHT \
  144. -sOutputFile="$OUTFILEPDF" \
  145. -c "<</BeginPage{$SCALE $SCALE scale $XTRANS $YTRANS translate}>> setpagedevice" \
  146. -f "$INFILEPDF"
  147. return $?
  148. }
  149. # Runs the ghostscript paper resize script
  150. pageResize() {
  151. # Get new paper sizes if not custom paper
  152. isNotCustomPaper && getGSPaperSize "$RESIZE_PAPER_TYPE"
  153. vprint " Auto Rotate: $(basename $AUTO_ROTATION)"
  154. # Flip detect
  155. local tmpInverter=""
  156. if [[ $FLIP_DETECTION -eq $TRUE || $FLIP_FORCE -eq $TRUE ]]; then
  157. if [[ $PGWIDTH -gt $PGHEIGHT && $RESIZE_WIDTH -lt $RESIZE_HEIGHT ]] || [[ $FLIP_FORCE -eq $TRUE ]]; then
  158. [[ $FLIP_FORCE -eq $TRUE ]] && vprint " Flip Detect: Forced Mode!" || vprint " Flip Detect: Wrong orientation detected!"
  159. vprint " Inverting Width <-> Height"
  160. tmpInverter=$RESIZE_HEIGHT
  161. RESIZE_HEIGHT=$RESIZE_WIDTH
  162. RESIZE_WIDTH=$tmpInverter
  163. else
  164. vprint " Flip Detect: No change needed"
  165. fi
  166. else
  167. vprint " Flip Detect: Disabled"
  168. fi
  169. vprint " Run Resizing: $(uppercase "$RESIZE_PAPER_TYPE") ( "$RESIZE_WIDTH" x "$RESIZE_HEIGHT" ) pts"
  170. # Change page size
  171. "$GSBIN" \
  172. -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
  173. -dCompatibilityLevel="1.5" -dPDFSETTINGS="/printer" \
  174. -dColorConversionStrategy=/LeaveColorUnchanged \
  175. -dSubsetFonts=true -dEmbedAllFonts=true \
  176. -dDEVICEWIDTHPOINTS=$RESIZE_WIDTH -dDEVICEHEIGHTPOINTS=$RESIZE_HEIGHT \
  177. -dAutoRotatePages=$AUTO_ROTATION \
  178. -dFIXEDMEDIA -dPDFFitPage \
  179. -sOutputFile="$OUTFILEPDF" \
  180. -f "$INFILEPDF"
  181. return $?
  182. }
  183. ########################## INITIALIZERS #########################
  184. # Loads external dependencies and checks for errors
  185. initDeps() {
  186. GREPBIN="$(which grep 2>/dev/null)"
  187. GSBIN="$(which gs 2>/dev/null)"
  188. BCBIN="$(which bc 2>/dev/null)"
  189. IDBIN=$(which identify 2>/dev/null)
  190. MDLSBIN="$(which mdls 2>/dev/null)"
  191. PDFINFOBIN="$(which pdfinfo 2>/dev/null)"
  192. vprint "Checking for basename, grep, ghostscript and bcmath"
  193. basename "" >/dev/null 2>&1 || printDependency 'basename'
  194. notIsAvailable "$GREPBIN" && printDependency 'grep'
  195. notIsAvailable "$GSBIN" && printDependency 'ghostscript'
  196. notIsAvailable "$BCBIN" && printDependency 'bc'
  197. return $TRUE
  198. }
  199. # Checks for dependencies errors, run after getting options
  200. checkDeps() {
  201. if [[ $MODE = "IDENTIFY" ]]; then
  202. vprint "Checking for imagemagick's identify"
  203. if notIsAvailable "$IDBIN"; then printDependency 'imagemagick'; fi
  204. fi
  205. if [[ $MODE = "PDFINFO" ]]; then
  206. vprint "Checking for pdfinfo"
  207. if notIsAvailable "$PDFINFOBIN"; then printDependency 'pdfinfo'; fi
  208. fi
  209. if [[ $MODE = "MDLS" ]]; then
  210. vprint "Checking for MacOS mdls"
  211. if notIsAvailable "$MDLSBIN"; then
  212. initError 'mdls executable was not found! Is this even MacOS?' $EXIT_MAC_MDLS_NOT_FOUND 'nobanner'
  213. fi
  214. fi
  215. return $TRUE
  216. }
  217. ######################### CLI OPTIONS ##########################
  218. # Parse options
  219. getOptions() {
  220. while getopts ":vhVis:m:r:pf:a:" o; do
  221. case "${o}" in
  222. v)
  223. ((VERBOSE++))
  224. ;;
  225. h)
  226. printHelp
  227. exit $EXIT_SUCCESS
  228. ;;
  229. V)
  230. printVersion
  231. exit $EXIT_SUCCESS
  232. ;;
  233. i)
  234. JUST_IDENTIFY=$TRUE
  235. ;;
  236. s)
  237. parseScale ${OPTARG}
  238. ;;
  239. m)
  240. parseMode ${OPTARG}
  241. ;;
  242. r)
  243. parsePaperResize ${OPTARG}
  244. ;;
  245. p)
  246. printPaperInfo
  247. exit $EXIT_SUCCESS
  248. ;;
  249. f)
  250. parseFlipDetectionMode ${OPTARG}
  251. ;;
  252. a)
  253. parseAutoRotationMode ${OPTARG}
  254. ;;
  255. *)
  256. initError "Invalid Option: -$OPTARG" $EXIT_INVALID_OPTION
  257. ;;
  258. esac
  259. done
  260. shift $((OPTIND-1))
  261. if [[ $JUST_IDENTIFY -eq $TRUE ]]; then
  262. VERBOSE=0
  263. fi
  264. # Validate input PDF file
  265. INFILEPDF="$1"
  266. isEmpty "$INFILEPDF" && initError "Input file is empty!" $EXIT_NO_INPUT_FILE
  267. isPDF "$INFILEPDF" || initError "Input file is not a PDF file: $INFILEPDF" $EXIT_INPUT_NOT_PDF
  268. isFile "$INFILEPDF" || initError "Input file not found: $INFILEPDF" $EXIT_FILE_NOT_FOUND
  269. printVersion 1 'verbose'
  270. if isMixedMode; then
  271. vprint " Mixed Tasks: Resize & Scale"
  272. isEmpty "$2" && OUTFILEPDF="${INFILEPDF%.pdf}.$(uppercase $RESIZE_PAPER_TYPE).SCALED.pdf"
  273. elif isResizeMode; then
  274. vprint " Single Task: Resize PDF Paper"
  275. isEmpty "$2" && OUTFILEPDF="${INFILEPDF%.pdf}.$(uppercase $RESIZE_PAPER_TYPE).pdf"
  276. else
  277. vprint " Single Task: Scale PDF Contents"
  278. isEmpty "$2" && OUTFILEPDF="${INFILEPDF%.pdf}.SCALED.pdf"
  279. fi
  280. isNotEmpty "$2" && OUTFILEPDF="${2%.pdf}.pdf"
  281. }
  282. # Parses and validates the scaling factor
  283. parseScale() {
  284. AUTOMATIC_SCALING=$FALSE
  285. if ! isFloatBiggerThanZero "$1"; then
  286. printError "Invalid factor: $1"
  287. printError "The factor must be a floating point number greater than 0"
  288. printError "Example: for 80% use 0.8"
  289. exit $EXIT_INVALID_SCALE
  290. fi
  291. SCALE="$1"
  292. }
  293. # Parse a forced mode of operation
  294. parseMode() {
  295. local param="$(lowercase $1)"
  296. case "${param}" in
  297. c|catgrep|'cat+grep'|grep|g)
  298. ADAPTIVEMODE=$FALSE
  299. MODE="CATGREP"
  300. return $TRUE
  301. ;;
  302. i|imagemagick|identify)
  303. ADAPTIVEMODE=$FALSE
  304. MODE="IDENTIFY"
  305. return $TRUE
  306. ;;
  307. m|mdls|quartz|mac)
  308. ADAPTIVEMODE=$FALSE
  309. MODE="MDLS"
  310. return $TRUE
  311. ;;
  312. p|pdfinfo)
  313. ADAPTIVEMODE=$FALSE
  314. MODE="PDFINFO"
  315. return $TRUE
  316. ;;
  317. *)
  318. ADAPTIVEMODE=$TRUE
  319. MODE=""
  320. if [[ "$param" != 'a' && "$param" != 'auto' && "$param" != 'automatic' && "$param" != 'adaptive' ]]; then
  321. printError "Error! Invalid PDF Size Detection Mode: \"$1\", using adaptive mode!"
  322. return $FALSE
  323. fi
  324. return $TRUE
  325. ;;
  326. esac
  327. return $FALSE
  328. }
  329. # Parses and validates the scaling factor
  330. parseFlipDetectionMode() {
  331. local param="$(lowercase $1)"
  332. case "${param}" in
  333. d|disable)
  334. FLIP_DETECTION=$FALSE
  335. FLIP_FORCE=$FALSE
  336. ;;
  337. f|force)
  338. FLIP_DETECTION=$FALSE
  339. FLIP_FORCE=$TRUE
  340. ;;
  341. *)
  342. [[ "$param" != 'a' && "$param" != 'auto' ]] && printError "Error! Invalid Flip Detection Mode: \"$1\", using automatic mode!"
  343. FLIP_DETECTION=$TRUE
  344. FLIP_FORCE=$FALSE
  345. ;;
  346. esac
  347. }
  348. # Parses and validates the scaling factor
  349. parseAutoRotationMode() {
  350. local param="$(lowercase $1)"
  351. case "${param}" in
  352. n|none)
  353. AUTO_ROTATION='/None'
  354. ;;
  355. a|all)
  356. AUTO_ROTATION='/All'
  357. ;;
  358. p|pagebypage|auto)
  359. AUTO_ROTATION='/PageByPage'
  360. ;;
  361. *)
  362. printError "Error! Invalid Auto Rotation Mode: $param, using default: $(basename $AUTO_ROTATION)"
  363. ;;
  364. esac
  365. }
  366. ################### PDF PAGE SIZE DETECTION ####################
  367. ################################################################
  368. # Detects operation mode and also runs the adaptive mode
  369. # PAGESIZE LOGIC
  370. # 1- Try to get Mediabox with GREP
  371. # 2- MacOS => try to use mdls
  372. # 3- Try to use pdfinfo
  373. # 4- Try to use identify (imagemagick)
  374. # 5- Fail
  375. ################################################################
  376. getPageSize() {
  377. if isNotAdaptiveMode; then
  378. vprint " Get Page Size: Adaptive Disabled"
  379. if [[ $MODE = "CATGREP" ]]; then
  380. vprint " Method: Grep"
  381. getPageSizeCatGrep
  382. elif [[ $MODE = "MDLS" ]]; then
  383. vprint " Method: Mac Quartz mdls"
  384. getPageSizeMdls
  385. elif [[ $MODE = "PDFINFO" ]]; then
  386. vprint " Method: PDFInfo"
  387. getPageSizePdfInfo
  388. elif [[ $MODE = "IDENTIFY" ]]; then
  389. vprint " Method: ImageMagick's Identify"
  390. getPageSizeImagemagick
  391. else
  392. printError "Error! Invalid Mode: $MODE"
  393. printError "Aborting execution..."
  394. exit $EXIT_INVALID_OPTION
  395. fi
  396. return $TRUE
  397. fi
  398. vprint " Get Page Size: Adaptive Enabled"
  399. vprint " Method: Grep"
  400. getPageSizeCatGrep
  401. if pageSizeIsInvalid && [[ $OSNAME = "Darwin" ]]; then
  402. vprint " Failed"
  403. vprint " Method: Mac Quartz mdls"
  404. getPageSizeMdls
  405. fi
  406. if pageSizeIsInvalid; then
  407. vprint " Failed"
  408. vprint " Method: PDFInfo"
  409. getPageSizePdfInfo
  410. fi
  411. if pageSizeIsInvalid; then
  412. vprint " Failed"
  413. vprint " Method: ImageMagick's Identify"
  414. getPageSizeImagemagick
  415. fi
  416. if pageSizeIsInvalid; then
  417. vprint " Failed"
  418. printError "Error when detecting PDF paper size!"
  419. printError "All methods of detection failed"
  420. printError "You may want to install pdfinfo or imagemagick"
  421. exit $EXIT_INVALID_PAGE_SIZE_DETECTED
  422. fi
  423. return $TRUE
  424. }
  425. # Gets page size using imagemagick's identify
  426. getPageSizeImagemagick() {
  427. # Sanity and Adaptive together
  428. if notIsFile "$IDBIN" && isNotAdaptiveMode; then
  429. notAdaptiveFailed "Make sure you installed ImageMagick and have identify on your \$PATH" "ImageMagick's Identify"
  430. elif notIsFile "$IDBIN" && isAdaptiveMode; then
  431. return $FALSE
  432. fi
  433. # get data from image magick
  434. local identify="$("$IDBIN" -format '%[fx:w] %[fx:h]BREAKME' "$INFILEPDF" 2>/dev/null)"
  435. if isEmpty "$identify" && isNotAdaptiveMode; then
  436. notAdaptiveFailed "ImageMagicks's Identify returned an empty string!"
  437. elif isEmpty "$identify" && isAdaptiveMode; then
  438. return $FALSE
  439. fi
  440. identify="${identify%%BREAKME*}" # get page size only for 1st page
  441. identify=($identify) # make it an array
  442. PGWIDTH=$(printf '%.0f' "${identify[0]}") # assign
  443. PGHEIGHT=$(printf '%.0f' "${identify[1]}") # assign
  444. return $TRUE
  445. }
  446. # Gets page size using Mac Quarts mdls
  447. getPageSizeMdls() {
  448. # Sanity and Adaptive together
  449. if notIsFile "$MDLSBIN" && isNotAdaptiveMode; then
  450. notAdaptiveFailed "Are you even trying this on a Mac?" "Mac Quartz mdls"
  451. elif notIsFile "$MDLSBIN" && isAdaptiveMode; then
  452. return $FALSE
  453. fi
  454. local identify="$("$MDLSBIN" -mdls -name kMDItemPageHeight -name kMDItemPageWidth "$INFILEPDF" 2>/dev/null)"
  455. if isEmpty "$identify" && isNotAdaptiveMode; then
  456. notAdaptiveFailed "Mac Quartz mdls returned an empty string!"
  457. elif isEmpty "$identify" && isAdaptiveMode; then
  458. return $FALSE
  459. fi
  460. identify=${identify//$'\t'/ } # change tab to space
  461. identify=($identify) # make it an array
  462. if [[ "${identify[5]}" = "(null)" || "${identify[2]}" = "(null)" ]] && isNotAdaptiveMode; then
  463. notAdaptiveFailed "There was no metadata to read from the file! Is Spotlight OFF?"
  464. elif [[ "${identify[5]}" = "(null)" || "${identify[2]}" = "(null)" ]] && isAdaptiveMode; then
  465. return $FALSE
  466. fi
  467. PGWIDTH=$(printf '%.0f' "${identify[5]}") # assign
  468. PGHEIGHT=$(printf '%.0f' "${identify[2]}") # assign
  469. return $TRUE
  470. }
  471. # Gets page size using Linux PdfInfo
  472. getPageSizePdfInfo() {
  473. # Sanity and Adaptive together
  474. if notIsFile "$PDFINFOBIN" && isNotAdaptiveMode; then
  475. notAdaptiveFailed "Do you have pdfinfo installed and available on your \$PATH?" "Linux pdfinfo"
  476. elif notIsFile "$PDFINFOBIN" && isAdaptiveMode; then
  477. return $FALSE
  478. fi
  479. # get data from image magick
  480. local identify="$("$PDFINFOBIN" "$INFILEPDF" 2>/dev/null | "$GREPBIN" -i 'Page size:' )"
  481. if isEmpty "$identify" && isNotAdaptiveMode; then
  482. notAdaptiveFailed "Linux PdfInfo returned an empty string!"
  483. elif isEmpty "$identify" && isAdaptiveMode; then
  484. return $FALSE
  485. fi
  486. identify="${identify##*Page size:}" # remove stuff
  487. identify=($identify) # make it an array
  488. PGWIDTH=$(printf '%.0f' "${identify[0]}") # assign
  489. PGHEIGHT=$(printf '%.0f' "${identify[2]}") # assign
  490. return $TRUE
  491. }
  492. # Gets page size using cat and grep
  493. getPageSizeCatGrep() {
  494. # get MediaBox info from PDF file using cat and grep, these are all possible
  495. # /MediaBox [0 0 595 841]
  496. # /MediaBox [ 0 0 595.28 841.89]
  497. # /MediaBox[ 0 0 595.28 841.89 ]
  498. # Get MediaBox data if possible
  499. #local mediaBox="$(cat "$INFILEPDF" | "$GREPBIN" -a '/MediaBox' | "$HEADBIN" -n1)"
  500. #local mediaBox="$("$GREPBIN" -a -e '/MediaBox' "$INFILEPDF" | "$HEADBIN" -n1)"
  501. local mediaBox="$("$GREPBIN" -a -e '/MediaBox' "$INFILEPDF" 2>/dev/null)"$'\n\n'
  502. while read l; do
  503. mediaBox="$l"
  504. break
  505. done <<< "$mediaBox"
  506. mediaBox="${mediaBox##*/MediaBox}"
  507. # No page size data available
  508. if isEmpty "$mediaBox" && isNotAdaptiveMode; then
  509. notAdaptiveFailed "There is no MediaBox in the pdf document!"
  510. elif isEmpty "$mediaBox" && isAdaptiveMode; then
  511. return $FALSE
  512. fi
  513. # remove chars [ and ]
  514. mediaBox="${mediaBox//[}"
  515. mediaBox="${mediaBox//]}"
  516. mediaBox=($mediaBox) # make it an array
  517. mbCount=${#mediaBox[@]} # array size
  518. # sanity
  519. if [[ $mbCount -lt 4 ]]; then
  520. printError "Error when reading the page size!"
  521. printError "The page size information is invalid!"
  522. exit $EXIT_INVALID_PAGE_SIZE_DETECTED
  523. fi
  524. # we are done
  525. PGWIDTH=$(printf '%.0f' "${mediaBox[2]}") # Get Round Width
  526. PGHEIGHT=$(printf '%.0f' "${mediaBox[3]}") # Get Round Height
  527. return $TRUE
  528. }
  529. # Prints error message and exits execution
  530. notAdaptiveFailed() {
  531. local errProgram="$2"
  532. local errStr="$1"
  533. if isEmpty "$2"; then
  534. printError "Error when reading input file!"
  535. printError "Could not determine the page size!"
  536. else
  537. printError "Error! $2 was not found!"
  538. fi
  539. isNotEmpty "$errStr" && printError "$errStr"
  540. printError "Aborting! You may want to try the adaptive mode."
  541. exit $EXIT_INVALID_PAGE_SIZE_DETECTED
  542. }
  543. # Verbose print of the Width and Height (Source or New) to screen
  544. vPrintPageSizes() {
  545. vprint " $1 Width: $PGWIDTH postscript-points"
  546. vprint "$1 Height: $PGHEIGHT postscript-points"
  547. }
  548. #################### GHOSTSCRIPT PAPER INFO ####################
  549. # Loads GS paper info to memory
  550. getPaperInfo() {
  551. # name inchesW inchesH mmW mmH pointsW pointsH
  552. sizesUS="\
  553. 11x17 11.0 17.0 279 432 792 1224
  554. ledger 17.0 11.0 432 279 1224 792
  555. legal 8.5 14.0 216 356 612 1008
  556. letter 8.5 11.0 216 279 612 792
  557. lettersmall 8.5 11.0 216 279 612 792
  558. archE 36.0 48.0 914 1219 2592 3456
  559. archD 24.0 36.0 610 914 1728 2592
  560. archC 18.0 24.0 457 610 1296 1728
  561. archB 12.0 18.0 305 457 864 1296
  562. archA 9.0 12.0 229 305 648 864"
  563. sizesISO="\
  564. a0 33.1 46.8 841 1189 2384 3370
  565. a1 23.4 33.1 594 841 1684 2384
  566. a2 16.5 23.4 420 594 1191 1684
  567. a3 11.7 16.5 297 420 842 1191
  568. a4 8.3 11.7 210 297 595 842
  569. a4small 8.3 11.7 210 297 595 842
  570. a5 5.8 8.3 148 210 420 595
  571. a6 4.1 5.8 105 148 297 420
  572. a7 2.9 4.1 74 105 210 297
  573. a8 2.1 2.9 52 74 148 210
  574. a9 1.5 2.1 37 52 105 148
  575. a10 1.0 1.5 26 37 73 105
  576. isob0 39.4 55.7 1000 1414 2835 4008
  577. isob1 27.8 39.4 707 1000 2004 2835
  578. isob2 19.7 27.8 500 707 1417 2004
  579. isob3 13.9 19.7 353 500 1001 1417
  580. isob4 9.8 13.9 250 353 709 1001
  581. isob5 6.9 9.8 176 250 499 709
  582. isob6 4.9 6.9 125 176 354 499
  583. c0 36.1 51.1 917 1297 2599 3677
  584. c1 25.5 36.1 648 917 1837 2599
  585. c2 18.0 25.5 458 648 1298 1837
  586. c3 12.8 18.0 324 458 918 1298
  587. c4 9.0 12.8 229 324 649 918
  588. c5 6.4 9.0 162 229 459 649
  589. c6 4.5 6.4 114 162 323 459"
  590. sizesJIS="\
  591. jisb0 NA NA 1030 1456 2920 4127
  592. jisb1 NA NA 728 1030 2064 2920
  593. jisb2 NA NA 515 728 1460 2064
  594. jisb3 NA NA 364 515 1032 1460
  595. jisb4 NA NA 257 364 729 1032
  596. jisb5 NA NA 182 257 516 729
  597. jisb6 NA NA 128 182 363 516"
  598. sizesOther="\
  599. flsa 8.5 13.0 216 330 612 936
  600. flse 8.5 13.0 216 330 612 936
  601. halfletter 5.5 8.5 140 216 396 612
  602. hagaki 3.9 5.8 100 148 283 420"
  603. sizesAll="\
  604. $sizesUS
  605. $sizesISO
  606. $sizesJIS
  607. $sizesOther"
  608. }
  609. # Gets a paper size in points and sets it to RESIZE_WIDTH and RESIZE_HEIGHT
  610. getGSPaperSize() {
  611. isEmpty "$sizesall" && getPaperInfo
  612. while read l; do
  613. local cols=($l)
  614. if [[ "$1" == ${cols[0]} ]]; then
  615. RESIZE_WIDTH=${cols[5]}
  616. RESIZE_HEIGHT=${cols[6]}
  617. return $TRUE
  618. fi
  619. done <<< "$sizesAll"
  620. }
  621. # Gets a paper size in points and sets it to RESIZE_WIDTH and RESIZE_HEIGHT
  622. getGSPaperName() {
  623. local w="$(printf "%.0f" $1)"
  624. local h="$(printf "%.0f" $2)"
  625. isEmpty "$sizesall" && getPaperInfo
  626. # Because US Standard has inverted sizes, I need to scan 2 times
  627. # instead of just testing if width is bigger than height
  628. while read l; do
  629. local cols=($l)
  630. if [[ "$w" == ${cols[5]} && "$h" == ${cols[6]} ]]; then
  631. printf "%s Portrait" $(uppercase ${cols[0]})
  632. return $TRUE
  633. fi
  634. done <<< "$sizesAll"
  635. while read l; do
  636. local cols=($l)
  637. if [[ "$w" == ${cols[6]} && "$h" == ${cols[5]} ]]; then
  638. printf "%s Landscape" $(uppercase ${cols[0]})
  639. return $TRUE
  640. fi
  641. done <<< "$sizesAll"
  642. return $FALSE
  643. }
  644. # Loads an array with paper names to memory
  645. getPaperNames() {
  646. paperNames=(a0 a1 a2 a3 a4 a4small a5 a6 a7 a8 a9 a10 isob0 isob1 isob2 isob3 isob4 isob5 isob6 c0 c1 c2 c3 c4 c5 c6 \
  647. 11x17 ledger legal letter lettersmall archE archD archC archB archA \
  648. jisb0 jisb1 jisb2 jisb3 jisb4 jisb5 jisb6 \
  649. flsa flse halfletter hagaki)
  650. }
  651. # Prints uppercase paper names to screen (used in help)
  652. printPaperNames() {
  653. isEmpty "$paperNames" && getPaperNames
  654. for i in "${!paperNames[@]}"; do
  655. [[ $i -eq 0 ]] && echo -n -e ' '
  656. [[ $i -ne 0 && $((i % 5)) -eq 0 ]] && echo -n -e $'\n '
  657. ppN="$(uppercase ${paperNames[i]})"
  658. printf "%-14s" "$ppN"
  659. done
  660. echo ""
  661. }
  662. # Returns $TRUE if $! is a valid paper name, $FALSE otherwise
  663. isPaperName() {
  664. isEmpty "$1" && return $FALSE
  665. isEmpty "$paperNames" && getPaperNames
  666. for i in "${paperNames[@]}"; do
  667. [[ "$i" = "$1" ]] && return $TRUE
  668. done
  669. return $FALSE
  670. }
  671. # Prints all tables with ghostscript paper information
  672. printPaperInfo() {
  673. printVersion
  674. echo $'\n'"Valid Ghostscript Paper Sizes accepted"$'\n'
  675. getPaperInfo
  676. printPaperTable "ISO STANDARD" "$sizesISO"; echo
  677. printPaperTable "US STANDARD" "$sizesUS"; echo
  678. printPaperTable "JIS STANDARD *Aproximated Points" "$sizesJIS"; echo
  679. printPaperTable "OTHERS" "$sizesOther"; echo
  680. }
  681. # GS paper table helper, prints a full line
  682. printTableLine() {
  683. echo '+-----------------------------------------------------------------+'
  684. }
  685. # GS paper table helper, prints a line with dividers
  686. printTableDivider() {
  687. echo '+-----------------+-------+-------+-------+-------+-------+-------+'
  688. }
  689. # GS paper table helper, prints a table header
  690. printTableHeader() {
  691. echo '| Name | inchW | inchH | mm W | mm H | pts W | pts H |'
  692. }
  693. # GS paper table helper, prints a table title
  694. printTableTitle() {
  695. printf "| %-64s%s\n" "$1" '|'
  696. }
  697. # GS paper table printer, prints a table for a paper variable
  698. printPaperTable() {
  699. printTableLine
  700. printTableTitle "$1"
  701. printTableLine
  702. printTableHeader
  703. printTableDivider
  704. while read l; do
  705. local cols=($l)
  706. printf "| %-15s | %+5s | %+5s | %+5s | %+5s | %+5s | %+5s |\n" ${cols[*]};
  707. done <<< "$2"
  708. printTableDivider
  709. }
  710. # Validades the a paper resize CLI option and sets the paper to $RESIZE_PAPER_TYPE
  711. parsePaperResize() {
  712. isEmpty "$1" && initError 'Invalid Paper Type: (empty)' $EXIT_INVALID_PAPER_SIZE
  713. local lowercasePaper="$(lowercase $1)"
  714. if [[ "$1" = 'custom' ]]; then
  715. if isNotValidMeasure "$2" || ! isFloatBiggerThanZero "$3" || ! isFloatBiggerThanZero "$4"; then
  716. initError "Invalid Custom Paper Definition!"$'\n'"Use: -r 'custom <measurement> <width> <height>'"$'\n'"Measurements: mm, in, pts" $EXIT_INVALID_OPTION
  717. fi
  718. RESIZE_PAPER_TYPE="custom"
  719. CUSTOM_RESIZE_PAPER=$TRUE
  720. if isMilimeter "$2"; then
  721. RESIZE_WIDTH="$(milimetersToPoints "$3")"
  722. RESIZE_HEIGHT="$(milimetersToPoints "$4")"
  723. elif isInch "$2"; then
  724. RESIZE_WIDTH="$(inchesToPoints "$3")"
  725. RESIZE_HEIGHT="$(inchesToPoints "$4")"
  726. elif isPoint "$2"; then
  727. RESIZE_WIDTH="$3"
  728. RESIZE_HEIGHT="$4"
  729. else
  730. initError "Invalid Custom Paper Definition!"$'\n'"Use: -r 'custom <measurement> <width> <height>'"$'\n'"Measurements: mm, in, pts" $EXIT_INVALID_OPTION
  731. fi
  732. else
  733. isPaperName "$lowercasePaper" || initError "Invalid Paper Type: $1" $EXIT_INVALID_PAPER_SIZE
  734. RESIZE_PAPER_TYPE="$lowercasePaper"
  735. fi
  736. }
  737. # Returns $TRUE if $1 is a valid measurement for a custom paper, $FALSE otherwise
  738. isNotValidMeasure() {
  739. isMilimeter "$1" || isInch "$1" || isPoint "$1" && return $FALSE
  740. return $TRUE
  741. }
  742. # Returns $TRUE if $1 is a valid milimeter string, $FALSE otherwise
  743. isMilimeter() {
  744. [[ "$1" = 'mm' || "$1" = 'milimeters' || "$1" = 'milimeter' ]] && return $TRUE
  745. return $FALSE
  746. }
  747. # Returns $TRUE if $1 is a valid inch string, $FALSE otherwise
  748. isInch() {
  749. [[ "$1" = 'in' || "$1" = 'inch' || "$1" = 'inches' ]] && return $TRUE
  750. return $FALSE
  751. }
  752. # Returns $TRUE if $1 is a valid point string, $FALSE otherwise
  753. isPoint() {
  754. [[ "$1" = 'pt' || "$1" = 'pts' || "$1" = 'point' || "$1" = 'points' ]] && return $TRUE
  755. return $FALSE
  756. }
  757. # Returns $TRUE if a custom paper is being used, $FALSE otherwise
  758. isCustomPaper() {
  759. return $CUSTOM_RESIZE_PAPER
  760. }
  761. isNotCustomPaper() {
  762. isCustomPaper && return $FALSE
  763. return $TRUE
  764. }
  765. # Returns $TRUE if the scale was set manually, $FALSE if we are using automatic scaling
  766. isManualScaledMode() {
  767. [[ $AUTOMATIC_SCALING -eq $TRUE ]] && return $FALSE
  768. return $TRUE
  769. }
  770. # Returns true if we are resizing a paper (ignores scaling), false otherwise
  771. isResizeMode() {
  772. isEmpty $RESIZE_PAPER_TYPE && return $FALSE
  773. return $TRUE
  774. }
  775. # Returns true if we are resizing a paper and the scale was manually set
  776. isMixedMode() {
  777. isResizeMode && isManualScaledMode && return $TRUE
  778. return $FALSE
  779. }
  780. # Prints the lowercase char value for $1
  781. lowercaseChar() {
  782. case "$1" in
  783. [A-Z])
  784. n=$(printf "%d" "'$1")
  785. n=$((n+32))
  786. printf \\$(printf "%o" "$n")
  787. ;;
  788. *)
  789. printf "%s" "$1"
  790. ;;
  791. esac
  792. }
  793. # Prints the lowercase version of a string
  794. lowercase() {
  795. word="$@"
  796. for((i=0;i<${#word};i++))
  797. do
  798. ch="${word:$i:1}"
  799. lowercaseChar "$ch"
  800. done
  801. }
  802. # Prints the uppercase char value for $1
  803. uppercaseChar(){
  804. case "$1" in
  805. [a-z])
  806. n=$(printf "%d" "'$1")
  807. n=$((n-32))
  808. printf \\$(printf "%o" "$n")
  809. ;;
  810. *)
  811. printf "%s" "$1"
  812. ;;
  813. esac
  814. }
  815. # Prints the uppercase version of a string
  816. uppercase() {
  817. word="$@"
  818. for((i=0;i<${#word};i++))
  819. do
  820. ch="${word:$i:1}"
  821. uppercaseChar "$ch"
  822. done
  823. }
  824. # Prints the postscript points rounded equivalent from $1 mm
  825. milimetersToPoints() {
  826. local pts=$(echo "scale=8; $1 * 72 / 25.4" | "$BCBIN")
  827. printf '%.0f' "$pts" # Print rounded conversion
  828. }
  829. # Prints the postscript points rounded equivalent from $1 inches
  830. inchesToPoints() {
  831. local pts=$(echo "scale=8; $1 * 72" | "$BCBIN")
  832. printf '%.0f' "$pts" # Print rounded conversion
  833. }
  834. # Prints the mm equivalent from $1 postscript points
  835. pointsToMilimeters() {
  836. local pts=$(echo "scale=8; $1 / 72 * 25.4" | "$BCBIN")
  837. printf '%.0f' "$pts" # Print rounded conversion
  838. }
  839. # Prints the inches equivalent from $1 postscript points
  840. pointsToInches() {
  841. local pts=$(echo "scale=8; $1 / 72" | "$BCBIN")
  842. printf '%.2f' "$pts" # Print rounded conversion
  843. }
  844. ########################## VALIDATORS ##########################
  845. # Returns $TRUE if $PGWIDTH OR $PGWIDTH are empty or NOT an Integer, $FALSE otherwise
  846. pageSizeIsInvalid() {
  847. if isNotAnInteger "$PGWIDTH" || isNotAnInteger "$PGHEIGHT"; then
  848. return $TRUE
  849. fi
  850. return $FALSE
  851. }
  852. # Return $TRUE if adaptive mode is enabled, $FALSE otherwise
  853. isAdaptiveMode() {
  854. return $ADAPTIVEMODE
  855. }
  856. # Return $TRUE if adaptive mode is disabled, $FALSE otherwise
  857. isNotAdaptiveMode() {
  858. isAdaptiveMode && return $FALSE
  859. return $TRUE
  860. }
  861. # Return $TRUE if $1 is empty, $FALSE otherwise
  862. isEmpty() {
  863. [[ -z "$1" ]] && return $TRUE
  864. return $FALSE
  865. }
  866. # Return $TRUE if $1 is NOT empty, $FALSE otherwise
  867. isNotEmpty() {
  868. [[ -z "$1" ]] && return $FALSE
  869. return $TRUE
  870. }
  871. # Returns $TRUE if $1 is an integer, $FALSE otherwise
  872. isAnInteger() {
  873. case $1 in
  874. ''|*[!0-9]*) return $FALSE ;;
  875. *) return $TRUE ;;
  876. esac
  877. }
  878. # Returns $TRUE if $1 is NOT an integer, $FALSE otherwise
  879. isNotAnInteger() {
  880. case $1 in
  881. ''|*[!0-9]*) return $TRUE ;;
  882. *) return $FALSE ;;
  883. esac
  884. }
  885. # Returns $TRUE if $1 is a floating point number (or an integer), $FALSE otherwise
  886. isFloat() {
  887. [[ -n "$1" && "$1" =~ ^-?[0-9]*([.][0-9]+)?$ ]] && return $TRUE
  888. return $FALSE
  889. }
  890. # Returns $TRUE if $1 is a floating point number bigger than zero, $FALSE otherwise
  891. isFloatBiggerThanZero() {
  892. isFloat "$1" && [[ (( $1 > 0 )) ]] && return $TRUE
  893. return $FALSE
  894. }
  895. # Returns $TRUE if $1 has a .pdf extension, false otherwsie
  896. isPDF() {
  897. [[ "$1" =~ ^..*\.pdf$ ]] && return $TRUE
  898. return $FALSE
  899. }
  900. # Returns $TRUE if $1 is a file, false otherwsie
  901. isFile() {
  902. [[ -f "$1" ]] && return $TRUE
  903. return $FALSE
  904. }
  905. # Returns $TRUE if $1 is NOT a file, false otherwsie
  906. notIsFile() {
  907. [[ -f "$1" ]] && return $FALSE
  908. return $TRUE
  909. }
  910. # Returns $TRUE if $1 is executable, false otherwsie
  911. isExecutable() {
  912. [[ -x "$1" ]] && return $TRUE
  913. return $FALSE
  914. }
  915. # Returns $TRUE if $1 is NOT executable, false otherwsie
  916. notIsExecutable() {
  917. [[ -x "$1" ]] && return $FALSE
  918. return $TRUE
  919. }
  920. # Returns $TRUE if $1 is a file and executable, false otherwsie
  921. isAvailable() {
  922. if isFile "$1" && isExecutable "$1"; then
  923. return $TRUE
  924. fi
  925. return $FALSE
  926. }
  927. # Returns $TRUE if $1 is NOT a file or NOT executable, false otherwsie
  928. notIsAvailable() {
  929. if notIsFile "$1" || notIsExecutable "$1"; then
  930. return $TRUE
  931. fi
  932. return $FALSE
  933. }
  934. ###################### PRINTING TO SCREEN ######################
  935. # Prints version
  936. printVersion() {
  937. local vStr=""
  938. [[ "$2" = 'verbose' ]] && vStr=" - Verbose Execution"
  939. local strBanner="$PDFSCALE_NAME v$VERSION$vStr"
  940. if [[ $1 -eq 2 ]]; then
  941. printError "$strBanner"
  942. elif [[ $1 -eq 3 ]]; then
  943. local extra="$(isNotEmpty "$2" && echo "$2")"
  944. echo "$strBanner$extra"
  945. else
  946. vprint "$strBanner"
  947. fi
  948. }
  949. # Prints the scale factor to screen, or custom message
  950. vPrintScaleFactor() {
  951. local scaleMsg="$SCALE"
  952. isNotEmpty "$1" && scaleMsg="$1"
  953. vprint " Scale Factor: $scaleMsg"
  954. }
  955. # Prints help info
  956. printHelp() {
  957. printVersion 3
  958. local paperList="$(printPaperNames)"
  959. echo "
  960. Usage: $PDFSCALE_NAME <inFile.pdf>
  961. $PDFSCALE_NAME -i <inFile.pdf>
  962. $PDFSCALE_NAME [-v] [-s <factor>] [-m <page-detection>] <inFile.pdf> [outfile.pdf]
  963. $PDFSCALE_NAME [-v] [-r <paper>] [-f <flip-detection>] [-a <auto-rotation>] <inFile.pdf> [outfile.pdf]
  964. $PDFSCALE_NAME -p
  965. $PDFSCALE_NAME -h
  966. $PDFSCALE_NAME -V
  967. Parameters:
  968. -v Verbose mode, prints extra information
  969. Use twice for timestamp
  970. -h Print this help to screen and exits
  971. -V Prints version to screen and exits
  972. -m <mode> Page size Detection mode
  973. May disable the Adaptive Mode
  974. -i <file> Prints <file> Page Size information to screen and exits
  975. -s <factor> Changes the scaling factor or forces scaling
  976. Defaults: $SCALE / no scaling (resize mode)
  977. MUST be a number bigger than zero
  978. Eg. -s 0.8 for 80% of the original size
  979. -r <paper> Triggers the Resize Paper Mode
  980. Resize PDF paper proportionally
  981. Uses a valid paper name or a custom defined paper
  982. -f <mode> Flip Detection Mode, defaults to 'auto'.
  983. Inverts Width <-> Height of a Resized PDF.
  984. Modes: a, auto - automatic detection, default
  985. f, force - forces flip W <-> H
  986. d, disable - disables flipping
  987. -a <mode> GS Auto-Rotation Setting, defaults to 'PageByPage'.
  988. Setting for GS -dAutoRotatePages.
  989. Modes: p, pagebypage - auto-rotates pages individually
  990. a, all - rotates all pages (or none) depending
  991. on a kind of \"majority decision\"
  992. n, none - retains orientation of each page
  993. -p Prints Ghostscript paper info tables to screen
  994. Scaling Mode:
  995. The default mode of operation is scaling mode with fixed paper
  996. size and scaling pre-set to $SCALE. By not using the resize mode
  997. you are using scaling mode. Flip-Detection and Auto-Rotation are
  998. disabled in Scaling mode.
  999. Resize Paper Mode:
  1000. Disables the default scaling factor! ($SCALE)
  1001. Changes the PDF Paper Size in points. Will fit-to-page.
  1002. Mixed Mode:
  1003. In mixed mode both the -s option and -r option must be specified.
  1004. The PDF will be first resized then scaled.
  1005. Output filename:
  1006. The output filename is optional. If no file name is passed
  1007. the output file will have the same name/destination of the
  1008. input file with added suffixes:
  1009. .SCALED.pdf is added to scaled files
  1010. .<PAPERSIZE>.pdf is added to resized files
  1011. .<PAPERSIZE>.SCALED.pdf is added in mixed mode
  1012. Page Size Detection Modes:
  1013. a, adaptive Default mode, tries all the methods below
  1014. g, grep Forces the use of grep method
  1015. m, mdls Forces the use of MacOS Quartz mdls
  1016. p, pdfinfo Forces the use of PDFInfo
  1017. i, identify Forces the use of ImageMagick's Identify
  1018. Valid Paper Names: (case-insensitive)
  1019. $paperList
  1020. Custom Paper Size:
  1021. Paper size can be set manually in Milimeters, Inches or Points.
  1022. Use: $PDFSCALE_NAME -r 'custom <measurement> <width> <height>'
  1023. Ex: $PDFSCALE_NAME -r 'custom mm 300 300'
  1024. Measurements can be: mm, inch, pts.
  1025. Custom paper definition MUST be quoted into a single parameter.
  1026. Actual size is applied in points (mms and inches are transformed).
  1027. Additional Notes:
  1028. - Adaptive Page size detection will try different modes until
  1029. it gets a page size. You can force a mode with -m 'mode'.
  1030. - Options must be passed before the file names to be parsed.
  1031. - Having the extension .pdf on the output file name is optional,
  1032. it will be added if not present.
  1033. - File and folder names with spaces should be quoted or escaped.
  1034. - The scaling is centered and using a scale bigger than 1 may
  1035. result on cropping parts of the pdf.
  1036. - Most of the options are case-insensitive, Ex: -m PdFinFo
  1037. Examples:
  1038. $PDFSCALE_NAME myPdfFile.pdf
  1039. $PDFSCALE_NAME -i '/home/My Folder/My PDF File.pdf'
  1040. $PDFSCALE_NAME myPdfFile.pdf \"My Scaled Pdf\"
  1041. $PDFSCALE_NAME -v -v myPdfFile.pdf
  1042. $PDFSCALE_NAME -s 0.85 myPdfFile.pdf My\\ Scaled\\ Pdf.pdf
  1043. $PDFSCALE_NAME -m pdfinfo -s 0.80 -v myPdfFile.pdf
  1044. $PDFSCALE_NAME -v -v -m i -s 0.7 myPdfFile.pdf
  1045. $PDFSCALE_NAME -r A4 myPdfFile.pdf
  1046. $PDFSCALE_NAME -v -v -r \"custom mm 252 356\" -s 0.9 -f \"../input file.pdf\" \"../my new pdf\"
  1047. "
  1048. }
  1049. # Prints usage info
  1050. usage() {
  1051. [[ "$2" != 'nobanner' ]] && printVersion 2
  1052. isNotEmpty "$1" && printError "$1"
  1053. printError "Usage: $PDFSCALE_NAME [-v] [-s <factor>] [-m <mode>] <inFile.pdf> [outfile.pdf]"
  1054. printError "Try: $PDFSCALE_NAME -h # for help"
  1055. }
  1056. # Prints Verbose information
  1057. vprint() {
  1058. [[ $VERBOSE -eq 0 ]] && return $TRUE
  1059. timestamp=""
  1060. [[ $VERBOSE -gt 1 ]] && timestamp="$(date +%Y-%m-%d:%H:%M:%S) | "
  1061. echo "$timestamp$1"
  1062. }
  1063. # Prints dependency information and aborts execution
  1064. printDependency() {
  1065. #printVersion 2
  1066. local brewName="$1"
  1067. [[ "$1" = 'pdfinfo' && "$OSNAME" = "Darwin" ]] && brewName="xpdf"
  1068. printError $'\n'"ERROR! You need to install the package '$1'"$'\n'
  1069. printError "Linux apt-get.: sudo apt-get install $1"
  1070. printError "Linux yum.....: sudo yum install $1"
  1071. printError "MacOS homebrew: brew install $brewName"
  1072. printError $'\n'"Aborting..."
  1073. exit $EXIT_MISSING_DEPENDENCY
  1074. }
  1075. # Prints initialization errors and aborts execution
  1076. initError() {
  1077. local errStr="$1"
  1078. local exitStat=$2
  1079. isEmpty "$exitStat" && exitStat=$EXIT_ERROR
  1080. usage "ERROR! $errStr" "$3"
  1081. exit $exitStat
  1082. }
  1083. # Prints to stderr
  1084. printError() {
  1085. echo >&2 "$@"
  1086. }
  1087. ########################## EXECUTION ###########################
  1088. initDeps
  1089. getOptions "${@}"
  1090. main
  1091. exit $?