复制代码
class PDFMiner:
    def __init__(self, filepath):
        # creating the file path
        self.filepath = filepath
        # opening the pdf document
        self.pdf = fitz.open(self.filepath)
        # loading the first page of the pdf document
        self.first_page = self.pdf.load_page(0)
        # getting the height and width of the first page
        self.width, self.height = self.first_page.rect.width, self.first_page.rect.height
        # initializing the zoom values of the page
        zoomdict = {800: 1.0, 700: 1.1, 600: 1.2, 500: 1.3, 1500: 0.9}
        # getting the width value
        self.change_width = int(math.floor(self.width / 100.0) * 100)
        # zooming the page
        try:
            self.zoom = zoomdict[self.change_width]
        except Exception as e:
            text1.insert(ttk.END, "页面缩放比例获取失败,将同比例展示.... " + e.__str__() + "\n")
            text1.see(ttk.END)
        finally:
            self.zoom = 1

    # this will get the metadata from the document like
    # author, name of document, number of pages
    def get_metadata(self):
        # getting metadata from the open PDF document
        metadata = self.pdf.metadata
        # getting number of pages from the open PDF document
        numPages = self.pdf.page_count
        # returning the metadata and the numPages
        return metadata, numPages

    # the function for getting the page
    def get_page(self, page_num):
        # loading the page
        page = self.pdf.load_page(page_num)
        # checking if zoom is True
        if self.zoom:
            # creating a Matrix whose zoom factor is self.zoom
            mat = fitz.Matrix(self.zoom, self.zoom)
            # gets the image of the page
            pix = page.get_pixmap(matrix=mat)
        # returns the image of the page
        else:
            pix = page.get_pixmap()
        # a variable that holds a transparent image
        px1 = fitz.Pixmap(pix, 0) if pix.alpha else pix
        # converting the image to bytes
        imgdata = px1.tobytes("ppm")
        # returning the image data
        return PhotoImage(data=imgdata)

    # function to get text from the current page
    def get_text(self, page_num):
        # loading the page
        page = self.pdf.load_page(page_num)
        # getting text from the loaded page
        text = page.getText('text')
        # returning text
        return text

