在 python 中,无需重新采样即可从 PDF 中提取图像?[关闭]

2025-01-22 08:45:00
admin
原创
114
摘要:问题描述:如何以原始分辨率和格式从 pdf 文档中提取所有图像?(意思是将 tiff 提取为 tiff,将 jpeg 提取为 jpeg 等,并且不进行重新采样)。布局并不重要,我不关心源图像在页面上的位置。解决方案 1:您可以使用模块 PyMuPDF。这会将所有图像输出为 .png 文件,但开箱即用且速度很快...

问题描述:

如何以原始分辨率和格式从 pdf 文档中提取所有图像?(意思是将 tiff 提取为 tiff,将 jpeg 提取为 jpeg 等,并且不进行重新采样)。布局并不重要,我不关心源图像在页面上的位置。


解决方案 1:

您可以使用模块 PyMuPDF。这会将所有图像输出为 .png 文件,但开箱即用且速度很快。

import fitz
doc = fitz.open("file.pdf")
for i in range(len(doc)):
    for img in doc.getPageImageList(i):
        xref = img[0]
        pix = fitz.Pixmap(doc, xref)
        if pix.n < 5:       # this is GRAY or RGB
            pix.writePNG("p%s-%s.png" % (i, xref))
        else:               # CMYK: convert to RGB first
            pix1 = fitz.Pixmap(fitz.csRGB, pix)
            pix1.writePNG("p%s-%s.png" % (i, xref))
            pix1 = None
        pix = None

点击此处查看更多资源

这是针对 fitz 1.19.6 的修改版本:

import os
import fitz  # pip install --upgrade pip; pip install --upgrade pymupdf
from tqdm import tqdm # pip install tqdm

workdir = "your_folder"

for each_path in os.listdir(workdir):
    if ".pdf" in each_path:
        doc = fitz.Document((os.path.join(workdir, each_path)))

        for i in tqdm(range(len(doc)), desc="pages"):
            for img in tqdm(doc.get_page_images(i), desc="page_images"):
                xref = img[0]
                image = doc.extract_image(xref)
                pix = fitz.Pixmap(doc, xref)
                pix.save(os.path.join(workdir, "%s_p%s-%s.png" % (each_path[:-4], i, xref)))
                
print("Done!")

解决方案 2:

在 Python 中pypdf,使用 Pillow 库很简单:

from pypdf import PdfReader

reader = PdfReader("example.pdf")
for page in reader.pages:
    for image in page.images:
        with open(image.name, "wb") as fp:
            fp.write(image.data)

请注意:PyPDF2 已弃用。请使用 pypdf。

解决方案 3:

在 PDF 中,图像通常按原样存储。例如,插入 jpg 的 PDF 将在中间某处有一系列字节,提取后即为有效的 jpg 文件。您可以使用它非常简单地从 PDF 中提取字节范围。我前段时间写过关于此内容的文章,其中包含示例代码:从 PDF 中提取 JPG。

解决方案 4:

在 Python 中使用 PyPDF2 作为 CCITTFaxDecode 过滤器:

import PyPDF2
import struct

"""
Links:
PDF format: http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf
CCITT Group 4: https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.6-198811-I!!PDF-E&type=items
Extract images from pdf: http://stackoverflow.com/questions/2693820/extract-images-from-pdf-without-resampling-in-python
Extract images coded with CCITTFaxDecode in .net: http://stackoverflow.com/questions/2641770/extracting-image-from-pdf-with-ccittfaxdecode-filter
TIFF format and tags: http://www.awaresystems.be/imaging/tiff/faq.html
"""


def tiff_header_for_CCITT(width, height, img_size, CCITT_group=4):
    tiff_header_struct = '<' + '2s' + 'h' + 'l' + 'h' + 'hhll' * 8 + 'h'
    return struct.pack(tiff_header_struct,
                       b'II',  # Byte order indication: Little indian
                       42,  # Version number (always 42)
                       8,  # Offset to first IFD
                       8,  # Number of tags in IFD
                       256, 4, 1, width,  # ImageWidth, LONG, 1, width
                       257, 4, 1, height,  # ImageLength, LONG, 1, lenght
                       258, 3, 1, 1,  # BitsPerSample, SHORT, 1, 1
                       259, 3, 1, CCITT_group,  # Compression, SHORT, 1, 4 = CCITT Group 4 fax encoding
                       262, 3, 1, 0,  # Threshholding, SHORT, 1, 0 = WhiteIsZero
                       273, 4, 1, struct.calcsize(tiff_header_struct),  # StripOffsets, LONG, 1, len of header
                       278, 4, 1, height,  # RowsPerStrip, LONG, 1, lenght
                       279, 4, 1, img_size,  # StripByteCounts, LONG, 1, size of image
                       0  # last IFD
                       )

