Extraia uma página de um pdf como um jpeg

95

No código python, como salvar com eficiência uma determinada página em um pdf como um arquivo jpeg? (Caso de uso: tenho um servidor da web python flask onde os pdf-s serão carregados e os jpeg-s correspondentes a cada página são lojas.)

Essa solução está perto, mas o problema é que ela não converte a página inteira para jpeg.

vishvAs vAsuki
fonte
1
Dependendo da imagem, pode ser melhor extrair como um PNG. Isso se aplicaria se a página contiver principalmente texto.
Paul Rooney

Respostas:

125

A biblioteca pdf2image pode ser usada.

Você pode instalá-lo simplesmente usando,

pip install pdf2image

Depois de instalado, você pode usar o seguinte código para obter imagens.

from pdf2image import convert_from_path
pages = convert_from_path('pdf_file', 500)

Salvando páginas em formato jpeg

for page in pages:
    page.save('out.jpg', 'JPEG')

Edit: o repositório Github pdf2image também menciona que usa pdftoppme que requer outras instalações:

pdftoppm é o software que faz a mágica real. Ele é distribuído como parte de um pacote maior chamado poppler . Os usuários do Windows terão que instalar o poppler para Windows . Os usuários de Mac terão que instalar o poppler para Mac . Os usuários do Linux terão o pdftoppm pré-instalado com a distro (testado no Ubuntu e Archlinux) se não estiver, execute sudo apt install poppler-utils.

Você pode instalar a versão mais recente no Windows usando o anaconda, fazendo:

conda install -c conda-forge poppler

observação: versões do Windows até 0,67 estão disponíveis em http://blog.alivate.com.au/poppler-windows/, mas observe que 0,68 foi lançado em agosto de 2018, portanto, você não receberá os recursos ou correções de bugs mais recentes.

Keval Dave
fonte
4
Oi, o poppler é apenas um arquivo compactado, não instala nada, o que se deve fazer com os arquivos dll ou bin?
gaurwraith
@gaurwraith: Use o seguinte link para poppler . Por algum motivo, o link na descrição de Rodrigo não é o mesmo do repositório do github.
Tobias,
@Keval Dave Você instalou o poppler e experimentou o pdf2image na máquina Windows? Qual Windows, por favor?
SKR
1
@elPastor você pode adicionar first_page e last_page no argumento da função conver_from_path para converter apenas a página especificada
Keval Dave
1
@Jacob 500 é o dpi. Ele compensa a resolução necessária e o cálculo disponível. Em minhas experiências, 500 funcionou bem na maioria dos casos, enquanto 300 me deram imagens de baixo rez.
Keval Dave
36

Eu encontrei esta solução simples, PyMuPDF , saída para arquivo png. Observe que a biblioteca é importada como "fitz", um nome histórico para o mecanismo de renderização que ela usa.

import fitz

pdffile = "infile.pdf"
doc = fitz.open(pdffile)
page = doc.loadPage(0)  # number of page
pix = page.getPixmap()
output = "outfile.png"
pix.writePNG(output)
JJPty
fonte
1
Por favor, adicione explicação à sua resposta.
Shanteshwar Inde,
1
Uma boa biblioteca e instala no Windows 10 sem problemas (sem necessidade de rodas). github.com/pymupdf
Camarada Che
7
Esta é a melhor resposta. Este foi o único código que não exigiu uma instalação adicional no meu sistema operacional. Os scripts Python devem se concentrar em trabalhar dentro do sistema Python. Não precisei instalar poppler, pdftoppm, imageMagick ou ghostscript, etc. (Python 3.6)
ZStoneDPM
1
Na verdade requer outra instalação (biblioteca fitz, importada sem nem mesmo ser referenciada e suas dependências), essa resposta está incompleta (como todas as respostas desta pergunta)
Tommaso Guerrini
1
@JJPty Em vez do arquivo pdf obtido do caminho, podemos usar o pdfurl? Além disso, é possível que o arquivo png seja um arquivo in-stream em vez de um arquivo png de saída?
Shubham Agrawal
18

