Bash Script to scale and/or resize PDFs from the command line.
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

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