파이썬에서 리샘플링하지 않고 PDF에서 이미지를 추출 하시겠습니까?


81

기본 해상도와 형식으로 pdf 문서에서 모든 이미지를 어떻게 추출 할 수 있습니까? (즉, tiff를 tiff로, jpeg를 jpeg 등으로 추출하고 리샘플링하지 않음). 레이아웃은 중요하지 않습니다. 소스 이미지가 페이지에 있는지 상관 없습니다.

파이썬 2.7을 사용하고 있지만 필요한 경우 3.x를 사용할 수 있습니다.


감사. "이미지가 PDF에 저장되는 방법"URL이 작동하지 않았지만 다음과 같이 보입니다 : jpedal.org/PDFblog/2010/04/…
nealmcb 2011

있습니다 JPedal의 이라고하지 자바 라이브러리 PDF 잘린 이미지 추출 . 저자 인 Mark Stephens는 이미지가 PDF에 저장되는 방법에 대한 간결하고 높은 수준의 개요를 제공 하여 Python 추출기를 구축하는 데 도움이 될 수 있습니다.
matt wilkie 2015

답변:


47

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

더 많은 리소스를 보려면 여기를 참조하십시오.


2
이것은 훌륭하게 작동합니다! ( pip install pymudf분명히 먼저 필요)
Basj

9
* pip install pymupdf위의 설치가 실패하는 이유를 궁금해하는 동료 Google 직원을 위해
VSZM

9
대신에 pip install pymupdf노력하고 pip install PyMuPDF 더 많은 정보를
Damotorie

1
이 코드를 사용하면 RuntimeError: pixmap must be grayscale or rgb to write as png누구든지 도울 수 있습니까?
vault

5
@vault이 주석은 오래되었습니다. 원래 조건으로는 CMYK 이미지를 올바르게 찾지 못하므로 "if pix.n <5"를 "if pix.n-pix.alpha <4"로 변경해야합니다.
Oringa

41

PyPDF2 및 Pillow 라이브러리가있는 Python에서는 간단합니다.

import PyPDF2

from PIL import Image

if __name__ == '__main__':
    input1 = PyPDF2.PdfFileReader(open("input.pdf", "rb"))
    page0 = input1.getPage(0)
    xObject = page0['/Resources']['/XObject'].getObject()

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

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

14
처음에이 흥분하지만, 토 NotImplementedError: unsupported filter /DCTDecode또는 ... /JPXDecode에서 xObject[obj].getData()처음 몇 PDF 파일의 I 시험에서. 세부 사항 : gist.github.com/maphew/fe6ba4bf9ed2bc98ecf5
matt wilkie 2015

4
최근에 PyPDF2 라이브러리에 '/ DCTDecode'수정을 푸시했습니다. 내 저장소를 사용할 수 있습니다 : github.com/sylvainpelissier/PyPDF2 가 메인 브랜치에 통합되어있는 동안.
sylvain

1
업데이트 해주셔서 감사합니다. 요점이 업데이트되었습니다. ValueError: not enough image datadctdecode 임베디드 이미지와 unsupported filter /JPXDecode다른 pdf를 얻 습니다 .
매트 윌키

1
전진! dctdecode pdf는 이제 오류없이 처리됩니다 (때로는 출력 이미지가 거꾸로되어 있음). 그러나 이제 JPXDecode 파일이 KeyError:/Filter대신 발생합니다. 그에 따라 요점을 업데이트했습니다. PDF 파일은 'net. 요점에는 소스 링크가 있습니다.
Matt wilkie 2015

29
"그것은이다 간단한 ... "
mlissner

34

종종 PDF에서 이미지는 그대로 저장됩니다. 예를 들어, jpg가 삽입 된 PDF는 추출 될 때 유효한 jpg 파일이되는 중간 어딘가에 바이트 범위가 있습니다. 이것을 사용하여 PDF에서 바이트 범위를 매우 간단하게 추출 할 수 있습니다. 얼마 전에 샘플 코드를 사용하여 이에 대해 썼습니다 . PDF에서 JPGs 추출 .


1
고마워 Ned. 내가 필요한 특정 pdf가 jpeg in-situ를 사용하지 않는 것처럼 보이지만 다른 항목과 일치하는 경우 샘플을 보관할 것입니다.
Matt Wilkie