A biblioteca Python pdf2image(usada na outra resposta) na verdade não faz muito mais do que apenas iniciar pdttoppm com subprocess.Popen, então aqui está uma versão curta fazendo isso diretamente:

PDFTOPPMPATH = r"D:\Documents\software\____PORTABLE\poppler-0.51\bin\pdftoppm.exe"
PDFFILE = "SKM_28718052212190.pdf"

import subprocess
subprocess.Popen('"%s" -png "%s" out' % (PDFTOPPMPATH, PDFFILE))

Aqui está o link de instalação do Windows para pdftoppm(contido em um pacote chamado poppler): http://blog.alivate.com.au/poppler-windows/

Basj
fonte
4
Olá, o link de instalação do Windows para pdftoppm é apenas um punhado de arquivos compactados. O que você precisa fazer com eles para que funcionem? Obrigado!
gaurwraith
14

Não há necessidade de instalar o Poppler em seu sistema operacional. Isso vai funcionar:

pip instalar varinha

from wand.image import Image

f = "somefile.pdf"
with(Image(filename=f, resolution=120)) as source: 
    for i, image in enumerate(source.sequence):
        newfilename = f[:-4] + str(i + 1) + '.jpeg'
        Image(image).save(filename=newfilename)
DevB2F
fonte
10
A biblioteca ImageMagick precisa ser instalada para funcionar no wand.
Neeraj Gulia
2
Tentei fazer isso e também precisei instalar o Ghostscript (usando Windows 10 e Python 3.7). Fiz e funcionou perfeitamente.
jcf
1
para que serve f [: - 4]? não é referenciado em nenhum outro lugar
Ari,
@Ari f [: - 4] cortará ".pdf" do nome do arquivo (divisão da string) para criar um novo nome de arquivo com outro ext.
Fabian
9

@gaurwraith, instale o poppler para Windows e use o pdftoppm.exe da seguinte maneira:

  1. Baixe o arquivo zip com os binários / dlls mais recentes do Poppler em http://blog.alivate.com.au/poppler-windows/ e descompacte em uma nova pasta em sua pasta de arquivos de programa. Por exemplo: "C: \ Arquivos de programas (x86) \ Poppler".

  2. Adicione "C: \ Arquivos de programas (x86) \ Poppler \ poppler-0.68.0 \ bin" à sua variável de ambiente SYSTEM PATH.

  3. Da linha cmd instale o módulo pdf2image -> "pip install pdf2image".

  4. Ou, alternativamente, execute diretamente o pdftoppm.exe do seu código usando o módulo de subprocesso do Python, conforme explicado pelo usuário Basj.

@vishvAs vAsuki, este código deve gerar os jpgs que você deseja através do módulo de subprocesso para todas as páginas de um ou mais pdfs em uma determinada pasta:

import os, subprocess

pdf_dir = r"C:\yourPDFfolder"
os.chdir(pdf_dir)

pdftoppm_path = r"C:\Program Files (x86)\Poppler\poppler-0.68.0\bin\pdftoppm.exe"

for pdf_file in os.listdir(pdf_dir):

    if pdf_file.endswith(".pdf"):

        subprocess.Popen('"%s" -jpeg %s out' % (pdftoppm_path, pdf_file))

Ou usando o módulo pdf2image:

import os
from pdf2image import convert_from_path

pdf_dir = r"C:\yourPDFfolder"
os.chdir(pdf_dir)

    for pdf_file in os.listdir(pdf_dir):

        if pdf_file.endswith(".pdf"):

            pages = convert_from_path(pdf_file, 300)
            pdf_file = pdf_file[:-4]

            for page in pages:

               page.save("%s-page%d.jpg" % (pdf_file,pages.index(page)), "JPEG")
photek1944
fonte
Isso ajudou muito. Obrigado!
Sreekiran
1
Esta deve ser realmente a resposta aceita. Mostra o que fazer com os binários instalados para Poppler
Kunj Mehta
3

