101

ネイティブ解像度とフォーマットで、PDFドキュメントからすべての画像を抽出するにはどうすればよいですか?(tiffをtiffとして、jpegをjpegとしてなど、リサンプリングせずに抽出することを意味します)。レイアウトは重要ではありません。ソース画像がページにあるかどうかは関係ありません。

私はPython2.7を使用していますが、必要に応じて3.xを使用できます。

4

21 に答える 21

33

多くの場合、PDFでは、画像はそのまま保存されます。たとえば、jpgが挿入されたPDFには、抽出されたときに有効なjpgファイルであるバイト範囲が中央にあります。これを使用して、PDFからバイト範囲を非常に簡単に抽出できます。私はこれについて少し前にサンプルコードで書いた:PDFからJPGを抽出する

于 2010-04-23T00:08:43.723 に答える
25

CCITTFaxDecode フィルター用の PyPDF2 を使用する Python の場合:

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()
于 2016-01-01T10:34:50.487 に答える
18

Libpoppler には、まさにこれを行う「pdfimages」というツールが付属しています。

(ubuntu システムでは poppler-utils パッケージにあります)

http://poppler.freedesktop.org/

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

Windows バイナリ: http://blog.alivate.com.au/poppler-windows/

于 2010-08-29T21:03:01.517 に答える
5

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_toPDF での画像のエンコード方法に基づいて、ファイル拡張子が自動的に選択されます。

必要に応じて、抽出された画像に関する詳細を印刷することもできます。

        # 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 ファイルで画像を置き換えるなど、画像でできることの詳細については、ドキュメントを参照してください。

于 2021-02-09T13:03:57.220 に答える
4

サーバーに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を取得した場合の「抽出」にすぎません。

于 2012-03-29T08:40:52.843 に答える
4

いくつか検索した後、私の PDF で非常にうまく機能する次のスクリプトを見つけました。JPG のみに対処しますが、保護されていないファイルで完全に機能しました。また、外部ライブラリは必要ありません。

名誉を傷つけないように言っておきますが、このスクリプトは私ではなく、ネッド バチェルダーが作成したものです。Python3 コード: pdf から jpg を抽出します。速くて汚い

import sys

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

startmark = b"\xff\xd8"
startfix = 0
endmark = b"\xff\xd9"
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
于 2017-06-07T01:09:27.043 に答える
1

これらすべてを PyPDFTK hereにまとめて追加しました。

私自身の貢献は、/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比較することはできないことに注意してください。そのため、配列をチェックして、インデックス付きパレット (コード内) を取得し、それを PIL Image オブジェクトに設定する必要があります。そうしないと、初期化されていない (ゼロ) ままになり、画像全体が黒く表示されます。/ColorSpaceArrayObjectlookup

私の最初の本能は、GIF (インデックス付き形式) として保存することでしたが、私のテストでは、PNG の方が小さく、同じように見えることがわかりました。

Foxit Reader PDF Printer を使用して PDF に印刷すると、これらのタイプの画像が見つかりました。

于 2016-03-23T01:38:54.500 に答える
0
  1. 最初にpdf2imageをインストールします

    pip install pdf2image==1.14.0

  2. 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ファイルを画像に簡単に変換することを探しているコーダーに役立つことを願っています.

于 2020-11-23T11:14:45.763 に答える