pymupdf / PyMuPDF

PyMuPDF is a high performance Python library for data extraction, analysis, conversion & manipulation of PDF (and other) documents.
https://pymupdf.readthedocs.io
GNU Affero General Public License v3.0
5.27k stars 502 forks source link

Example zoom factor in Tkinter #44

Closed ITKSoft closed 8 years ago

ITKSoft commented 8 years ago

It would be the correct way to use zoom factor with Tkinter?

PyMuPDF

doc_pdf = fitz.Document( "example.pdf" ) matrix = fitz.Matrix ( 1 , 1 ).preScale( 1.2 , 1.2 )

page = doc_pdf.loadPage( 1 )
pix = page.getPixmap( matrix = matrix , colorspace = 'RGB' )
data = str( pix.samples )

data2 = "".join( [ data[4_i:4_i+3] for i in range( len( data ) / 4 ) ] )

Tkinter - canvas

from PIL import Image , ImageTk im = Image.frombytes( "RGBA" , [pix.width , pix.height] , data )
canvas = Canvas( root , relief=SUNKEN ) canvas.config( width=400 , height=200 ) canvas.config( highlightthickness=0 )

sbarV = Scrollbar( root , orient=VERTICAL ) sbarH = Scrollbar( root , orient=HORIZONTAL )

sbarV.config( command=canvas.yview ) sbarH.config( command=canvas.xview )

canvas.config( yscrollcommand=sbarV.set ) canvas.config( xscrollcommand=sbarH.set ) sbarV.pack( side=RIGHT , fill=Y ) sbarH.pack( side=BOTTOM , fill=X )

canvas.pack( side=LEFT, expand=YES, fill=BOTH )

width , height = im.size canvas.config( scrollregion = ( 0 , 0 , width , height ) ) im2 = ImageTk.PhotoImage( im )

nWid = ( root.winfo_screenwidth() / 2 ) - ( width / 2 )

imgtag = canvas.create_image( nWid , 10 , anchor="nw" , image=im2 )

JorjMcKie commented 8 years ago

One problem is, that Tkinter also has Image (as does PIL). So, your from Tkinter import * overrides it.

Another problem is, that the variable root is not defined ...

I am not sure what you are trying to do:

Do you just want to display one fixed, scaled page in a window that can be scrolled?

Or do you want to dynamically scale the displayed page image?

All of this would have significant impact on your code of course.

ITKSoft commented 8 years ago

I'm not using (from Tkinter import *). Only example. I want to dynamically scale the displayed page image, after selected scale in the toolbar.

JorjMcKie commented 8 years ago

@ITKSoft - got you. For every new scale factor, you need to a new pixmap. Internally, this will not cause the PDF page to be re-read or re-parsed. The required information (stored in a so-called fitz.DisplayList) will be re-used and kept as long as the page object lives. A pseudo code sequence could look like:

1. determine scale factor f (based on user input)
2. define appropriate matrix as fitz.Matrix (1 , 1).preScale(f, f)
3. create pixmap pix = page.getPixmap( matrix = matrix) (RGB is default)
4. use pix.samples for display
5. start over

Obviously, lines 2 to 4 could be put in a function like this

def ScaledImage(page, f):
    mat = fitz.Matrix(1, 1).preScale(f, f)
    pix = page.getPixmap(matrix = mat)
    data = str(pix.samples)
    return Image.frombytes( "RGBA" , [pix.width , pix.height] , data )

Apart from being handy, this ensures that the resources associated with the pixmap are being released.

ITKSoft commented 8 years ago

And access to the page would be with ( page = doc.load Page ( npage ) ) ?

JorjMcKie commented 8 years ago

Yes - here is a more complete sequence of statements:

import fitz
doc = fitz.Document("filename.pdf")
page = doc.loadPage(20)
etc.

The integer parameter to the loadPage() method is 0-based, so the above page is actually 21 by human understanding ...

If you look at the tutorial, the demo and the examples you should find many ideas of what else you can do with PyMuPDF ...

JorjMcKie commented 8 years ago

@ITKSoft - were you successfull? Any more help needed (note: I don't really know Thinter, but otherwise ...)? Please don't forget to close the issue ...