конвертировать изображения в pdf: как сделать PDF страницы одинакового размера

45

Я сделал что-то вроде

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

Но 1-я страница намного больше, чем последующие. Это происходит, даже если размеры изображения похожи. Эти изображения сканируются и обрезаются, поэтому могут иметь небольшие различия в размерах

Я думал, -page A4должен исправить размер страниц?

Jiew Meng
источник

Ответы:

60

В прошлый раз, когда я использовал convertдля такой задачи, я явно указал размер места назначения с помощью изменения размера:

$ 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

Команда convertне всегда использует DPI в качестве единицы измерения плотности / формата страницы по умолчанию, поэтому мы явно указываем DPI с помощью этой -unitsопции (в противном случае вы можете получить разные результаты с разными комбинациями версий / форматов ввода). Новый размер (указанный через -resize) - это размер страницы DIN A4 в пикселях. Аргумент resize указывает максимальный размер страницы. Какое разрешение и качество выбрать точно, зависит от варианта использования - я выбрал 150 DPI и среднее качество, чтобы сэкономить место, хотя при печати на бумаге он выглядит не так уж плохо.

Обратите внимание, что convertпо умолчанию не изменяется соотношение сторон с помощью операции изменения размера:

Изменение размера подгонит изображение под требуемый размер. НЕ заполняет, запрошенный размер коробки.

( Руководство по ImageMagick )

В зависимости от версии ImageMagick и задействованных форматов ввода, возможно, можно пропустить этот -repageпараметр. Но иногда это требуется, и без этой опции заголовок PDF может содержать слишком маленькие размеры. В любом случае, -repageне должно быть больно.

В вычислениях используется целочисленная арифметика, поскольку это bashподдерживается только. С zshпомощью выражений можно упростить - т.е. заменить на $((i*8.27))x$((i*11.69)).

Lineart Images

Если файлы PNG представляют собой двухуровневые (черно-белые или линейные) изображения, тогда img2pdfинструмент дает превосходные результаты по сравнению с ImageMagick convert. Это означает, img2pdfчто быстрее и дает меньше PDF-файлов.

Пример:

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

или же:

$ img2pdf --pagesize A4 -o multipage.pdf a.png b.png
maxschlepzig
источник
2
при использовании -repage a4я получаюinvalid argument for option '-repage': a4
Scolytus
1
@Scolytus, в системе Fedora 19 я наблюдал похожую проблему - похоже, -repageона больше не поддерживает имя a4. Я работал над этим с помощью арифметики оболочки:-repage $((150*8.27))x$((150*11.69))
maxschlepzig
Я предполагаю, что эти магические числа имеют 150 точек на дюйм, а А4 выражается в устаревших единицах?
Майкл Шепер
@MichaelScheper, да, точек на дюйм и дюймов.
maxschlepzig
Спасибо, помогите мне. На самом деле -density 150аргумент было важно добавить.
dma_k
23

Что вы действительно хотите использовать:

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

-extentфактически расширяет изображение до 1240x1753, сохраняя при -resizeэтом соотношение изображения, подгоняя его либо к, 1240x...либо ...x1753.

-gravityПараметр является необязательным , но может быть использован для размещения изображения при расширении.

caugner
источник
1
Спасибо! -extentэто действительно то, что я хочу использовать :) - пожалуйста, добавьте пропущенную левую кавычку перед -extent, спасибо!
броуновский
Спасибо, я в итоге добавил пропущенную галочку! ;-)
caugner
9

Дополнение к ответу Каугнера :

установив IM v6.6.9-7, я обнаружил, что -gravityпараметр должен быть помещен между -resizeи -extentиметь эффект.

Кроме того (хотя это и не часть оп-вопроса), я обнаружил, что задан другой привлекательный цвет фона, в результате чего общая команда

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

Еще один полезный вариант, который я часто использую, когда не хочу изменять масштаб изображения, которое уже имеет правильное соотношение сторон, но сохраняет свое индивидуальное разрешение.

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

где целевая плотность определяется динамически путем вычисления ширины, деленной на 8,27 (которая является шириной в дюймах страницы А4). -repage a4параметр можно опустить большую часть времени , но у меня было несколько случаев , когда в результате .pdf будет иметь другой формат sligtly от размеров А4 210х297мм (8.27x11.6" )

antiplex
источник
2

Я обнаружил, что код Михера очень полезен, однако он полностью отображает PDF-файл как книжный или альбомный, поэтому я изменил его, чтобы проверить макет каждого входного файла и сопоставить его в выходных данных.

Я не включил редактирование Yotam, поскольку оно работает без него на моем 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."
user173283
источник
2

Мне кажется удобным следующий скрипт, который объединяет ответы, перечисленные здесь, а также некоторые проблемы, которые у меня были с вычислением с плавающей запятой:

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"

Скрипт вызывается (сохраняется как файл images2pdf)

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

/ edit: Добавлен флаг "-l" в соответствии с комментарием tanius для большей точности.

rindPHI
источник
Общий совет: $(echo "150*8.27" | bc)все еще не подходит для плавающей запятой. Здесь работает, потому что это умножение. Для, $(echo "150/8.27" | bc)хотя, результат - 18(урезанный к целому числу). Вместо этого звоните bcс более высоким scale:, $(echo "150/8.27" | bc -l)результаты есть 18.137847….
Танус
1

Я тоже боролся с этим. Основываясь на вышеупомянутой информации, я написал скрипт, который добавляет отсортированные по алфавиту файлы изображений в один PDF.

Некоторые переменные устанавливаются внутри скрипта. Это зависит от ImageMagick и pdftk.

NB. Если входное изображение имеет более высокое разрешение (т / д), чем требуемое разрешение файла output.pdf, то изображение повторно дискретизируется до более низкого разрешения. В противном случае изображение не пересэмплируется и расширяется только для соответствия холсту страницы.

#!/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
источник
В вышеупомянутом я должен был измениться -set density $ImgDensна-density $ImgDens
Yotam
1

Я настоятельно рекомендую программу Python CLI img2pdfдля преобразования без потерь:

https://gitlab.mister-muffin.de/josch/img2pdf

Пример использования:

img2pdf img1.png img2.png -o out.pdf
Адам Эриксон
источник
0

Я просто использовал что-то похожее на ответ maxschlepzigs под Ubuntu 16.04 / ImageMagick

Это также центрирует результат

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
Мартин Тома
источник
0

Я хотел преобразовать изображение в размер страницы 5,00 x 8,00 дюйма (при просмотре из Adobe Reader). Вот что я сделал на Ubuntu 18.04 OS. Во-первых, выясните, какой размер страницы мне нужен, вот так:

$ pdfinfo my-input.pdf

И возвращение: Размер страницы: 360 х 576 баллов

Затем изображение преобразуется в PDF такого же размера, например:

$ img2pdf --pagesize 360x576 -o outpage.pdf input_pic.jpg

Примечание: установить img2pdf

$ sudo apt install img2pdf

Гарри
источник