pdf_filename = 'scan.pdf'
pdf_file = open(pdf_filename, 'rb')
cond_scan_reader = PyPDF2.PdfFileReader(pdf_file)
for i in range(0, cond_scan_reader.getNumPages()):
    page = cond_scan_reader.getPage(i)
    xObject = page['/Resources']['/XObject'].getObject()
    for obj in xObject:
        if xObject[obj]['/Subtype'] == '/Image':
            """
            The  CCITTFaxDecode filter decodes image data that has been encoded using
            either Group 3 or Group 4 CCITT facsimile (fax) encoding. CCITT encoding is
            designed to achieve efficient compression of monochrome (1 bit per pixel) image
            data at relatively low resolutions, and so is useful only for bitmap image data, not
            for color images, grayscale images, or general data.

            K < 0 --- Pure two-dimensional encoding (Group 4)
            K = 0 --- Pure one-dimensional encoding (Group 3, 1-D)
            K > 0 --- Mixed one- and two-dimensional encoding (Group 3, 2-D)
            """
            if xObject[obj]['/Filter'] == '/CCITTFaxDecode':
                if xObject[obj]['/DecodeParms']['/K'] == -1:
                    CCITT_group = 4
                else:
                    CCITT_group = 3
                width = xObject[obj]['/Width']
                height = xObject[obj]['/Height']
                data = xObject[obj]._data  # sorry, getData() does not work for CCITTFaxDecode
                img_size = len(data)
                tiff_header = tiff_header_for_CCITT(width, height, img_size, CCITT_group)
                img_name = obj[1:] + '.tiff'
                with open(img_name, 'wb') as img_file:
                    img_file.write(tiff_header + data)
                #
                # import io
                # from PIL import Image
                # im = Image.open(io.BytesIO(tiff_header + data))
pdf_file.close()

解决方案 5:

Libpoppler 附带一个名为“pdfimages”的工具,可以完成这个任务。

(在 ubuntu 系统上它位于 poppler-utils 包中)

http://poppler.freedesktop.org/

http://en.wikipedia.org/wiki/Pdfimages

Windows 二进制文件:http://blog.alivate.com.au/poppler-windows/

解决方案 6:

我更喜欢 minecart,因为它非常容易使用。以下代码片段展示了如何从 pdf 中提取图像:

#pip install minecart
import minecart

pdffile = open('Invoices.pdf', 'rb')
doc = minecart.Document(pdffile)

page = doc.get_page(0) # getting a single page

#iterating through all pages
for page in doc.iter_pages():
    im = page.images[0].as_pil()  # requires pillow
    display(im)

解决方案 7:

PikePDF可以用很少的代码做到这一点:

from pikepdf import Pdf, PdfImage

filename = "sample-in.pdf"
example = Pdf.open(filename)

for i, page in enumerate(example.pages):
    for j, (name, raw_image) in enumerate(page.images.items()):
        image = PdfImage(raw_image)
        out = image.extract_to(fileprefix=f"{filename}-page{i:03}-img{j:03}")

extract_to将根据图像在 PDF 中的编码方式自动选择文件扩展名。

如果需要,您还可以在提取图像时打印一些有关图像的详细信息:

        # Optional: print info about image
        w = raw_image.stream_dict.Width
        h = raw_image.stream_dict.Height
        f = raw_image.stream_dict.Filter
        size = raw_image.stream_dict.Length

        print(f"Wrote {name} {w}x{h} {f} {size:,}B {image.colorspace} to {out}")

可以打印类似

Wrote /Im1 150x150 /DCTDecode 5,952B /ICCBased to sample2.pdf-page000-img000.jpg
Wrote /Im10 32x32 /FlateDecode 36B /ICCBased to sample2.pdf-page000-img001.png
...

请参阅文档以了解对图像执行的更多操作,包括在 PDF 文件中替换图像。


