对于一个项目,我需要将 PDF 转换为 1 位(大)BMP 图像条。
质量不是这里的主要问题,但转换速度才是。
输入是 PDF 文档,输出是一系列 BMP 图像,大小均为 65.000 x 4800 像素。
我无法发布实际的 PDF,因此作为示例,我包含了 IKEA BILLY 组装说明中的一条。
此条是PNG格式,但也可以是JPG、PBM或其他格式。片段的创建是使用 pyvips 完成的,速度非常快。
问题是我如何获得最终输出。我知道 ImageMagick 中的命令,但速度慢得令人痛苦。每条超过 10 秒。
Imagemagick 命令:
magick Billy_04.jpg -resize 65000x -dither FloydSteinberg -remap pattern:gray50 -colors 2 -monochrome BMP3:Billy_04_converted.bmp
我不需要任何子采样或类似的,如果输出有轻微的块状就可以了。
有没有办法在Python中快速完成这种转换?我没有被 pyvips 束缚。
我用来制作条带的脚本:
#!/usr/bin/python3
import sys
import pyvips
import math
destinationwidth = 60000
destinationheight = 4700
image = pyvips.Image.new_from_file(sys.argv[1])
for i in range(1): # for the example, limit to first page only.
# for i in range(image.get('n-pages')):
image = pyvips.Image.new_from_file(sys.argv[1], page=i, scale=10)
mywidth = image.width
myheight = image.height
scale_in_width = destinationwidth/mywidth
stripheight = math.floor(destinationheight/scale_in_width)
stripcount = myheight/stripheight
stripcountInt = math.ceil(stripcount)
print("Width = " , mywidth, " height = ", myheight)
print("Strip height = ", stripheight, " amount of strips = ", stripcount , " (round to) ", stripcountInt)
theheight = stripheight
verticalpos = 0
for s in range(stripcountInt):
print(f"Strip number {s} at {s*stripheight} : ")
thestrip = image.crop( 0, s*stripheight, mywidth, theheight)
verticalpos += theheight
# do not want to go outside area
if (verticalpos + stripheight) > myheight:
theheight = myheight - verticalpos-1
thestrip.write_to_file(f"Pstrip_{s}.png")
libvips 没有原生 BMP 加载器或保存器 - 对于这种格式,它将通过 libMagick 进行,并且不会让您对保存参数有太多控制。
一定是BMP吗?如果您可以使用 1 位 TIFF 或 1 位 PNG 来代替,您可以在 pyvips 中完成这一切,并且 pyvips 会在内部自动为您分块。
例如:
#!/usr/bin/env python3
import sys
import pyvips
image = pyvips.Image.pdfload(sys.argv[1])
# what scale do we need to get an image 65536 pixels across
target_width = 65536
scale = target_width / image.width
image = pyvips.Image.pdfload(sys.argv[1], scale=scale, page=5)
# the libvips pdf loader makes an rgba image ... flatten to rgb to remove the
# alpha, then convert to mono
image = image.flatten().colourspace("b-w")
# and save as 1-bit tiff
image.tiffsave(sys.argv[2], compression="ccittfax4", bitdepth=1)
使用比利 PDF:
https://www.ikea.com/gb/en/ assembly_instructions/billy-bookcase-white__AA-1823127-8-2.pdf
我可以跑步:
$ VIPS_PROGRESS=1 /usr/bin/time -f %M:%e ./pdf-to-fax.py ~/pics/billy-bookcase-white__AA-1823127-8-2.pdf x.tif
pdf-to-fax.py temp-25: 65566 x 92730 pixels, 32 threads, 128 x 128 tiles, 640 lines in buffer
pdf-to-fax.py temp-25: done in 48.3s
2420324:48.38
$ ls -l x.tif
-rw-r--r-- 1 john john 1012028 Jun 15 14:08 x.tif
图像看起来不错:
它需要 2.4GB,这不太好。 libvips 使用 4000 个扫描线高块进行 pdfload,也许这应该是一个可调参数?