Bilder in PDF konvertieren: So stellen Sie sicher, dass PDF-Seiten dieselbe Größe haben

45

Ich habe so etwas gemacht

convert -page A4 -compress A4 *.png CH00.pdf

Die erste Seite ist jedoch viel größer als die nachfolgenden Seiten. Dies geschieht, obwohl die Bildabmessungen ähnlich sind. Diese Bilder werden gescannt und beschnitten, daher kann es zu geringfügigen Dimensionsunterschieden kommen

Ich dachte, -page A4sollte die Größe der Seiten reparieren?

Jiew Meng
quelle

Antworten:

60

Als ich das letzte Mal converteine solche Aufgabe ausgeführt habe, habe ich die Größe des Ziels explizit über die Größenänderung angegeben:

$ i=150; convert a.png b.png -compress jpeg -quality 70 \
      -density ${i}x${i} -units PixelsPerInch \
      -resize $((i*827/100))x$((i*1169/100)) \
      -repage $((i*827/100))x$((i*1169/100)) multipage.pdf

Der convertBefehl verwendet nicht immer DPI als Standardeinheit für Dichte / Seitenformat, daher geben wir DPI explizit mit der -unitsOption an (andernfalls erhalten Sie möglicherweise unterschiedliche Ergebnisse mit unterschiedlichen Versionen / Eingabeformatkombinationen). Die neue Größe (angegeben über -resize) ist die Abmessung einer DIN A4-Seite in Pixel. Das Argument resize gibt die maximale Seitengröße an. Welche Auflösung und Qualität genau ausgewählt werden muss, hängt vom Anwendungsfall ab. Ich habe 150 DPI und eine durchschnittliche Qualität ausgewählt, um Platz zu sparen, während es beim Drucken auf Papier nicht allzu schlecht aussieht.

Beachten Sie, dass convertdas Seitenverhältnis bei der Größenänderung standardmäßig nicht geändert wird:

Größe ändern passt das Bild in die gewünschte Größe. Es wird NICHT die gewünschte Kartongröße gefüllt.

( ImageMagick Handbuch )

Abhängig von der ImageMagick-Version und den beteiligten Eingabeformaten ist es möglicherweise in Ordnung, die -repageOption wegzulassen . Manchmal ist dies jedoch erforderlich, und ohne diese Option enthält der PDF-Header möglicherweise zu kleine Abmessungen. Auf jeden Fall -repagesollte das nicht schaden.

Die Berechnungen verwenden Integer-Arithmetik, da dies bashnur unterstützt wird. Mit können zshdie Ausdrücke vereinfacht - dh durch ersetzt werden $((i*8.27))x$((i*11.69)).

Lineart Images

Wenn es sich bei den PNG-Dateien um Bilder mit zwei Ebenen (Schwarzweiß oder Lineart) handelt img2pdf, liefert das Tool bessere Ergebnisse als ImageMagick convert. Das heißt, es img2pdfist schneller und liefert kleinere PDFs.

Beispiel:

$ img2pdf -o multipage.pdf a.png b.png

oder:

$ img2pdf --pagesize A4 -o multipage.pdf a.png b.png
maxschlepzig
quelle
2
wenn -repage a4ich es benutze bekomme ich eineninvalid argument for option '-repage': a4
Scolytus
1
@Scolytus, auf einem Fedora 19-System habe ich ein ähnliches Problem festgestellt - es scheint, dass -repageder a4-Name nicht mehr unterstützt wird. Ich habe das durch Shell-Arithmetik -repage $((150*8.27))x$((150*11.69))
umgangen
Ich gehe davon aus, dass diese magischen Zahlen 150 dpi und A4 in Legacy-Einheiten ausgedrückt sind.
Michael Scheper
@ MichaelScheper, ja, dpi und Zoll.
Maxschlepzig
Danke, hilf mir. Eigentlich war das -density 150Argument wichtig hinzuzufügen.
dma_k
23

Was Sie wirklich verwenden möchten, ist:

$ convert a.png b.png -compress jpeg -resize 1240x1753 \
                      -extent 1240x1753 -gravity center \
                      -units PixelsPerInch -density 150x150 multipage.pdf

-extentErweitert das Bild tatsächlich auf 1240 x 1753, -resizebehält dabei das Bildverhältnis bei und passt es entweder an 1240x...oder an ...x1753.

