Answers:
上一次我用于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用作默认的密度/页面格式单位,因此我们使用该-units
选项明确指定了DPI (否则,使用不同的版本/输入格式组合可能会得到不同的结果)。新尺寸(通过指定-resize
)是DIN A4页面的尺寸(以像素为单位)。resize参数指定最大页面大小。确切选择哪种分辨率和质量取决于用例-我选择了150 DPI和平均质量以节省一些空间,而在纸上打印时看起来并不差。
请注意,convert
默认情况下不会通过调整大小操作更改纵横比:
调整大小将使图像适合要求的大小。它没有填满要求的盒子大小。
根据ImageMagick版本和所涉及的输入格式,可以省略该-repage
选项。但是有时是必需的,没有该选项,PDF标头可能包含太小的尺寸。无论如何,-repage
都不应该受到伤害。
由于bash
仅支持整数运算,因此计算使用整数运算。随着zsh
表达式可以简化-即与更换$((i*8.27))x$((i*11.69))
。
如果PNG文件是双层图像(黑白又称为线稿),则该img2pdf
工具将产生比ImageMagick更好的结果convert
。这意味着img2pdf
速度更快,并且产生的PDF较小。
例:
$ img2pdf -o multipage.pdf a.png b.png
要么:
$ img2pdf --pagesize A4 -o multipage.pdf a.png b.png
-repage
不再支持a4名称。我已经通过Shell算术解决了这个问题:-repage $((150*8.27))x$((150*11.69))
-density 150
论点很重要。
您真正想要使用的是:
$ 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
参数是可选的,但在扩展时可用于使图像居中。
-extent
确实是我想使用的:)-请在-extent前面添加缺少的左引号,谢谢!
除了柯格纳的答案:
安装了IM v6.6.9-7后,我发现该-gravity
参数需要放在两者之间-resize
并-extent
起作用。
另外(虽然这不是op问题的一部分),但我发现设置了一种不同的背景色效果很吸引人,这将导致
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(A4页面的英寸宽度)来动态确定的。该-repage a4
参数在大多数情况下都可以省略,但是在某些情况下,生成的.pdf格式将与A4尺寸210x297mm(8.27x11.6“)截然不同
我发现Mikher的代码非常有用,但是它将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."
我发现以下脚本很方便,它结合了此处列出的答案以及浮点计算所遇到的一些问题:
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:根据tanius的注释添加了“ -l”标志,以实现更好的精度。
$(echo "150*8.27" | bc)
对于浮点来说仍然不是很好。在这里工作,因为它是一个乘法。对于$(echo "150/8.27" | bc)
虽然,结果是18
(截断为整数)。而是bc
使用更高的调用scale
:$(echo "150/8.27" | bc -l)
,结果为18.137847…
。
我也在那东西上挣扎。基于以上信息,我编写了一个脚本,该脚本将按字母顺序排序的图像文件添加到单个PDF中。
在脚本中可以设置一些变量。这取决于ImageMagick和pdftk。
注意:如果输入图像的分辨率(dpi)比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."
-set density $ImgDens
为-density $ImgDens
我强烈建议使用Python CLI程序img2pdf
进行无损转换:
https://gitlab.mister-muffin.de/josch/img2pdf
用法示例:
img2pdf img1.png img2.png -o out.pdf
-repage a4
我得到了invalid argument for option '-repage': a4