3
코드에서 몇 가지를 설명해 주시겠습니까? 예를 들어, 왜 먼저 "stream"을 검색 한 다음 startmark? startmark이것이 JPG의 시작이므로 검색을 시작할 수 있습니까? 과의 지점 무슨 startfix변수가, 당신은 모든 ..에서 변경 해달라고
user3599803

이것은 이미지를 추출하려는 PDF에서 완벽하게 작동했습니다. (다른 사람에게 도움이되는 경우에는 그의 코드를 .py 파일로 저장 한 다음 Python 2.7.18을 설치 / 사용하여 실행하고 단일 명령 줄 인수로 내 PDF 경로를 전달했습니다.)
matt

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()

이것은 나를 위해 즉시 작동했으며 매우 빠릅니다!! 내 모든 이미지가 거꾸로 나왔지만 OpenCV로 수정할 수있었습니다. 나는 그것을 호출하기 위해 ImageMagick의 convert사용 subprocess을 사용해 왔지만 고통스럽게 느립니다. 이 솔루션을 공유해 주셔서 감사합니다
crld

2
마찬가지로 다른 지적 당신이 tiff_header_struct읽어야합니다 '<' + '2s' + 'H' + 'L' + 'H' + 'HHLL' * 8 + 'L'. 특히 'L'끝에 유의하십시오 .
디스펜서

이것에 대한 도움이 필요하시면 : stackoverflow.com/questions/55899363/…
Aakash Basu

17

Libpoppler는이를 정확히 수행하는 "pdfimages"라는 도구와 함께 제공됩니다.

(우분투 시스템에서는 poppler-utils 패키지에 있습니다)

http://poppler.freedesktop.org/

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

Windows 바이너리 : http://blog.alivate.com.au/poppler-windows/


누군가 pdfimages가 서브 시스템에 설치되는 것에 의존하지 않는 Python 모듈을 발견하면 좋겠습니다 .
user1717828

그것은 출력 이미지 pagewise하지 않습니다
알록 나약에게

10

나는 사용하기 매우 쉽기 때문에 광산 수레를 선호합니다. 아래 스 니펫은 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)

안녕하세요, minecart는 완벽하게 작동하지만 작은 문제가 있습니다. 때때로 이미지의 레이아웃이 변경됩니다 (가로-> 세로). 내가 이것을 어떻게 피할 수 있는지 아십니까? 감사!
Sha Li

minecart를 사용하면 pdfminer.pdftypes.PDFNotImplementedError : 지원되지 않는 필터 : / CCITTFaxDecode
Javi12

7

다음은 PDF에서 모든 이미지를 재귀 적으로 가져와 PIL로 읽는 2019의 내 버전입니다. 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

이 코드는 거의 수정없이 저에게 효과적이었습니다. 감사합니다.
xax 2010

6

@sylvain 코드에서 시작했습니다. 예외와 같은 몇 가지 결함이있었습니다. NotImplementedError: unsupported filter /DCTDecode getData 거나 코드가 페이지보다 더 깊은 수준에 있기 때문에 일부 페이지에서 이미지를 찾지 못했다는 사실이있었습니다.

내 코드가 있습니다.

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 :\nPDF_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)

이 코드는 '/ ICCBased' '/ FlateDecode'필터링 된 이미지에서 실패합니다img = Image.frombytes(mode, size, data) ValueError: not enough image data
GrantD71

1
@ GrantD71 저는 전문가가 아니며 ICCBased에 대해 들어 본 적이 없습니다. 또한 입력을 제공하지 않으면 오류를 재현 할 수 없습니다.
Labo

나는 KeyError: '/ColorSpace', 그래서 나는 당신의 라인을 DeviceRGB로 바꿀 것 if '/ColorSpace' not in xObject[obj] or xObject[obj]['/ColorSpace'] == '/DeviceRGB':입니다. 어쨌든 이미지가 아마도 PNG (확실하지 않음)이기 때문에 결국 이것은 저에게 효과가 없었습니다.
Basj

@Basj 내 코드는 PNG에서도 작동하도록되어 있습니다. 의 가치는 xObject[obj]['/Filter']무엇입니까?
Labo

