Encontrando um erro compression error -2
. Seria ótimo se alguém pudesse fornecer algumas dicas
Anexou o PDF com o problema:
5_EN.pdf
Mensagem de erro:
Processing Pages: 1/28...mupdf: compression error -2
Traceback (most recent call last):
File "/Users/erikchan/Downloads/convert.py", line 10, in <module>
parse(pdf_files[i], docx_files[i])
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pdf2docx/main.py", line 31, in parse
cv.make_docx(indexes, multi_processing)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pdf2docx/converter.py", line 118, in make_docx
self._make_docx(page_indexes)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pdf2docx/converter.py", line 192, in _make_docx
self.initialize(page).parse().make_page(self.doc_docx)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pdf2docx/converter.py", line 172, in initialize
images, paths = self._paths_extractor.extract_paths(page)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pdf2docx/shape/Path.py", line 61, in extract_paths
image = largest.to_image(page) if largest.contains_curve else None
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pdf2docx/shape/Path.py", line 140, in to_image
return ImagesExtractor.clip_page(page, bbox, zoom)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pdf2docx/image/Image.py", line 60, in clip_page
return cls.to_raw_dict(image, bbox)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pdf2docx/image/Image.py", line 50, in to_raw_dict
'image': image.getPNGData()
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/fitz/fitz.py", line 5899, in getPNGData
barray = self._getImageData(1)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/fitz/fitz.py", line 5868, in _getImageData
return _fitz.Pixmap__getImageData(self, format)
RuntimeError: compression error -2
Obrigado por fornecer este caso.
Muitos gráficos vetoriais, ou seja, path
como uma linha, curva e sua combinação, existem em seu pdf. No entanto, atualmente o caminho de recorte é ignorado por esta biblioteca devido a problemas técnicos ao extrair esses caminhos do pdf. Alguns caminhos estão fora da página sem serem cortados, o que resulta neste problema de compression error -2
.
Além disso, mais dois problemas para converter este pdf:
A cor do caminho está incorreta. Eu acho que a causa raiz é que atualmente apenas Device Color Space
(Gray / RGB / CMYK) são considerados, enquanto esta amostra de pdf pode seguir um espaço de cor especial como Indexed CS
, DeviceN CS
.
as imagens sobrepostas são removidas. python-docx
é aplicado para escrever o docx convertido, mas python-docx
não suporta elementos flutuantes agora. Portanto, as imagens flutuantes são removidas como um compromisso.
Então, infelizmente, pdf2docx
não pode converter seu pdf por enquanto. Devem ser feitos pelo menos os seguintes esforços:
Obrigado @dothinking pela explicação clara. Estou surpreso que esta biblioteca não seja mais popular do que é. A versão atual já é muito boa e sei que muita gente pode se beneficiar dela.
Por favor, deixe-me saber como posso ajudar a resolver qualquer um dos problemas listados (vou precisar de alguma orientação). Seja resolvendo os bugs, testando ou de outra forma.
Muito obrigado @ echan00.
Algum progresso neste problema:
PyMuPDF
publicou um novo recurso no caminho de extração. Vou investigar e espero poder resolver o problema.Depois disso, qualquer teste ou sugestão são apreciados.
Comentário sobre 2020-12-31: o PyMuPDF 1.18.5 mais recente resolveu esse problema parcialmente, mas não perfeitamente, especialmente o caminho de recorte.
Como a imagem embutida é compatível com python-docx
, as etapas para explorar a imagem flutuante:
behind text
)resultados da estrutura xml:
<wp:inline>
em <w:drawing>
<wp:anchor>
em <w:drawing>
<wp:positionH>
e <wp:positionV>
para definir a posição fixaPortanto, a ideia é criar <wp:anchor>
node e, em seguida, anexar subnós:
<wp:positionH>
e <wp:positionV>
Parece que a imagem flutuante com python-docx
é um pedido comum, documente aqui para compartilhar.
# -*- coding: utf-8 -*-
'''
Implement floating image based on python-docx.
- Text wrapping style: BEHIND TEXT <wp:anchor behindDoc="1">
- Picture position: top-left corner of PAGE `<wp:positionH relativeFrom="page">`.
Create a docx sample (Layout | Positions | More Layout Options) and explore the
source xml (Open as a zip | word | document.xml) to implement other text wrapping
styles and position modes per `CT_Anchor._anchor_xml()`.
'''
from docx.oxml import parse_xml, register_element_cls
from docx.oxml.ns import nsdecls
from docx.oxml.shape import CT_Picture
from docx.oxml.xmlchemy import BaseOxmlElement, OneAndOnlyOne
# refer to docx.oxml.shape.CT_Inline
class CT_Anchor(BaseOxmlElement):
"""
``<w:anchor>`` element, container for a floating image.
"""
extent = OneAndOnlyOne('wp:extent')
docPr = OneAndOnlyOne('wp:docPr')
graphic = OneAndOnlyOne('a:graphic')
<strong i="7">@classmethod</strong>
def new(cls, cx, cy, shape_id, pic, pos_x, pos_y):
"""
Return a new ``<wp:anchor>`` element populated with the values passed
as parameters.
"""
anchor = parse_xml(cls._anchor_xml(pos_x, pos_y))
anchor.extent.cx = cx
anchor.extent.cy = cy
anchor.docPr.id = shape_id
anchor.docPr.name = 'Picture %d' % shape_id
anchor.graphic.graphicData.uri = (
'http://schemas.openxmlformats.org/drawingml/2006/picture'
)
anchor.graphic.graphicData._insert_pic(pic)
return anchor
<strong i="8">@classmethod</strong>
def new_pic_anchor(cls, shape_id, rId, filename, cx, cy, pos_x, pos_y):
"""
Return a new `wp:anchor` element containing the `pic:pic` element
specified by the argument values.
"""
pic_id = 0 # Word doesn't seem to use this, but does not omit it
pic = CT_Picture.new(pic_id, filename, rId, cx, cy)
anchor = cls.new(cx, cy, shape_id, pic, pos_x, pos_y)
anchor.graphic.graphicData._insert_pic(pic)
return anchor
<strong i="9">@classmethod</strong>
def _anchor_xml(cls, pos_x, pos_y):
return (
'<wp:anchor distT="0" distB="0" distL="0" distR="0" simplePos="0" relativeHeight="0" \n'
' behindDoc="1" locked="0" layoutInCell="1" allowOverlap="1" \n'
' %s>\n'
' <wp:simplePos x="0" y="0"/>\n'
' <wp:positionH relativeFrom="page">\n'
' <wp:posOffset>%d</wp:posOffset>\n'
' </wp:positionH>\n'
' <wp:positionV relativeFrom="page">\n'
' <wp:posOffset>%d</wp:posOffset>\n'
' </wp:positionV>\n'
' <wp:extent cx="914400" cy="914400"/>\n'
' <wp:wrapNone/>\n'
' <wp:docPr id="666" name="unnamed"/>\n'
' <wp:cNvGraphicFramePr>\n'
' <a:graphicFrameLocks noChangeAspect="1"/>\n'
' </wp:cNvGraphicFramePr>\n'
' <a:graphic>\n'
' <a:graphicData uri="URI not set"/>\n'
' </a:graphic>\n'
'</wp:anchor>' % ( nsdecls('wp', 'a', 'pic', 'r'), int(pos_x), int(pos_y) )
)
# refer to docx.parts.story.BaseStoryPart.new_pic_inline
def new_pic_anchor(part, image_descriptor, width, height, pos_x, pos_y):
"""Return a newly-created `w:anchor` element.
The element contains the image specified by *image_descriptor* and is scaled
based on the values of *width* and *height*.
"""
rId, image = part.get_or_add_image(image_descriptor)
cx, cy = image.scaled_dimensions(width, height)
shape_id, filename = part.next_id, image.filename
return CT_Anchor.new_pic_anchor(shape_id, rId, filename, cx, cy, pos_x, pos_y)
# refer to docx.text.run.add_picture
def add_float_picture(p, image_path_or_stream, width=None, height=None, pos_x=0, pos_y=0):
"""Add float picture at fixed position `pos_x` and `pos_y` to the top-left point of page.
"""
run = p.add_run()
anchor = new_pic_anchor(run.part, image_path_or_stream, width, height, pos_x, pos_y)
run._r.add_drawing(anchor)
# refer to docx.oxml.shape.__init__.py
register_element_cls('wp:anchor', CT_Anchor)
if __name__ == '__main__':
from docx import Document
from docx.shared import Inches, Pt
document = Document()
# add a floating image
p = document.add_paragraph()
add_float_picture(p, 'test.png', width=Inches(5.0), pos_x=Pt(20), pos_y=Pt(30))
# add text
p.add_run('Hello World'*50)
document.save('output.docx')
Legal @dothinking , parece que você sabe exatamente quais são os problemas. Eu tenho uma variedade de PDFs que posso ajudar a testar quando você estiver pronto
@dothinking, muito obrigado por seu exemplo de código! Resolve meu problema perfeitamente !!!!
Não tive tempo para este projeto por muito tempo. A nova versão v0.5.0
agora está disponível para resolver parcialmente este problema:
PyMuPDF
, mas não tão boa para formas complicadas, por exemplo, caminho de recorte.Com esta versão mais recente, o pdf de amostra pode ser convertido com sucesso, mas ainda precisa de muito trabalho para melhorar a qualidade do arquivo docx convertido, devido ao estilo complicado / lindo.
Uau, essa é uma grande atualização. Muito obrigado pelo seu trabalho árduo @dothinking
Comentários muito úteis
Parece que a imagem flutuante com
python-docx
é um pedido comum, documente aqui para compartilhar.