如何最好地将 png 缩放为 1 位 BMP(pyvips 或 PIL)

问题描述 投票:0回答:1

对于一个项目,我需要将 PDF 转换为 1 位(大)BMP 图像条。

质量不是这里的主要问题,但转换速度才是。

输入是 PDF 文档,输出是一系列 BMP 图像,大小均为 65.000 x 4800 像素。

我无法发布实际的 PDF,因此作为示例,我包含了 IKEA BILLY 组装说明中的一条。

Example of a strip from PDF

此条是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")
python image-processing bitmap vips
1个回答
0
投票

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

图像看起来不错:

enter image description here

它需要 2.4GB,这不太好。 libvips 使用 4000 个扫描线高块进行 pdfload,也许这应该是一个可调参数?

© www.soinside.com 2019 - 2024. All rights reserved.