# creating a class called PDFViewer
class PDFViewer:
    # initializing the __init__ / special method
    def __init__(self, master):
        # path for the pdf doc
        self.path = None
        # state of the pdf doc, open or closed
        self.fileisopen = None
        self.filekind = None
        # author of the pdf doc
        self.author = None
        # name for the pdf doc
        self.name = None
        # the current page for the pdf
        self.current_page = 0
        # total number of pages for the pdf doc
        self.numPages = None
        self.canvas_image = None
        self.canvas_pdf = None

        # 图片的大小
        self.img_width = None
        self.img_height = None

        # creating the window
        self.master = master

        # creating the top frame
        self.top_frame = Frame(self.master)
        # creating the bottom frame
        self.bottom_frame = Frame(self.top_frame)

        # creating the canvas for display the PDF pages
        self.output = ScrolledCanvas(self.top_frame, bg="white", highlightthickness=0, takefocus=1)
        self.output.frame.pack(expand=True, fill=BOTH, side=TOP)

        # loading the button icons
        self.page_frame = Frame(self.bottom_frame)
        self.uparrow_icon = PhotoImage(data=Arrow_Down_png)
        self.downarrow_icon = PhotoImage(data=Arrow_Down_png)
        # resizing the icons to fit on buttons
        self.uparrow = self.uparrow_icon.subsample(1, 1)
        self.downarrow = self.downarrow_icon.subsample(1, 1)
        # creating an up button with an icon
        self.upbutton = Button(self.page_frame,bd=0, bg="white", highlightthickness=0, image=self.uparrow, command=self.previous_page)
        self.upbutton.config(background="white", disabledforeground="white", foreground="white", activebackground="white")
        # adding the button
        self.upbutton.pack(anchor=CENTER, side=LEFT, padx=1, pady=5)
        # creating a down button with an icon
        self.downbutton = Button(self.page_frame, bg="white", highlightthickness=0, image=self.downarrow, command=self.next_page)
        self.downbutton.config(background="white", disabledforeground="white", foreground="white", activebackground="white")
        # adding the button
        self.downbutton.pack(anchor=CENTER, side=LEFT,  padx=1, pady=5)
        # label for displaying page numbers
        self.page_label = Label(self.page_frame, text='page')
        # adding the label
        self.page_label.pack(anchor=CENTER, side=LEFT, padx=3, pady=5)
        self.page_frame.pack(expand=True, anchor=CENTER, side=LEFT, padx=3, pady=5)

        # loading the button icons
        self.zoom_frame = Frame(self.bottom_frame)
        self.zoomin_icon = PhotoImage(data=Zoom_In_png)
        self.zoomout_icon = PhotoImage(data=Zoom_Out_png)
        # resizing the icons to fit on buttons
        self.zoomin = self.zoomin_icon.subsample(1, 1)
        self.zoomout = self.zoomout_icon.subsample(1, 1)
        # creating an up button with an icon
        self.zoominbutton = Button(self.zoom_frame, bd=0, bg="white", highlightthickness=0, image=self.zoomin,
                               command=self.zoomin_page)
        self.zoominbutton.config(background="white", disabledforeground="white", foreground="white", activebackground="white")
        # adding the button
        self.zoominbutton.pack(anchor=CENTER, side=LEFT, padx=3, pady=5)
        # creating a down button with an icon
        self.zoomoutbutton = Button(self.zoom_frame, bg="white", highlightthickness=0, image=self.zoomout,
                                 command=self.zoomout_page)
        self.zoomoutbutton.config(background="white", disabledforeground="white", foreground="white", activebackground="white")
        # adding the button
        self.zoomoutbutton.pack(anchor=CENTER, side=LEFT, padx=3, pady=5)
        # label for displaying page numbers
        self.zoom_label = Label(self.zoom_frame, text='Zoom')
        # adding the label
        self.zoom_label.pack(anchor=CENTER, side=LEFT, padx=3, pady=5)

        self.zoom_value = StringVar()
        # 45--200 每次 5
        zooms = [zoom for zoom in range(45, 200, 5)]
        self.zoom_combobox = Combobox(self.zoom_frame, textvariable=self.zoom_value, width=6,state=READONLY,
                                      value=[(value).__str__() + "%" for value in zooms])
        self.zoom_combobox.pack(anchor=CENTER, side=LEFT, padx=3, pady=5)
        self.zoom_value.set("100%")
        self.zoom_combobox.bind("<<ComboboxSelected>>", self.zoom_combobox_change)
        self.zoom_frame.pack(expand=True, anchor=CENTER, side=LEFT, padx=3, pady=5)

        # placing the frame using inside main window using grid()

        self.bottom_frame.pack(side=BOTTOM, fill=X)

        # placing the frame using inside main window using grid()
        self.top_frame.pack(side=TOP, fill=BOTH, expand=True)

    def zoom_combobox_change(self, event):
        if self.fileisopen and 'pdf' in self.filekind.mime.__str__():
            # 更改缩略比例
            self.miner.zoom = int(self.zoom_combobox.get()[:-2]) / 10
            if self.miner.zoom <= 0.45 or self.miner.zoom >= 2:
                self.miner.zoom = 1
            self.display_page()
        elif self.fileisopen and 'image' in self.filekind.mime.__str__():
            # 更改缩略比例
            zoom = int(self.zoom_combobox.get()[:-2]) / 10
            if zoom <= 0.45 or zoom >= 2:
                zoom = 1
            self.output.canvas.delete(self.canvas_image)
            self.output.canvas.img_avatar = ImageTk.PhotoImage(
                image=self.pil_avatar.resize((int(self.img_width * zoom), int(self.img_height * zoom))))
            self.canvas_image = self.output.canvas.create_image(0, 0, anchor=NW, image=self.output.canvas.img_avatar)

    # function for opening pdf files
    def open_file(self, filepath):
        if filepath:
            # declaring the path
            self.path = filepath
            self.filekind = filetype.guess(self.path)
            # extracting the pdf file from the path
            filename = os.path.basename(self.path)
            if self.canvas_pdf:
                self.output.canvas.delete("all")
            if self.canvas_image:
                self.output.canvas.delete("all")
            self.output.canvas.update()
            if self.filekind:
                if('pdf' in self.filekind.mime.__str__()):
                    # passing the path to PDFMiner
                    self.miner = PDFMiner(self.path)
                    # getting data and numPages
                    data, numPages = self.miner.get_metadata()
                    # setting the current page to 0
                    self.current_page = 0
                    # checking if numPages exists
                    if numPages:
                        # getting the title
                        self.name = data.get('title', filename[:-4])
                        # getting the author
                        self.author = data.get('author', None)
                        self.numPages = numPages
                        # setting fileopen to True
                        self.fileisopen = True
                        # calling the display_page() function
                        self.display_page()
                        # replacing the window title with the PDF document name
                        self.zoom_value.set(int(self.miner.zoom * 100).__str__() + "%")
                elif 'image' in self.filekind.mime.__str__():
                    self.fileisopen = True
                    # calling the display_page() function
                    self.display_image(self.path)
                    # replacing the window title with the PDF document name
                    self.zoom_value.set("100%")


    def display_image(self, img_file):
        # checking if numPages is less than current_page and if current_page is less than
        self.pil_avatar = PILImage.open(img_file)
        # inserting the page image inside the Canvas
        self.img_width, self.img_height = self.pil_avatar.width, self.pil_avatar.height
        self.output.canvas.img_avatar = ImageTk.PhotoImage(image=self.pil_avatar.resize((self.img_width, self.img_height)))
        # self.output.canvas.itemconfig(main_image, self.output.canvas.img_avatar)
        self.canvas_image = self.output.canvas.create_image(0, 0, anchor=NW, image=self.output.canvas.img_avatar)

        # creating a region for inserting the page inside the Canvas
        region = self.output.canvas.bbox(ALL)
        # making the region to be scrollable
        self.output.canvas.configure(scrollregion=region)

    def zoomin_page(self):
        if self.fileisopen and 'pdf' in self.filekind.mime.__str__():
            # checking if current_page is less than or equal to numPages-1
            self.miner.zoom = self.miner.zoom - 0.05
            if self.miner.zoom <= 0.45:
                self.miner.zoom = 0.45
            self.zoom_value.set(int(self.miner.zoom * 100).__str__() + "%")
            self.display_page()
        elif self.fileisopen and 'image' in self.filekind.mime.__str__():
            self.output.canvas.delete(self.canvas_image)
            zoom = int(self.zoom_value.get()[:-1]) / 100
            zoom = zoom - 0.05
            if zoom <= 0.45:
                zoom = 0.45
            self.output.canvas.img_avatar = ImageTk.PhotoImage(
                image=self.pil_avatar.resize((int(self.img_width * zoom), int(self.img_height * zoom))))
            self.canvas_image = self.output.canvas.create_image(0, 0, anchor=NW, image=self.output.canvas.img_avatar)
            self.zoom_value.set(int(zoom * 100).__str__() + "%")

    def zoomout_page(self):
        if self.fileisopen and 'pdf' in self.filekind.mime.__str__():
            # checking if current_page is less than or equal to numPages-1
            self.miner.zoom = self.miner.zoom + 0.05
            if self.miner.zoom >= 2:
                self.miner.zoom = 2
            self.zoom_value.set(int(self.miner.zoom * 100).__str__() + "%")
            self.display_page()
        elif self.fileisopen and  'image' in self.filekind.mime.__str__():
            self.output.canvas.delete(self.canvas_image)
            zoom = int(self.zoom_value.get()[:-1]) / 100
            zoom = zoom + 0.05
            if zoom >= 2:
                zoom = 2
            self.output.canvas.img_avatar = ImageTk.PhotoImage(
                image=self.pil_avatar.resize((int(self.img_width * zoom), int(self.img_height * zoom))))
            self.canvas_image = self.output.canvas.create_image(0, 0, anchor=NW, image=self.output.canvas.img_avatar)
            self.zoom_value.set(int(zoom * 100).__str__() + "%")

    # the function to display the page
    def display_page(self):
        # checking if numPages is less than current_page and if current_page is less than
        # or equal to 0
        if 0 <= self.current_page < self.numPages:
            # getting the page using get_page() function from miner
            self.img_file = self.miner.get_page(self.current_page)
            # inserting the page image inside the Canvas
            self.canvas_pdf = self.output.canvas.create_image(0, 0, anchor=CENTER, image=self.img_file)
            # the variable to be stringified
            self.stringified_current_page = self.current_page + 1
            # updating the page label with number of pages
            self.page_label['text'] = str(self.stringified_current_page) + ' of ' + str(self.numPages)
            # creating a region for inserting the page inside the Canvas
            region = self.output.canvas.bbox(ALL)
            # making the region to be scrollable
            self.output.canvas.configure(scrollregion=region)

    # function for displaying next page
    def next_page(self):
        # checking if file is open
        if self.fileisopen and 'pdf' in self.filekind.mime.__str__():
            # checking if current_page is less than or equal to numPages-1
            if self.current_page <= self.numPages - 1:
                # updating the page with value 1
                self.current_page += 1
                # displaying the new page
                self.display_page()

    # function for displaying the previous page
    def previous_page(self):
        # checking if fileisopen
        if self.fileisopen and 'pdf' in self.filekind.mime.__str__():
            # checking if current_page is greater than 0
            if self.current_page > 0:
                # decrementing the current_page by 1
                self.current_page -= 1
                # displaying the previous page
                self.display_page()

pdfview = PDFViewer(master=labFrame_canvas)

labFrame_canvas.pack(fill=BOTH, expand=True, side=BOTTOM)
复制代码

 

双击预览pdf

 

下一页

 

放大  缩小

 

posted on   Old-Kang  阅读(60)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
· 全程使用 AI 从 0 到 1 写了个小工具



点击右上角即可分享
微信分享提示