Der -gravityParameter ist optional, kann jedoch verwendet werden, um das Bild beim Erweitern zu zentrieren.

Kaugner
quelle
1
Danke! -extentist wirklich das, was ich verwenden möchte :) - bitte fügen Sie ein verpasstes linkes Zitat vor -extent hinzu, danke!
Brownian
Danke, ich habe irgendwann das fehlende Häkchen hinzugefügt! ;-)
caugner
9

Ergänzung zu Caugners Antwort :

nachdem installiert IM v6.6.9-7 ich die herausgefunden -gravityParameter Bedarf platziert werden zwischendurch -resizeund -extenteinen Effekt zu haben.

zusätzlich (obwohl nicht in der op-frage enthalten) fand ich die einstellung einer anderen hintergrundfarbe ansprechend, was zu dem totalen befehl von führen würde

convert in.jpg -resize 1240x1750 -background black -compose Copy\
               -gravity center -extent 1240x1750\
               -units PixelsPerInch -density 150 out.pdf

eine weitere nützliche variante, die ich oft verwende, wenn ich ein bild, das bereits im richtigen seitenverhältnis vorliegt, aber seine individuelle auflösung beibehält, nicht neu skalieren möchte

convert in.jpg -units PixelsPerInch -set density '%[fx:w/8.27]'\
               -repage a4 out.pdf

