【问题标题】:imagemagick construct document with two images per A4 pageimagemagick 构造文档,每个 A4 页面有两个图像
【发布时间】:2018-11-02 15:44:51
【问题描述】:

使用 Ubuntu 14.04 Linux,我在一个名为 Capture 01.jpgCapture 02.jpg 等的文件夹中有一个 .jpg 图像列表,我想编写一个命令行,用 A4 创建一个多页文档大小的页面,其中每页按给定的顺序包含 2 个图像,文件名作为标题,页面包含页脚,如“第 1 页,共 41 页”。见,例如:

------
Capture 01.jpg

[image]

Capture 02.jpg

[image]
Page 1 of 41
------
Capture 03.jpg

[image]

Capture 04.jpg

[image]
Page 2 of 41
------
...

图片大小相同,大约为 1600x1200 像素。

了解一点 ImageMagick 的工作原理,我认为这将涉及某种 collatemontage 命令,但我不确定如何使其适合 A4 大小的页面以及如何格式化它们以进行打印(pdf? )。

有什么建议吗?

编辑:我发现了一个与添加图像文件名有关的问题:

Overlaying an image's filename using ImageMagick (or similar)

【问题讨论】:

  • 如果您收到的答案中缺少任何内容,如果您能告诉我们,那就太好了。否则,应将此问题标记为已解决。

标签: ubuntu command-line imagemagick


【解决方案1】:

首先,我建议您的文件名中不要包含空格,并使用足够多的前导零,以便目录中的文件按字母顺序排列。

我拍了这张照片:


再复制5次,并依次编号为:

lena_01.png
lena_02.png
lena_03.png
lena_04.png
lena_05.png
lena_06.png

并将它们放入我 Mac 桌面上名为“test”的新文件夹中。

然后使用带有 Unix bash shell 脚本的 ImageMagick 6,我在子 shell 中创建了一个循环,这样我就可以将中间图像保存为 MIFF: 格式,而无需单独保存它们。然后,我将输出通过管道传输到新的转换器以另存为 PDF。请注意,子外壳由 for 循环周围的括号表示。

这是一组命令:

#!/bin/bash