虽然这种方法通常很有效,但请注意,有许多图像无法通过这种方式提取:

  • 矢量图形,例如嵌入式 SVG/PS/PDF;您可以裁剪原始 PDF,但我不知道有没有简单的方法可以通过编程来实现这一点

  • PDF 中使用“CCITTFaxDecode,类型 G4,将 /EncodedByteAlign 设置为 true”压缩的某些单色图像

  • 非 RGB/CMYK 图像,又名 ProcessColorModel/DeviceN/HiFi,用于颜色分离(感谢mara004)

解决方案 8:

这是我 2019 年的版本,它以递归方式从 PDF 中获取所有图像并使用 PIL 读取它们。与 Python 2/3 兼容。我还发现有时 PDF 中的图像可能被 zlib 压缩,因此我的代码支持解压缩。

#!/usr/bin/env python3
try:
    from StringIO import StringIO
except ImportError:
    from io import BytesIO as StringIO
from PIL import Image
from PyPDF2 import PdfFileReader, generic
import zlib


def get_color_mode(obj):

    try:
        cspace = obj['/ColorSpace']
    except KeyError:
        return None

    if cspace == '/DeviceRGB':
        return "RGB"
    elif cspace == '/DeviceCMYK':
        return "CMYK"
    elif cspace == '/DeviceGray':
        return "P"

    if isinstance(cspace, generic.ArrayObject) and cspace[0] == '/ICCBased':
        color_map = obj['/ColorSpace'][1].getObject()['/N']
        if color_map == 1:
            return "P"
        elif color_map == 3:
            return "RGB"
        elif color_map == 4:
            return "CMYK"


def get_object_images(x_obj):
    images = []
    for obj_name in x_obj:
        sub_obj = x_obj[obj_name]

        if '/Resources' in sub_obj and '/XObject' in sub_obj['/Resources']:
            images += get_object_images(sub_obj['/Resources']['/XObject'].getObject())

        elif sub_obj['/Subtype'] == '/Image':
            zlib_compressed = '/FlateDecode' in sub_obj.get('/Filter', '')
            if zlib_compressed:
               sub_obj._data = zlib.decompress(sub_obj._data)

            images.append((
                get_color_mode(sub_obj),
                (sub_obj['/Width'], sub_obj['/Height']),
                sub_obj._data
            ))

    return images


def get_pdf_images(pdf_fp):
    images = []
    try:
        pdf_in = PdfFileReader(open(pdf_fp, "rb"))
    except:
        return images

    for p_n in range(pdf_in.numPages):

        page = pdf_in.getPage(p_n)

        try:
            page_x_obj = page['/Resources']['/XObject'].getObject()
        except KeyError:
            continue

        images += get_object_images(page_x_obj)

    return images


if __name__ == "__main__":

    pdf_fp = "test.pdf"

    for image in get_pdf_images(pdf_fp):
        (mode, size, data) = image
        try:
            img = Image.open(StringIO(data))
        except Exception as e:
            print ("Failed to read image with PIL: {}".format(e))
            continue
        # Do whatever you want with the image

解决方案 9:

好吧,我已经为此奋斗了好几个星期,其中许多答案都帮助了我,但总是缺少一些东西,显然这里没有人遇到过jbig2 编码图像的问题。

在我要扫描的一堆 PDF 中,用 jbig2 编码的图像非常受欢迎。

据我所知,有许多复印/扫描机可以扫描纸张并将其转换为充满 jbig2 编码图像的 PDF 文件。

因此经过多日的测试后,决定寻求 dkagedal 很久以前在这里提出的答案。

这是我在 Linux 上的一步步操作:(如果您有其他操作系统,我建议使用Linux docker,这样会容易得多。)

第一步:

apt-get install poppler-utils

然后我可以像这样运行名为 pdfimages 的命令行工具:

pdfimages -all myfile.pdf ./images_found/

使用上述命令,您将能够提取myfile.pdf 中包含的所有图像,并将它们保存在 images_found 中(您必须先创建 images_found)

在列表中,您会发现几种类型的图像,png,jpg,tiff;所有这些都可以使用任何图形工具轻松读取。

然后你将会有一些名为的文件:-145.jb2e 和 -145.jb2g。