wobei die Zieldichte dynamisch durch Berechnen der Breite geteilt durch 8,27 (das ist die Breite in Zoll einer A4-Seite) bestimmt wird. Der -repage a4Parameter kann die meiste Zeit weggelassen werden, aber ich hatte ein paar Fälle, in denen die resultierende PDF-Datei ein anderes Format hatte als die A4-Abmessungen von 210 x 297 mm (8,27 x 11,6 ").

antiplex
quelle
2

Ich fand Mikhers Code sehr nützlich, aber er legt die PDF-Datei vollständig als Hochformat oder Querformat aus. Deshalb habe ich sie so geändert, dass sie das Layout jeder Eingabedatei überprüft und mit der Ausgabe übereinstimmt.

Ich habe die Bearbeitung von Yotam nicht berücksichtigt, da sie auf meiner Ubuntu 15.04-Box ohne funktioniert.

$#!/bin/bash

# Resizes files to A4 (or other size - change PaperWdthMetr and PaperHghtMetr below) and merges into a PDF

export LOCALE=C

[[ "${2}x" == "x" ]] && \
 { echo "Usage: $( basename $0 ) output.pdf extension"
   echo "       merges all files (*.extension) into a single PDF"
   echo "If files z_merged.pdf, z_temp.pdf or $1 exist, they will be overwritten"
 exit 1
 } || \
 OutName="$1"
 ext="$2"

# Set basic variables
unset Debug #; Debug="yes" # print extra messages
IMBackground="white"      # what colour for paper
IMQuality="91"            # JPEG compression level
PaperHghtMetr="297"       # milimeters, 297 for ISO A4
PaperWdthMetr="210"       # milimeters, 210 for ISO A4
PaperDens="200"           # maximum (wanted) dpi for a page
PaperHInch=$( echo scale=5\; $PaperHghtMetr / 2.54 / 10      | bc -l ) # Inch
PaperWInch=$( echo scale=5\; $PaperWdthMetr / 2.54 / 10      | bc -l ) # Inch
PaperRtio=$(     echo scale=5\; $PaperWdthMetr / $PaperHghtMetr | bc -l )

# Remove temporary files from prior run
rm -rf z_merged.pdf z_temp.pdf 2>/dev/null

# Process any $ext file in the current directory
find . -maxdepth 1 -name "*.${ext}" -print0 | sort -z | while read -d '' -r FName
do
  echo "Converting $FName"
  ImgIdentify=$( identify -format "%w %h" "$FName" )
  ImgWdthOrig=$( echo $ImgIdentify | cut -d" " -f1  )
  ImgHghtOrig=$( echo $ImgIdentify | cut -d" " -f2  )
  ImgRtio=$( echo "scale=5; $ImgWdthOrig / $ImgHghtOrig"  | bc -l )


# Match output page layout - Landscape or Portrait - to input file
  if (( $(echo "$ImgRtio > 1 && $PaperRtio > 1 || $ImgRtio < 1 && $PaperRtio < 1" |bc -l) )); then
    echo "Portrait"
    PaperHghtInch=$PaperHInch
    PaperWdthInch=$PaperWInch
  else
    echo "Landscape"
    PaperHghtInch=$PaperWInch
    PaperWdthInch=$PaperHInch
  fi


  [[ $( echo $ImgRtio'>'$PaperRtio | bc -l ) == 1 ]] \
    && ImgDens=$( echo scale=0\; $ImgWdthOrig / $PaperWdthInch | bc -l ) \
    || ImgDens=$( echo scale=0\; $ImgHghtOrig / $PaperHghtInch | bc -l )
  [[ $Debug ]] && echo "ImgDens1: $ImgDens"
  [[ $( echo $ImgDens'>'$PaperDens | bc -l ) == 1 ]] \
    && ImgDens=$PaperDens
  [[ $Debug ]] && echo "ImgDens2: $ImgDens"

  ImgWdth=$( echo $PaperWdthInch \* $ImgDens | bc -l ) # pixels
  ImgHght=$( echo $PaperHghtInch \* $ImgDens | bc -l ) # pixels

  [[ $Debug ]] && echo "ImgWdth: $ImgWdth".
  [[ $Debug ]] && echo "ImgHght: $ImgHght".

  convert "${FName}"                                 \
          -resize ${ImgWdth}x${ImgHght}              \
          -background $IMBackground -gravity center  \
          -extent ${ImgWdth}x${ImgHght}              \
          -units PixelsPerInch -set density $ImgDens \
          -repage ${ImgWdth}x${ImgHght}+0+0          \
          -compress JPEG                             \
          -quality $IMQuality                        \
          "${FName%.$ext}.pdf"

  # Merge new PDF page with prior pages
  [[ -f z_merged.pdf ]] && \
   { pdftk z_merged.pdf "${FName%.$ext}.pdf" cat output z_temp.pdf
     mv z_temp.pdf z_merged.pdf
   } || \
     cp "${FName%.$ext}.pdf" z_merged.pdf
  [[ $Debug ]] || rm -rf "${FName%.$ext}.pdf"
done

[[ -f z_merged.pdf ]] && mv z_merged.pdf "$OutName"
echo "Done."
user173283
quelle
2

Ich finde das folgende Skript praktisch, das die hier aufgeführten Antworten sowie einige Probleme mit der Gleitkommaberechnung kombiniert:

endInputArgs=$(($#-1))

quoted_args="$(printf " %q" "${@:1:$endInputArgs}")"
output_arg="$(printf " %q" "${@:$#:1}")"

ratiox=$(echo "150*8.27" | bc -l)
ratioy=$(echo "150*11.69" | bc -l)

bash -c "convert $quoted_args -compress jpeg -resize 1240x1753 \
  -units PixelsPerInch -density 150x150 -repage ${ratiox}x${ratioy} $output_arg"

Das Skript wird aufgerufen (als Datei images2pdf gespeichert)

images2pdf file\ 1.jpg file\ 2.jpg file\ 3.jpg output.pdf

/ edit: "-l" -Flag entsprechend dem Kommentar von Tanius hinzugefügt, um die Genauigkeit zu verbessern.

rindPHI
quelle
Allgemeiner Hinweis: $(echo "150*8.27" | bc)eignet sich immer noch nicht für Gleitkommazahlen. Funktioniert hier, weil es eine Multiplikation ist. Denn $(echo "150/8.27" | bc)obwohl, wird das Ergebnis 18(abgeschnitten integer). Rufe stattdessen bcmit höher scale: auf $(echo "150/8.27" | bc -l), das Ergebnis ist 18.137847….
Tanius
1

Ich hatte auch damit zu kämpfen. Basierend auf den obigen Informationen habe ich ein Skript geschrieben, das alphabetisch sortierte Bilddateien zu einer einzelnen PDF-Datei hinzufügt.

Einige Variablen sind innerhalb des Skripts einstellbar. Das hängt von ImageMagick und pdftk ab.

NB: Wenn das Eingabebild eine höhere Auflösung (dpi) als die gewünschte Auflösung von output.pdf hat, wird das Bild auf die niedrigere Auflösung neu abgetastet. Andernfalls wird das Bild nicht erneut abgetastet und nur so erweitert, dass es in den Seitenbereich passt.

#!/bin/bash

export LOCALE=C

[[ "${2}x" == "x" ]] && \
 { echo "Usage: $( basename $0 ) output.pdf extension"
   echo "       merges all files (*.extension) into a single PDF"
   echo "If files z_merged.pdf, z_temp.pdf or $1 exist, they will be overwritten"
 exit 1
 } || \
 OutName="$1"
 ext="$2"

# Set basic variables
unset Debug #; Debug="yes" # print extra messages
IMBackground="white"      # what colour for paper
IMQuality="91"            # JPEG compression level
PaperWdthMetr="210"       # milimeters, 210 for ISO A4
PaperHghtMetr="297"       # milimeters, 297 for ISO A4
PaperDens="200"           # maximum (wanted) dpi for a page
PaperWdthInch=$( echo scale=5\; $PaperWdthMetr / 2.54 / 10      | bc -l ) # Inch
PaperHghtInch=$( echo scale=5\; $PaperHghtMetr / 2.54 / 10      | bc -l ) # Inch
PaperRtio=$(     echo scale=5\; $PaperWdthMetr / $PaperHghtMetr | bc -l )

# Remove temporary files from prior run
rm -rf z_merged.pdf z_temp.pdf 2>/dev/null

# Process any $ext file in the current directory
find . -maxdepth 1 -name "*.${ext}" -print0 | sort -z | while read -d '' -r FName
do
  echo "Converting $FName"
  ImgIdentify=$( identify -format "%w %h" "$FName" )
  ImgWdthOrig=$( echo $ImgIdentify | cut -d" " -f1  )
  ImgHghtOrig=$( echo $ImgIdentify | cut -d" " -f2  )
  ImgRtio=$( echo "scale=5; $ImgWdthOrig / $ImgHghtOrig"  | bc -l )
  [[ $( echo $ImgRtio'>'$PaperRtio | bc -l ) == 1 ]] \
    && ImgDens=$( echo scale=0\; $ImgWdthOrig / $PaperWdthInch | bc -l ) \
    || ImgDens=$( echo scale=0\; $ImgHghtOrig / $PaperHghtInch | bc -l )
  [[ $Debug ]] && echo "ImgDens1: $ImgDens"
  [[ $( echo $ImgDens'>'$PaperDens | bc -l ) == 1 ]] \
    && ImgDens=$PaperDens
  [[ $Debug ]] && echo "ImgDens2: $ImgDens"

  ImgWdth=$( echo $PaperWdthInch \* $ImgDens | bc -l ) # pixels
  ImgHght=$( echo $PaperHghtInch \* $ImgDens | bc -l ) # pixels

  [[ $Debug ]] && echo "ImgWdth: $ImgWdth".
  [[ $Debug ]] && echo "ImgHght: $ImgHght".

  convert "${FName}"                                 \
          -resize ${ImgWdth}x${ImgHght}              \
          -background $IMBackground -gravity center  \
          -extent ${ImgWdth}x${ImgHght}              \
          -units PixelsPerInch -set density $ImgDens \
          -repage ${ImgWdth}x${ImgHght}+0+0          \
          -compress JPEG                             \
          -quality $IMQuality                        \
          "${FName%.$ext}.pdf"

  # Merge new PDF page with prior pages
  [[ -f z_merged.pdf ]] && \
   { pdftk z_merged.pdf "${FName%.$ext}.pdf" cat output z_temp.pdf
     mv z_temp.pdf z_merged.pdf
   } || \
     cp "${FName%.$ext}.pdf" z_merged.pdf
  [[ $Debug ]] || rm -rf "${FName%.$ext}.pdf"
done

[[ -f z_merged.pdf ]] && mv z_merged.pdf "$OutName"
echo "Done."
Mikher
quelle
Oben musste ich -set density $ImgDens-density $ImgDens
Uhr
0

Ich habe gerade so etwas wie maxschlepzigs Antwort unter Ubuntu 16.04 / ImageMagick benutzt

Dies zentriert auch das Ergebnis

i=300; convert a.png b.png -compress jpeg -quality 100 \
      -density ${i}x${i} -units PixelsPerInch \
      -resize $((i*827/100))x$((i*1169/100)) \
      -gravity center \
      -extent $((i*827/100))x$((i*1169/100)) multipage.pdf
Martin Thoma
quelle