2
Python 2와 3 모두에서 작동하도록 코드를 수정했습니다. Ronan Paixão의 / Indexed 변경 사항도 구현했습니다. 또한 필터 if / elif를 같지 않고 'in'으로 변경했습니다. / Filter 유형 [ '/ ASCII85Decode', '/ FlateDecode']의 PDF가 있습니다. 또한 파일에 쓰는 대신 이미지 blob을 반환하도록 함수를 변경했습니다. 업데이트 된 코드는 여기에서 찾을 수 있습니다 : gist.github.com/gstorer/f6a9f1dfe41e8e64dcf58d07afa9ab2a
Gerald

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를 얻은 경우에만 '추출'됩니다.


1
Image magick는 고스트 스크립트를 사용하여이를 수행합니다. 이 게시물 에서 이미지 magick가 커버 아래에서 사용하는 ghostscript 명령을 확인할 수 있습니다 .
Filipe Correia

때때로 렌더링이 정말 나쁘다고 말해야합니다. poppler를 사용하면 문제없이 작동합니다.
Raffi

4

몇 가지 검색 후 내 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"\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

1
흥미로워 보입니다. 어디서 찾았 어? (그리고, 게시물에 서식하는 것은 조금 엉망입니다 언밸런스 따옴표 나는 생각한다..)
매트 윌키

1
nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html 당신은 ... 여기에 원래 게시물을 찾을 수 있습니다
최대 AH Hartvigsen

4

훨씬 더 쉬운 솔루션 :