这两个文件包含一个用 jbig2 编码的图像,保存在两个不同的文件中,一个用于标题,一个用于数据

我又花了很多天的时间尝试如何将这些文件转换为可读的内容,最后我遇到了这个名为 jbig2dec 的工具

因此首先你需要安装这个神奇的工具:

apt-get install jbig2dec

然后你可以运行:

jbig2dec -t png -145.jb2g -145.jb2e

您最终将能够将所有提取的图像转换为有用的内容。

祝你好运!

解决方案 10:

我从@sylvain 的代码开始,发现其中存在一些缺陷,例如NotImplementedError: unsupported filter /DCTDecodegetData 的异常,或者代码无法在某些页面中找到图像,因为它们位于比页面更深的层次。

这是我的代码:

import PyPDF2

from PIL import Image

import sys
from os import path
import warnings
warnings.filterwarnings("ignore")

number = 0

def recurse(page, xObject):
    global number

    xObject = xObject['/Resources']['/XObject'].getObject()

    for obj in xObject:

        if xObject[obj]['/Subtype'] == '/Image':
            size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
            data = xObject[obj]._data
            if xObject[obj]['/ColorSpace'] == '/DeviceRGB':
                mode = "RGB"
            else:
                mode = "P"

            imagename = "%s - p. %s - %s"%(abspath[:-4], p, obj[1:])

            if xObject[obj]['/Filter'] == '/FlateDecode':
                img = Image.frombytes(mode, size, data)
                img.save(imagename + ".png")
                number += 1
            elif xObject[obj]['/Filter'] == '/DCTDecode':
                img = open(imagename + ".jpg", "wb")
                img.write(data)
                img.close()
                number += 1
            elif xObject[obj]['/Filter'] == '/JPXDecode':
                img = open(imagename + ".jp2", "wb")
                img.write(data)
                img.close()
                number += 1
        else:
            recurse(page, xObject[obj])



try:
    _, filename, *pages = sys.argv
    *pages, = map(int, pages)
    abspath = path.abspath(filename)