cd
cd desktop/test
arr=(`ls`)
num=${#arr[*]}
numm1=$((num-1))
numpages=`echo "scale=0; ($num+0.5)/2" | bc`
pagenum=1
(
for ((i=0; i<numm1; i=i+2)); do
  j=$((i+1))
  convert "${arr[$i]}" "${arr[$j]}" -background white -gravity center -append \
  -resize 595x842 -extent 595x842 +repage \
  -font arial -pointsize 18 -undercolor white -fill black \
  -gravity north -annotate +0+10 "${arr[$i]}" -annotate +0+431 "${arr[$j]}" \
  -gravity south -annotate +0+10 "Page $pagenum of $numpages" miff:-
  pagenum=$((pagenum+1))
  done
) | convert - ../result.pdf


其中 arr 是测试目录中的图像名称数组。请注意,A4 页面大小为 595x842,以 72 dpi 打印为 8.27 × 11.7 英寸

result.pdf

如果您确实想在文件名中保留空格,则可以将 IFS 更改为 arr 语句之前的新行,然后将其更改回空格。例如:

lena 01.png
lena 02.png
lena 03.png
lena 04.png
lena 05.png
lena 06.png

代码将更改为以下内容:

cd
cd desktop/test
OLDIFS=$IFS
IFS=$'\n'
arr=(`ls`)
num=${#arr[*]}
numm1=$((num-1))
numpages=`echo "scale=0; ($num+0.5)/2" | bc`
echo "numpages=$numpages"
pagenum=1
IFS=$OLDIFS
(
for ((i=0; i<numm1; i=i+2)); do
j=$((i+1))
convert "${arr[$i]}" "${arr[$j]}" -background white -gravity center -append \
-resize 595x842 -extent 595x842 +repage \
-font arial -pointsize 18 -undercolor white -fill black \
-gravity north -annotate +0+10 "${arr[$i]}" \
-annotate +0+431 "${arr[$j]}" \
-gravity south  -annotate +0+10 "Page $pagenum of $numpages" miff:-
pagenum=$((pagenum+1))
done
) | convert - ../result2.pdf

result2.pdf

【讨论】:

  • 感谢您的回复。我在转换命令中发现了+repage,我认为这是分页的作用。
  • @71906。不,似乎需要在调整大小和事件之后重置虚拟画布,以便相对于重力设置正确放置文本。没有它,页码似乎被放置在奇数图像的底部,而不是偶数图像的底部。页面大小由调整大小 595x842 决定,即 A4 大小(以像素为单位)(72 dpi)。
  • 很好的答案,但我不得不反对您关于文件名中的空格的建议。至少在 Unix 中,它们和许多其他字符(如 *、@、[、\ 等)是允许的,并且编写正确处理它们的脚本并不难。在您的情况下,它就像用(*) 替换(`ls`) 一样简单。模式可以用(*.png)pat="*.png *.jpg"; arr=($pat) 之类的方式完成。
  • 我同意您可以解决空格问题。至少对我来说,它只是让避免它们变得更容易。使用 arr=(*) 不起作用,因为每个空格分隔的字符串都是一个单独的元素。必须更改 IFS,在这种情况下我会这样做。
  • 在上述情况下,不清楚 Capture 是图像名称还是目录的一部分。我认为它是图像名称的一部分。但是如果 Capture 是目录,我的代码可以很容易地更改。
【解决方案2】:

fmw42 的要求,这是我的版本,我相信这是一个改进,因为它可以更好地处理“困难”文件名。

首先进行一些设置。
创建目录、下载图像、复制 x6 并提供新的古怪名称。

#!/bin/bash

cd ~/Desktop
mkdir testimagesSO
cd testimagesSO
wget "https://i.imgur.com/GeaEv21.png"

mv *.png testimage.png

Names=("Drøbaksundet\n img #1*" "Drøbaksundet\n img #2*" "Drøbaksundet\n img #3*" \
       "Drøbaksundet\n img #4*" "Drøbaksundet\n img #5*" "Drøbaksundet\n img #6*" )

echo "${#Names[@]}"

for f in "${Names[@]}"
do
  cp testimage.png "$f".png
done

rm testimage.png

该命令的内容与fmw42 非常相似,只是它完全基于数组。我还逐步使用了bc

arr=(*)
num=${#arr[*]}
numm1=$((num-1))
npp=2
numpages=$((($num+$npp-1)/$npp))
echo "numpages=$numpages"
pagenum=1
(
for ((i=0; i<numm1; i=i+2)); do
  j=$((i+1))
  convert "${arr[$i]}" "${arr[$j]}" -background white -gravity center -append \
  -resize 595x842 -extent 595x842 +repage \
  -font arial -pointsize 18 -undercolor white -fill black \
  -gravity north -annotate +0+10 "${arr[$i]}" \
  -annotate +0+431 "${arr[$j]}" \
  -gravity south  -annotate +0+10 "Page $pagenum of $numpages" miff:-
  pagenum+=1
done
) | convert - ../result2.pdf

我没有方便的地方来托管 PDF,但这或多或少是我得到的输出(想象一下它分为 3 个 A4 页面。

【讨论】:

  • 也许我误解了,但是您的方法似乎要求您在数组中设置名称列表,并在它们周围加上引号,因为有空格。这是您手动执行的额外步骤。在我的方法中,我尽量避免这样做。我误解了吗?还是您的方法是从名称不带引号的目录中自动执行此操作?
  • @fmw42:您是指设置部分中的Names 数组?这只是为了使示例易于重现而分配名称。 Names 从未在 convert 部分中引用,所有文件名都来自 arr 数组,就像在您的示例中所做的那样。
  • 我测试了您的代码,并且确实使用 arr=(*) 获得了正确数量的文件名,即使有空格也是如此。所以我想我今天学到了一些新东西。谢谢。
  • @fmw42:有趣!如果你很好奇,我从 Gilles here 那里学到了大部分内容
猜你喜欢
  • 2014-06-06
  • 2021-11-26
  • 1970-01-01
  • 2011-05-04
  • 2015-09-29
  • 2012-12-10
  • 2017-09-11
  • 2018-01-10
  • 1970-01-01
相关资源
最近更新 更多