提取文本坐标时 Y 值不准确

问题描述 投票:0回答:1

我正在使用

PyQt5.QWebEngineView
显示 pdf。目前,我正在使用
PDF.js
使用以下代码从 PDF 文档中的选定区域中提取文本坐标(基于此 question):

from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, QTextBrowser
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl, QTimer, QEventLoop
import os


class MyWebWidgetPdf(QWebEngineView):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


    def contextMenuEvent(self, event):
        position_action = QAction("Position", self)
        position_action.triggered.connect(self.get_current_position)

        self.menu = self.page().createStandardContextMenu()
        self.menu.addAction(position_action)
        self.menu.popup(event.globalPos())

    def get_current_position(self):
        js_script = """
                var pageIndex = PDFViewerApplication.pdfViewer.currentPageNumber - 1; 
                var page = PDFViewerApplication.pdfViewer.getPageView(pageIndex);
                var pageRect = page.canvas.getClientRects()[0];
                var selection = window.getSelection();
                var selectionRects = selection.getRangeAt(0).getClientRects();
                var selectionRectsArray = Array.from(selectionRects);

                var selectedText = selection.toString();
                var viewport = page.viewport;
                var selected = selectionRectsArray.map(function (r) {
                    return viewport.convertToPdfPoint(r.left - pageRect.x, r.top - pageRect.y).concat(
                        viewport.convertToPdfPoint(r.right - pageRect.x, r.bottom - pageRect.y)
                    ); 
                });
                
                var result = {
                    page: pageIndex + 1, 
                    coords: selected, 
                    selectedText: selectedText
                };

                result;
            """

        result = self.execJavaScript(js_script)
        print(result)


    def execJavaScript(self, script):
        """This function executes a javascript script and returns the result.
            :param script: The script to execute.
            :return: The result of the script."""
        result = None  # initialize the result

        def callback(data):
            """This function is called when the script is executed.
                :param data: The result of the script."""
            nonlocal result  # use the result variable of the parent function
            result = data  # set the result
            loop.quit()  # quit the event loop

        loop = QEventLoop()  # create an event loop
        QTimer.singleShot(0, lambda: self.page().runJavaScript(script, callback))  # execute the script
        loop.exec()  # start the event loop
        return result  # return the result


class PDFViewer(QMainWindow):
    def __init__(self):
        super().__init__()

        self.browser = QTextBrowser()
        self.setCentralWidget(self.browser)

        self.pdf_viewer = MyWebWidgetPdf()
        self.setCentralWidget(self.pdf_viewer)
        path = "/Users/user/Desktop/3._SprengV.pdf"
        PDF = f'file:{os.path.abspath(path)}'
        self.PDFJS = 'file:////Users/user/PycharmProjects/legalref/pdfjs-3/web/viewer.html'
        self.pdf_viewer.load(QUrl.fromUserInput(f'{self.PDFJS}?file={PDF}'))


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    dialog = PDFViewer()
    dialog.show()
    sys.exit(app.exec_())

我遇到一个问题,X 值是正确的,但 Y 值始终偏离很多。我用

PyMuPdf
控制了 x 和 y 值。

javascript python pdf.js qwebengineview
1个回答
0
投票

原生 PDF 内容就像 Y 方向向上的图表一样。通常“原点”位于左下角。高度通常使用点大小单位,名义上为 1/72"。

所有这些都可以通过

/UserUnit
C
当前
M
矩阵变换更改为不同的“向上”,如“从右到左”(右读)甚至“颠倒”。

通常(默认)我们看到信纸页的 /MediaBox 的高度为 72 x 11 = 792 个单位,但它可以是任意数量的单位,并且在打印/显示时仍然为 11 英寸高。

因此,在渲染时,“屏幕”原点被假定为左上角。许多 PDF 应用程序以这些向下的单位工作,然后在写入过程中转换为相反的方向。

在同一工作区中使用多个应用程序时,这会导致问题。但是,通过从 /Media 高度中减去当前高度并调整当前用户标量和/或位置,可以轻松解决此问题。

因此,我们可能会将 4.5 英寸高的图像放置在半高处(5.5 英寸,因此它们可以是上方 1 英寸的空隙),因此我们可以计算出它需要位于 792 - 396 - 324 =

72 Down

© www.soinside.com 2019 - 2024. All rights reserved.