except BaseException:
    print('Usage :
PDF_extract_images file.pdf page1 page2 page3 …')
    sys.exit()


file = PyPDF2.PdfFileReader(open(filename, "rb"))

for p in pages:    
    page0 = file.getPage(p-1)
    recurse(p, page0)

print('%s extracted images'% number)

解决方案 11:

经过一番搜索,我发现以下脚本对我的 PDF 非常有效。它只处理 JPG,但对我未受保护的文件却非常有效。而且它不需要任何外部库。

不承担任何责任,该脚本源自 Ned Batchelder,而不是我。Python3 代码:从 pdf 中提取 jpg。快速而粗略

import sys

with open(sys.argv[1],"rb") as file:
    file.seek(0)
    pdf = file.read()

startmark = b"xffxd8"
startfix = 0
endmark = b"xffxd9"
endfix = 2
i = 0

njpg = 0
while True:
    istream = pdf.find(b"stream", i)
    if istream < 0:
        break
    istart = pdf.find(startmark, istream, istream + 20)
    if istart < 0:
        i = istream + 20
        continue
    iend = pdf.find(b"endstream", istart)
    if iend < 0:
        raise Exception("Didn't find end of stream!")
    iend = pdf.find(endmark, iend - 20)
    if iend < 0:
        raise Exception("Didn't find end of JPG!")

    istart += startfix
    iend += endfix
    print("JPG %d from %d to %d" % (njpg, istart, iend))
    jpg = pdf[istart:iend]
    with open("jpg%d.jpg" % njpg, "wb") as jpgfile:
        jpgfile.write(jpg)

    njpg += 1
    i = iend

解决方案 12:

我为自己的程序做了这件事,发现最好的库是 PyMuPDF。它可以让您找出每页上每个图像的“外部参照”编号,并使用它们从 PDF 中提取原始图像数据。

import fitz
from PIL import Image
import io

filePath = "path/to/file.pdf"
#opens doc using PyMuPDF
doc = fitz.Document(filePath)

#loads the first page
page = doc.loadPage(0)

#[First image on page described thru a list][First attribute on image list: xref n], check PyMuPDF docs under getImageList()
xref = page.getImageList()[0][0]

#gets the image as a dict, check docs under extractImage 
baseImage = doc.extractImage(xref)

#gets the raw string image data from the dictionary and wraps it in a BytesIO object before using PIL to open it
image = Image.open(io.BytesIO(baseImage['image']))

#Displays image for good measure
image.show()

不过,一定要查看文档。

解决方案 13:

更简单的解决方案:

使用 poppler-utils 包。要安装它,请使用 homebrew(homebrew 是 MacOS 专用的,但您可以在此处找到适用于 Widows 或 Linux 的 poppler-utils 包:https: //poppler.freedesktop.org/)。下面的第一行代码使用 homebrew 安装 poppler-utils。安装后,第二行(从命令行运行)从 PDF 文件中提取图像并将其命名为“image*”。要从 Python 内部运行此程序,请使用 os 或 subprocess 模块。第三行是使用 os 模块的代码,下面是使用 subprocess 的示例(run() 函数需要 python 3.5 或更高版本)。更多信息请见:https: //www.cyberciti.biz/faq/easily-extract-images-from-pdf-file/

brew install poppler

pdfimages file.pdf image

import os
os.system('pdfimages file.pdf image')

或者

import subprocess
subprocess.run('pdfimages file.pdf image', shell=True)

解决方案 14:

阅读完使用pyPDF2 的帖子后。

使用@sylvain 的代码时出现的错误NotImplementedError: unsupported filter /DCTDecode一定来自该方法.getData():使用@Alex Paramonov 的方法可以解决此问题._data

到目前为止,我只遇到过“DCTDecode”案例,但我正在分享包含来自不同帖子的注释的改编代码:来自zilb@Alex Paramonov 的sub_obj['/Filter']列表,来自@mxl 的注释。

希望可以帮助pyPDF2用户。代码如下:

    import sys
    import PyPDF2, traceback
    import zlib
    try:
        from PIL import Image
    except ImportError:
        import Image

    pdf_path = 'path_to_your_pdf_file.pdf'
    input1 = PyPDF2.PdfFileReader(open(pdf_path, "rb"))
    nPages = input1.getNumPages()

    for i in range(nPages) :
        page0 = input1.getPage(i)

        if '/XObject' in page0['/Resources']:
            try:
                xObject = page0['/Resources']['/XObject'].getObject()
            except :
                xObject = []

            for obj_name in xObject:
                sub_obj = xObject[obj_name]
                if sub_obj['/Subtype'] == '/Image':
                    zlib_compressed = '/FlateDecode' in sub_obj.get('/Filter', '')
                    if zlib_compressed:
                       sub_obj._data = zlib.decompress(sub_obj._data)

                    size = (sub_obj['/Width'], sub_obj['/Height'])
                    data = sub_obj._data#sub_obj.getData()
                    try :
                        if sub_obj['/ColorSpace'] == '/DeviceRGB':
                            mode = "RGB"
                        elif sub_obj['/ColorSpace'] == '/DeviceCMYK':
                            mode = "CMYK"
                            # will cause errors when saving (might need convert to RGB first)
                        else:
                            mode = "P"

                        fn = 'p%03d-%s' % (i + 1, obj_name[1:])
                        if '/Filter' in sub_obj:
                            if '/FlateDecode' in sub_obj['/Filter']:
                                img = Image.frombytes(mode, size, data)
                                img.save(fn + ".png")
                            elif '/DCTDecode' in sub_obj['/Filter']:
                                img = open(fn + ".jpg", "wb")
                                img.write(data)
                                img.close()
                            elif '/JPXDecode' in sub_obj['/Filter']:
                                img = open(fn + ".jp2", "wb")
                                img.write(data)
                                img.close()
                            elif '/CCITTFaxDecode' in sub_obj['/Filter']:
                                img = open(fn + ".tiff", "wb")
                                img.write(data)
                                img.close()
                            elif '/LZWDecode' in sub_obj['/Filter'] :
                                img = open(fn + ".tif", "wb")
                                img.write(data)
                                img.close()
                            else :
                                print('Unknown format:', sub_obj['/Filter'])
                        else:
                            img = Image.frombytes(mode, size, data)
                            img.save(fn + ".png")
                    except:
                        traceback.print_exc()
        else:
            print("No image found for page %d" % (i + 1))

解决方案 15:

我在我的服务器上安装了ImageMagick,然后通过以下方式运行命令行调用Popen

 #!/usr/bin/python

 import sys
 import os
 import subprocess
 import settings

 IMAGE_PATH = os.path.join(settings.MEDIA_ROOT , 'pdf_input' )

 def extract_images(pdf):
     output = 'temp.png'
     cmd = 'convert ' + os.path.join(IMAGE_PATH, pdf) + ' ' + os.path.join(IMAGE_PATH, output)
     subprocess.Popen(cmd.split(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

这将为每个页面创建一个图像并将它们存储为 temp-0.png、temp-1.png……如果您得到的 pdf 只有图像而没有文本,这才是“提取”。

解决方案 16:

截至 2019 年 2 月,@sylvain 给出的解决方案(至少在我的设置上)如果不进行小幅修改则无法工作:xObject[obj]['/Filter']不是一个值,而是一个列表,因此为了使脚本正常工作,我必须修改格式检查如下:

import PyPDF2, traceback

from PIL import Image

input1 = PyPDF2.PdfFileReader(open(src, "rb"))
nPages = input1.getNumPages()
print nPages

for i in range(nPages) :
    print i
    page0 = input1.getPage(i)
    try :
        xObject = page0['/Resources']['/XObject'].getObject()
    except : xObject = []

    for obj in xObject:
        if xObject[obj]['/Subtype'] == '/Image':
            size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
            data = xObject[obj].getData()
            try :
                if xObject[obj]['/ColorSpace'] == '/DeviceRGB':
                    mode = "RGB"
                elif xObject[obj]['/ColorSpace'] == '/DeviceCMYK':
                    mode = "CMYK"
                    # will cause errors when saving
                else:
                    mode = "P"

                fn = 'p%03d-%s' % (i + 1, obj[1:])
                print '    ', fn
                if '/FlateDecode' in xObject[obj]['/Filter'] :
                    img = Image.frombytes(mode, size, data)
                    img.save(fn + ".png")
                elif '/DCTDecode' in xObject[obj]['/Filter']:
                    img = open(fn + ".jpg", "wb")
                    img.write(data)
                    img.close()
                elif '/JPXDecode' in xObject[obj]['/Filter'] :
                    img = open(fn + ".jp2", "wb")
                    img.write(data)
                    img.close()
                elif '/LZWDecode' in xObject[obj]['/Filter'] :
                    img = open(fn + ".tif", "wb")
                    img.write(data)
                    img.close()
                else :
                    print 'Unknown format:', xObject[obj]['/Filter']
            except :
                traceback.print_exc()

解决方案 17:

我在这里将所有这些都添加到了 PyPDFTK 中。

我自己的贡献是处理/Indexed这样的文件:

for obj in xObject:
    if xObject[obj]['/Subtype'] == '/Image':
        size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
        color_space = xObject[obj]['/ColorSpace']
        if isinstance(color_space, pdf.generic.ArrayObject) and color_space[0] == '/Indexed':
            color_space, base, hival, lookup = [v.getObject() for v in color_space] # pg 262
        mode = img_modes[color_space]

        if xObject[obj]['/Filter'] == '/FlateDecode':
            data = xObject[obj].getData()
            img = Image.frombytes(mode, size, data)
            if color_space == '/Indexed':
                img.putpalette(lookup.getData())
                img = img.convert('RGB')
            img.save("{}{:04}.png".format(filename_prefix, i))

请注意,/Indexed找到文件后,不能仅将其/ColorSpace与字符串进行比较,因为它以 的形式出现ArrayObject。因此,我们必须检查数组并检索索引调色板(lookup在代码中)并将其设置在 PIL Image 对象中,否则它将保持未初始化状态(零),并且整个图像显示为黑色。

我的第一反应是将它们保存为 GIF(一种索引格式),但测试结果表明 PNG 更小而且看起来一样。

当我使用 Foxit Reader PDF Printer 打印为 PDF 时,我发现了这些类型的图像。

解决方案 18:

pdfimages您也可以在 Ubuntu 中使用命令。

使用以下命令安装 poppler lib。

sudo apt install poppler-utils

sudo apt-get install python-poppler

pdfimages file.pdf image

创建的文件列表为(例如,pdf 中有两张图片)

image-000.png
image-001.png

成功了!现在你可以使用subprocess.runpython 来运行它了。

解决方案 19:

尝试下面的代码。它将从 pdf 中提取所有图像。

    import sys
    import PyPDF2
    from PIL import Image
    pdf=sys.argv[1]
    print(pdf)
    input1 = PyPDF2.PdfFileReader(open(pdf, "rb"))
    for x in range(0,input1.numPages):
        xObject=input1.getPage(x)
        xObject = xObject['/Resources']['/XObject'].getObject()
        for obj in xObject:
            if xObject[obj]['/Subtype'] == '/Image':
                size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
                print(size)
                data = xObject[obj]._data
                #print(data)
                print(xObject[obj]['/Filter'])
                if xObject[obj]['/Filter'][0] == '/DCTDecode':
                    img_name=str(x)+".jpg"
                    print(img_name)
                    img = open(img_name, "wb")
                    img.write(data)
                    img.close()
        print(str(x)+" is done")

解决方案 20:

我将解决方案重写为单个 Python 类。它应该易于使用。如果您注意到新的“/Filter”或“/ColorSpace”,则只需将其添加到内部词典中即可。

https://github.com/survtur/extract_images_from_pdf

要求:

  • Python3.6+

  • PyPDF2

  • 太平船务

解决方案 21:

使用 pypdfium2 (v4):

import pypdfium2.__main__ as pdfium_cli

pdfium_cli.api_main(["extract-images", "input.pdf", "-o", "output_dir"])

有一些不同的提取策略可供选择(参见pypdfium2 extract-images --help)。

实际的非 CLI Python API 也可用。CLI 的实现演示了它们(有关详细信息,请参阅文档):

# assuming `args` is a given options set (e. g. argparse namepsace)

import pypdfium2 as pdfium
import pypdfium2.raw as pdfium_c

pdf = pdfium.PdfDocument(args.input)

images = []
for i in args.pages:
    page = pdf.get_page(i)
    obj_searcher = page.get_objects(
        filter = (pdfium_c.FPDF_PAGEOBJ_IMAGE, ),
        max_depth = args.max_depth,
    )
    images += list(obj_searcher)

n_digits = len(str(len(images)))

for i, image in enumerate(images):
    prefix = args.output_dir / ("%s_%0*d" % (args.input.stem, n_digits, i+1))
    
    try:
        if args.use_bitmap:
            pil_image = image.get_bitmap(render=args.render).to_pil()
            pil_image.save("%s.%s" % (prefix, args.format))
        else:
            image.extract(prefix, fb_format=args.format, fb_render=args.render)
    except pdfium.PdfiumError:
        traceback.print_exc()

注意:遗憾的是,PDFium 的公共图像提取 API 非常有限,因此PdfImage.extract()远不如 pikepdf 那么智能。PdfImage.get_bitmap()不过,如果您只需要图像位图并且不打算保存图像,那么应该没问题。

(免责声明:我是 pypdfium2 的作者)

解决方案 22:

以下代码是 PyMUPDF 的更新版本:

doc = fitz.open("/Users/vignesh/Downloads/ViewJournal2244.pdf")
Images_per_page={}
for i in page:
    images=[]
    for image_box in doc[page].get_images():
        rect=doc[page].get_image_rects(image_box)
        page=doc[page].get_pixmap(matrix=fitz.Identity,clip=rect[0],dpi=None,colorspace=fitz.csRGB,alpha=True, annots=True) 
        string=page.tobytes()
        images.append(string)
    Images_per_page[i]=images

解决方案 23:

  1. 首先安装 pdf2image

pip 安装 pdf2image==1.14.0

  1. 按照以下代码从 PDF 中提取页面。

file_path="file path of PDF"
info = pdfinfo_from_path(file_path, userpw=None, poppler_path=None)
maxPages = info["Pages"]
image_counter = 0
if maxPages > 10:
    for page in range(1, maxPages, 10):
        pages = convert_from_path(file_path, dpi=300, first_page=page, 
                last_page=min(page+10-1, maxPages))
        for page in pages:
            page.save(image_path+'/' + str(image_counter) + '.png', 'PNG')
            image_counter += 1
else:
    pages = convert_from_path(file_path, 300)
    for i, j in enumerate(pages):
        j.save(image_path+'/' + str(i) + '.png', 'PNG')

希望它可以帮助那些希望按照 PDF 页面轻松将 PDF 文件转换为图像的编码人员。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用