É um utilitário chamado pdftojpg que pode ser usado para converter o pdf em img

Você pode encontrar o código aqui https://github.com/pankajr141/pdf2jpg

from pdf2jpg import pdf2jpg
inputpath = r"D:\inputdir\pdf1.pdf"
outputpath = r"D:\outputdir"
# To convert single page
result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="1")
print(result)

# To convert multiple pages
result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="1,0,3")
print(result)

# to convert all pages
result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="ALL")
print(result)
Pato
fonte
2
essa coisa de java acabou de excluir toda a minha pasta cheia de scripts de python manipulando pdf ....?
Ulf Gjerdingen
2

GhostScript executa muito mais rápido do que Poppler para um sistema baseado em Linux.

A seguir está o código para conversão de pdf em imagem.

def get_image_page(pdf_file, out_file, page_num):
    page = str(page_num + 1)
    command = ["gs", "-q", "-dNOPAUSE", "-dBATCH", "-sDEVICE=png16m", "-r" + str(RESOLUTION), "-dPDFFitPage",
               "-sOutputFile=" + out_file, "-dFirstPage=" + page, "-dLastPage=" + page,
               pdf_file]
    f_null = open(os.devnull, 'w')
    subprocess.call(command, stdout=f_null, stderr=subprocess.STDOUT)

GhostScript pode ser instalado no macOS usando brew install ghostscript

As informações de instalação para outras plataformas podem ser encontradas aqui . Se ainda não estiver instalado em seu sistema.

Keval Dave
fonte
0

Eu uso uma opção (talvez) muito mais simples de pdf2image:

cd $dir
for f in *.pdf
do
  if [ -f "${f}" ]; then
    n=$(echo "$f" | cut -f1 -d'.')
    pdftoppm -scale-to 1440 -png $f $conv/$n
    rm $f
    mv  $conv/*.png $dir
  fi
done

Esta é uma pequena parte de um script bash em um loop para o uso de um dispositivo de casting estreito. Verifica a cada 5 segundos os arquivos PDF adicionados (todos) e os processa. Isso é para um dispositivo de demonstração, no final a conversão será feita em um servidor remoto. Converter para .PNG agora, mas .JPG também é possível.

Essa conversão, junto com as transições no formato A4, exibindo um vídeo, dois textos de rolagem suave e um logotipo (com transição em três versões), define o Pi3 para quase 4x 100% cpu-load ;-)

Robert
fonte
0
from pdf2image import convert_from_path
import glob

pdf_dir = glob.glob(r'G:\personal\pdf\*')  #your pdf folder path
img_dir = "G:\\personal\\img\\"           #your dest img path

for pdf_ in pdf_dir:
    pages = convert_from_path(pdf_, 500)
    for page in pages:
        page.save(img_dir+pdf_.split("\\")[-1][:-3]+"jpg", 'JPEG')
Saiprasad Bhatwadekar
fonte
Essa seria uma resposta melhor se você explicasse como o código fornecido responde à pergunta.
pppery de
1
@pppery Python é bastante legível, os comentários indicam a pasta de origem e a pasta de saída, o resto é lido como o inglês.
Ari,
-1

Aqui está uma solução que não requer bibliotecas adicionais e é muito rápida. Isso foi encontrado em: https://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html# Eu adicionei o código em uma função para torná-lo mais conveniente.

def convert(filepath):
    with open(filepath, "rb") as file:
        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
        jpg = pdf[istart:iend]
        newfile = "{}jpg".format(filepath[:-3])
        with open(newfile, "wb") as jpgfile:
            jpgfile.write(jpg)

        njpg += 1
        i = iend

        return newfile

Chame convert com o caminho do pdf como argumento e a função criará um arquivo .jpg no mesmo diretório

moo5e
fonte
1
Essa técnica parece que extrai imagens que foram incorporadas ao arquivo, em vez de rasterizar uma página do arquivo como uma imagem que é o que o questionador deseja.
Josh Gallagher