poppler-utils 패키지를 사용하십시오. 설치하려면 homebrew를 사용하십시오 (homebrew는 MacOS에 따라 다르지만 여기에서 Widows 또는 Linux 용 poppler-utils 패키지를 찾을 수 있습니다 : https://poppler.freedesktop.org/ ). 아래 코드의 첫 줄은 homebrew를 사용하여 poppler-utils를 설치합니다. 설치 후 두 번째 줄 (명령 줄에서 실행)은 PDF 파일에서 이미지를 추출하고 이름을 "image *"로 지정합니다. Python 내에서이 프로그램을 실행하려면 os 또는 subprocess 모듈을 사용하십시오. 세 번째 줄은 os 모듈을 사용하는 코드이며 그 아래에는 하위 프로세스 (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)

1
감사합니다 Colton. Homebrew는 MacOS 전용입니다. 지침이 플랫폼에 따라 다르면 OS를 기록하는 것이 좋습니다.
맷 윌키

@mattwilkie-감사합니다. 내 대답에서 이것을 주목할 것입니다.
Colton Hicks

3

내 프로그램을 위해이 작업을 수행했으며 사용하기에 가장 좋은 라이브러리는 PyMuPDF라는 것을 알았습니다. 각 페이지에있는 각 이미지의 "xref"번호를 찾아 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()

그래도 문서를 확실히 확인하십시오.


최상의 옵션 IMO : fitzWin 10에 설치 한 후 다음 오류가 발생했습니다. ModuleNotFoundError : 'frontend'라는 모듈이 없습니다.이 오류는 다음 pip install PyMuPDF과 같이 설치 하여 쉽게 해결할 수 있습니다. stackoverflow.com/questions/56467667/…
Peter

3

글쎄, 나는 몇 주 동안 이것으로 어려움을 겪어 왔으며 이러한 답변 중 많은 것이 나를 도와 주었지만 항상 누락 된 것이 있었고 분명히 여기에 아무도 jbig2 인코딩 이미지에 문제가 없었습니다 .

내가 스캔 할 PDF 묶음에서 jbig2로 인코딩 된 이미지는 매우 인기가 있습니다.

내가 이해하는 한 종이를 스캔하여 jbig2 인코딩 이미지로 가득 찬 PDF 파일로 변환하는 복사 / 스캔 기계가 많이 있습니다.

그래서 여러 날의 테스트 끝에 오래 전에 dkagedal이 제안한 답변을 찾기로 결정했습니다.

다음은 Linux에 대한 단계별 설명입니다. (다른 OS가 있다면 Linux 도커 를 사용하는 것이 훨씬 쉬울 것입니다.)

첫 번째 단계:

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와 같은 이름의 파일이 있습니다.

이 2 개의 파일은 헤더 용과 데이터 용으로 하나씩 2 개의 다른 파일에 저장된 jbig2로 인코딩 된 하나의 이미지를 포함합니다.

다시 나는 그 파일을 읽을 수있는 것으로 변환하는 방법을 찾으려고 많은 날을 잃었고 마침내 jbig2dec라는이 도구를 발견했습니다

따라서 먼저이 마법 도구를 설치해야합니다.

apt-get install jbig2dec

그런 다음 다음을 실행할 수 있습니다.

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

마침내 추출 된 모든 이미지를 유용한 것으로 변환 할 수 있습니다.

행운을 빕니다!


이것은 유용한 정보이며 방금 한 것처럼 문서화하고 공유해야합니다 . +1. 그러나 나는이 질문의 포인트입니다 자신의 새로운 질문과 주소 파이썬에서이 일을하지 않기 때문에 다음 자동 응답으로 게시하시기 바랍니다 (이 같은 게시물을 링크 교차 자유롭게 되어 관련합니다.)
매트 윌키를

안녕하세요 @mattwilkie, 조언에 감사드립니다. 질문이 있습니다. stackoverflow.com/questions/60851124/…
Marco

2

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 '\t', 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()

1
DCTDecode CCITTFaxDecode 필터는 아직 구현되지 않았습니다.
Abhimanyu

안녕하세요 @Modem Rakesh goud,이 오류를 유발 한 PDF 파일을 제공해 주시겠습니까? 감사합니다!
mxl

불행히도 그 pdf를 공유 할 수 없습니다.
모뎀 Rakesh goud

또는 당신은 결국 그냥 나에게주고, PDF 파일의 일부를 추출하고 해당 부분을 제공하거나 할 수 아크로뱃 (안 리더,하지만 PRO 버전), 또는 대안 다른 PDF 편집 프로그램 같은 프로그램의 소지가 될 것입니다 traceback.print_exc()의를 주어진 에러 라인, 내가 그것을 유발 한 것을 볼 수 있도록; 또는이 사이트에서 다른 솔루션을 선택할 수 있습니다. 여기에 제공된 솔루션은 PDF에서 1 : 1 무손실 데이터 추출을 제공하는 데 초점을 맞추고 있으며 원하는 것이 아닐 수도 있습니다. 감사합니다!
mxl

1

여기 에 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 이미지 개체에 설정해야합니다. 그렇지 않으면 초기화되지 않은 상태 (0)로 유지되고 전체 이미지가 검은 색으로 표시됩니다.

내 첫 번째 본능은 GIF (인덱싱 된 형식)로 저장하는 것이었지만 테스트 결과 PNG가 더 작고 동일한 방식으로 보입니다.

Foxit Reader PDF 프린터로 PDF로 인쇄 할 때 이러한 유형의 이미지를 발견했습니다.


1

pdfimagesUbuntu에서도 명령을 사용할 수 있습니다 .

아래 명령을 사용하여 poppler lib를 설치하십시오.

sudo apt install poppler-utils

sudo apt-get install python-poppler

pdfimages file.pdf image

생성 된 파일 목록은 다음과 같습니다 (예 : pdf에 두 개의 이미지가 있음).

image-000.png
image-001.png

효과가있다 ! 이제 a subprocess.run를 사용하여 파이썬에서 실행할 수 있습니다 .


1

pyPDF2를 사용하여 게시물을 읽은 후 .

@sylvain의 코드를 사용하는 동안 발생하는 오류 NotImplementedError: unsupported filter /DCTDecode는 메소드에서 비롯된 것이어야합니다 .getData().._data . 대신 @Alex Paramonov를 .

지금까지 "DCTDecode"사례 만 만났지만 다른 게시물의 발언을 포함하는 수정 된 코드를 공유하고 있습니다. From zilbby @Alex Paramonov,sub_obj['/Filter'] 의 목록입니다.

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))

0

아래 코드를 시도하십시오. 그것은 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")

0
  1. 먼저 pdf2image 설치

    pip 설치 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 파일을 이미지로 쉽게 변환하려는 코더가 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.