konwertuj obrazy na pdf: jak zrobić strony PDF tego samego rozmiaru

45

Zrobiłem coś takiego

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

Ale pierwsza strona jest znacznie większa niż kolejne strony. Dzieje się tak, mimo że wymiary obrazu są podobne. Te obrazy są skanowane i przycinane, dlatego mogą mieć niewielkie różnice w wymiarach

Pomyślałem, że -page A4powinienem naprawić rozmiar stron?

Jiew Meng
źródło

Odpowiedzi:

60

Ostatnim razem, gdy użyłem converttakiego zadania, wyraźnie określiłem rozmiar miejsca docelowego, zmieniając rozmiar:

$ 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

convertKomenda nie zawsze używać DPI jako jednostki domyślnego formatu gęstość / strona, więc możemy jednoznacznie określić DPI z -unitsopcji (w przeciwnym razie można uzyskać różne wyniki w różnych wersjach / kombinacje format wejściowy). Nowy rozmiar (określony przez -resize) to rozmiar strony DIN A4 w pikselach. Argument zmiany rozmiaru określa maksymalny rozmiar strony. Wybór rozdzielczości i jakości zależy dokładnie od przypadku użycia - wybrałem 150 DPI i średnią jakość, aby zaoszczędzić trochę miejsca, a nie wygląda tak źle po wydrukowaniu na papierze.

Należy pamiętać, że convertdomyślnie nie zmienia współczynnika proporcji podczas operacji zmiany rozmiaru:

Zmiana rozmiaru dopasuje obraz do żądanego rozmiaru. NIE wypełnia żądanego rozmiaru pudełka.

( Instrukcja ImageMagick )

W zależności od wersji ImageMagick i zaangażowanych formatów wejściowych może być pominięcie tej -repageopcji. Ale czasami jest to wymagane i bez tej opcji nagłówek PDF może zawierać zbyt małe wymiary. W każdym razie -repagenie powinno boleć.

Obliczenia wykorzystują arytmetykę liczb całkowitych, ponieważ bashtylko to obsługuje. Dzięki zshwyrażeniom można uprościć - tzn. Zastąpić je $((i*8.27))x$((i*11.69)).

Obrazy Lineart

Jeśli pliki PNG są obrazami dwupoziomowymi (czarno-biały aka lineart), to img2pdfnarzędzie daje lepsze wyniki niż ImageMagick convert. Oznacza to, że img2pdfjest szybszy i daje mniejsze pliki PDF.

Przykład:

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

lub:

$ img2pdf --pagesize A4 -o multipage.pdf a.png b.png
maxschlepzig
źródło
2
podczas korzystania -repage a4dostajęinvalid argument for option '-repage': a4
Scolytus
1
@Scolytus, w systemie Fedora 19 zaobserwowałem podobny problem - wygląda na to, że -repagenie obsługuje już nazwy A4. Pracowałem nad tym za pomocą arytmetyki powłoki:-repage $((150*8.27))x$((150*11.69))
maxschlepzig
Zakładam, że te magiczne liczby to 150dpi, a A4 wyrażone w starszych jednostkach?
Michael Scheper
@MichaelScheper, tak, dpi i cale.
maxschlepzig
Dzięki, pomóż mi. Właściwie -density 150argument był ważny do dodania.
dma_k
23

To, czego naprawdę chcesz użyć to:

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

-extentfaktycznie wydłuża obraz do rozmiaru 1240 x 1753, -resizezachowując proporcje obrazu, dopasowując go do jednego 1240x...lub ...x1753.

Ten -gravityparametr jest opcjonalny, ale można go użyć do wyśrodkowania obrazu podczas rozciągania.

caugner
źródło
1
Dziękuję Ci! -extentjest naprawdę tym, czego chcę użyć :) - dodaj brakujący lewy cytat przed tekstem, dzięki!
brownian
Dziękuję, w końcu dodałem brakujący tik! ;-)
caugner
9

Dodatek do odpowiedzi caugnera :

po zainstalowaniu IM v6.6.9-7 dowiedziałem się, że -gravityparametr musi być umieszczony pomiędzy -resizei -extentaby mieć efekt.

dodatkowo (choć nie jest to część pytania operacyjnego) ustaliłem, że ustawienie innego koloru tła jest atrakcyjne, co spowodowałoby całkowitą kontrolę nad

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

kolejna przydatna odmiana, której często używam, gdy nie chcę przeskalować obrazu, który już ma prawidłowy współczynnik kształtu, ale zachowuje indywidualną rozdzielczość

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

gdzie docelowa gęstość jest określana dynamicznie przez obliczenie szerokości podzielonej przez 8,27 (która jest szerokością w calach strony A4). -repage a4parametr może być pominięte przez większość czasu, ale miałem kilka przypadków, w których powstały .pdf miałyby inny format Sligtly off wymiarach A4 (210x297mm 8.27x11.6" )

antiplex
źródło
2

Uznałem, że kod Mikhera jest bardzo przydatny, jednak określa on całkowicie PDF jako Pionowy lub Poziomy, więc zmodyfikowałem go, aby sprawdzić układ każdego pliku wejściowego i dopasować go do wyniku.

Nie dodałem edycji Yotam, ponieważ działa ona bez niej na moim systemie Ubuntu 15.04.

$#!/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."
użytkownik173283
źródło
2

Uważam, że wygodny jest następujący skrypt, który łączy wymienione tutaj odpowiedzi, a także niektóre problemy, które miałem z obliczeniami zmiennoprzecinkowymi:

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"

Skrypt jest wywoływany (zapisany jako plik images2pdf)

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

/ edit: Dodano flagę „-l” zgodnie z komentarzem Taniusa dla większej precyzji.

rindPHI
źródło
Ogólna wskazówka: $(echo "150*8.27" | bc)nadal nie jest świetna do liczb zmiennoprzecinkowych. Działa tutaj, ponieważ jest to mnożenie. W przypadku $(echo "150/8.27" | bc)jednak, wynik 18(skrócony na całkowitą). Zamiast tego zadzwoń bcz wyższym scale: $(echo "150/8.27" | bc -l)wyniki są 18.137847….
tanius
1

Walczyłem też z tymi rzeczami. Na podstawie powyższych informacji napisałem skrypt, który dodaje posortowane alfabetycznie pliki obrazów do jednego pliku PDF.

Niektóre zmienne są ustawiane w skrypcie. To zależy od ImageMagick i pdftk.

Uwaga: Jeśli obraz wejściowy ma wyższą rozdzielczość (dpi) niż pożądana rozdzielczość pliku wyjściowego.pdf, obraz jest ponownie próbkowany do niższej rozdzielczości. W przeciwnym razie obraz nie jest ponownie próbkowany i jest rozszerzany tylko w celu dopasowania do obszaru roboczego strony.

#!/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
źródło
W powyższym przypadku musiałem zmienić się -set density $ImgDensna-density $ImgDens
Yotam
0

Właśnie użyłem czegoś podobnego do odpowiedzi maxschlepzigs pod Ubuntu 16.04 / ImageMagick

To także centruje wynik

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
źródło