Skip to content

pdfviewer using PyMuPDF broken with recent versions of PyMuPDF. PATCH included #1350

@jmoraleda

Description

@jmoraleda

The following snippet of code (extracted from https://wxpython.org/Phoenix/docs/html/wx.lib.pdfviewer.html?highlight=pdf#usage by removing the button panel) demonstrates the problem:

import wx
import wx.lib.sized_controls as sc

from wx.lib.pdfviewer import pdfViewer

class PDFViewer(sc.SizedFrame):
    def __init__(self, parent, **kwds):
        super(PDFViewer, self).__init__(parent, **kwds)

        paneCont = self.GetContentsPane()

        self.viewer = pdfViewer(paneCont, wx.ID_ANY, wx.DefaultPosition,
                                wx.DefaultSize,
                                wx.HSCROLL|wx.VSCROLL|wx.SUNKEN_BORDER)

        self.viewer.SetSizerProps(expand=True, proportion=1)


if __name__ == '__main__':
    import wx.lib.mixins.inspection as WIT
    app = WIT.InspectableApp(redirect=False)

    pdfV = PDFViewer(None, size=(800, 600))
    pdfV.viewer.LoadFile(r'path_to_any_pdf_file.pdf')
    pdfV.Show()

    app.MainLoop()

The code works correctly with older versions of PyMuPDF(up to 1.14) but fails with more recent versions (1.15 and above). This is the complete output written to the console:

python .\pdftest.py
pdfviewer using PyMuPDF (GPL)
Traceback (most recent call last):
  File "C:\Program Files\Python37\lib\site-packages\wx\core.py", line 3259, in <lambda>
    lambda event: event.callable(*event.args, **event.kw) )
  File "C:\Program Files\Python37\lib\site-packages\wx\lib\pdfviewer\viewer.py", line 433, in Render
    self.pdfdoc.RenderPage(gc, pageno, scale=self.scale)
  File "C:\Program Files\Python37\lib\site-packages\wx\lib\pdfviewer\viewer.py", line 518, in RenderPage
    bmp = wx.Bitmap.FromBufferRGBA(pix.width, pix.height, pix.samples)
ValueError: Invalid data buffer size.

FIX

The issue is that PyMuPDF used to produce RGBA values, but now produces RGB values, thus the code as it stands works on older installations, but fails on newer installations. In particular, Bitmap.FromBuffer should be used instead of Bitmap.FromBufferRGBA.

This is a patch that will correctly handle both the older and newer versions of PyMuPDF.

diff --git a/wx/lib/pdfviewer/viewer.py b/wx/lib/pdfviewer/viewer.py
index 7b75724b..284069e1 100644
--- a/wx/lib/pdfviewer/viewer.py
+++ b/wx/lib/pdfviewer/viewer.py
@@ -516,7 +516,11 @@ class mupdfProcessor(object):
         matrix = fitz.Matrix(scale, scale)
         try:
             pix = page.getPixmap(matrix=matrix)   # MUST be keyword arg(s)
-            bmp = wx.Bitmap.FromBufferRGBA(pix.width, pix.height, pix.samples)
+            if [int(v) for v in fitz.version[1].split('.')] >= [1,15,0]:
+                # See https://github.com/wxWidgets/Phoenix/issues/1350
+                bmp = wx.Bitmap.FromBuffer(pix.width, pix.height, pix.samples)
+            else:
+                bmp = wx.Bitmap.FromBufferRGBA(pix.width, pix.height, pix.samples)
             gc.DrawBitmap(bmp, 0, 0, pix.width, pix.height)
             self.zoom_error = False
         except (RuntimeError, MemoryError):

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions