PDF parsing

The PDF appears to be in landscape orientation, but the extracted coordinates are incorrect: clarify the rotation matrix

You are parsing a scanned document or an engineering drawing; to the naked eye, the table appears on the right side of the page, but gettext() The returned coor

阅读文本 / Reading text
This paper uses synthetic samples to demonstrate the processing method. The code has been verified using examples in an isolated environment; this does not guarantee effectiveness for all real files or products. Before processing important files, please retain the original copies and verify them against the boundaries and acceptance criteria outlined in this document. You are parsing a scanned document or an engineering drawing; to the naked eye, the table appears on the right side of the page, but get_text() The returned coordinates, however, point to the upper-left corner; or, when attempting to highlight a certain paragraph with code, the yellow block ends up appearing in the header area. This is usually not a bug in the parsing library, but rather a result of inconsistencies between the PDF coordinate system and visual rendering. The PDF specification allows pages to carry /Rotate attributes (0, 90, 180, 270), the reader automatically applies this rotation during rendering, but the underlying content stream’s coordinates remain based on the original, unrotated MediaBox. If you directly use the extracted raw coordinates for drawing or region matching, misalignment will occur. Understanding the difference between the unrotated space and the displayed space PyMuPDF has explicitly distinguished between these two coordinate systems since version v1.17.0. Page.get_text() 、 Page.get_image_bbox() and the coordinates of all annotated objects are, by default, relative to unrotated page returns. This means that no matter how many degrees the PDF viewer rotates the page, the values returned by these APIs always remain anchored to the original width and height. Only Page.rect and Page.bound() will reflect the actual display size after rotation. This design is intended to ensure the stability of content extraction: even if you change the page’s rotation angle, the extraction coordinates for the same text segment will remain unchanged. However, when you need to “map” these coordinates back onto the page or align them with visual interactions such as mouse clicks, you must perform the coordinate transformation manually. PyMuPDF provides two key matrix properties: Page.rotation_matrix is used to convert unrotated coordinates into display coordinates, Page.derotation_matrix performs the inverse operation. These two matrices encapsulate translation and rotation transformations, eliminating the need for developers to manually implement trigonometric calculations. synthesis example: correct and incorrect expectations for coordinate transformations To demonstrate this mechanism, we construct an in-memory synthetic scenario that does not rely on external files. If you need to test real documents, please prepare in advance a file containing /Rotate=90 The PDF file of the attribute, and ensure that its CropBox matches the MediaBox to eliminate interference from cropping offsets. input setting : Create an A4 portrait page (595 x 842 pt), set /Rotate = 90 . In the unrotated space, the point (100, 100) is located near the upper-left corner; however, in the display space after a 90-degree rotation, because the coordinate system rotates along with it, the visual position of this point changes significantly. correctly outputs the expected : Multiply (100, 100) by rotation_matrix Afterward, the resulting display coordinates should fall within the valid boundaries of the rotated page (that is, page.rect ). For the default A4 page rotated 90 degrees counterclockwise, the original top-left corner should be mapped to a position near the bottom-left in the display space, meaning its x-coordinate is larger while its y-coordinate is close to 0. Do not blindly assume y > x , the specific value depends entirely on the definition of the MediaBox origin. boundary case handling : When the rotation angle is 0, rotation_matrix should be the identity matrix. If an invalid rotation value that is not a multiple of 90 is passed, PyMuPDF will typically normalize it; however, defensive programming still recommends verifying the matrix’s validity to prevent NaN coordinates. Python implementation of coordinate validation logic The following example demonstrates how to verify a coordinate transformation in memory. Note that this code is intended solely for illustrating the logic of matrix operations and does not constitute a complete PDF-processing pipeline. Before running, ensure that the necessary packages are installed. PyMuPDF library, and run it in your own locked dependency environment. import fitz # PyMuPDF def validate_rotation_transform(): """合成示例:验证旋转矩阵在未旋转坐标与显示坐标间的转换""" doc = fitz.open() # 空文档,无需文件路径 page = doc.new_page(width=595, height=842) # 设置页面旋转90度,模拟横向显示的PDF page.set_rotation(90) # 定义一个在未旋转空间中的测试点 (左上角附近) unrotated_point = fitz.Point(100, 100) # 获取旋转矩阵并执行变换 mat = page.rotation_matrix display_point = unrotated_point * mat # 验证1: 变换后的点必须位于旋转后的页面可视区域内 assert page.rect.contains(display_point), ( f"变换后坐标 {display_point} 超出显示边界 {page.rect}" ) # 验证2: 对于默认A4逆时针旋转90度,原(100,100)应变为左下角 # 即 x 接近页宽(842),y 接近 0。注意:此处纠正了常见的 y>x 误区 assert display_point.x > 500 and display_point.y < 200, ( f"90度旋转预期左下角,实际得到 ({display_point.x:.1f}, {display_point.y:.1f})" ) # 验证3: 逆变换可精确恢复原始坐标 inv_mat = page.derotation_matrix recovered = display_point * inv_mat assert abs(recovered.x - unrotated_point.x) < 0.01 assert abs(recovered.y - unrotated_point.y) < 0.01 doc.close() print("坐标变换逻辑校验通过(合成数据)") # 请在本地环境运行,不要假设线上环境已安装fitz validate_rotation_transform() This code does not read any real files; it constructs the page state entirely in memory. assert The statement checks the validity of mathematical relationships, not business correctness. If your actual PDF contains non-standard MediaBoxes or nested transformations, additional debugging may be required. Acceptance Criteria and Manual Review Boundary code passing assertions does not guarantee foolproof operation in a production environment. The table below lists common exceptions and the corresponding handling decisions, helping to distinguish between scenarios that can be resolved automatically and those requiring manual intervention. Observation of the phenomenon possible causes processing decision annotation has an overall offset of a fixed distance CropBox and MediaBox have inconsistent origins uses page.cropbox_position compensation offset After rotation, the text coordinates are correct, but the image is misaligned. image uses an independent CTM transformation matrix is changed to get_image_rects() rather than get_image_bbox() Some pages are rotated correctly, while others are distorted document contains pages with varying rotation angles page-by-page inspection page.rotation , disable the global cache matrix The transformed coordinates exceed the page boundaries. The original content itself has been cropped or contains negative coordinates is flagged as an anomalous page and forwarded for manual review 0The page requires no transformation yet still exhibits deviation Hidden rotational metadata written by third-party tools forcibly invokes remove_rotation() Reset and then process Note: This table pertains to coordinate transformation logic and does not address OCR accuracy or font encoding issues. When encountering complex layouts (such as multi-column mixed formatting combined with locally rotated charts), automatic validation may fail; in such cases, the pipeline should be paused, and manual judgment should determine whether to proceed. References and Next Steps PyMuPDF Page.rotation_matrix Official Documentation PyMuPDF Coordinates Concept Explanation uses this checklist for document translation first ensures that the page order, source locations, and text integrity have been thoroughly checked, then submits the same de-identified sample to the translation process. After translation, it is still necessary to verify that the headings, body text, and figure captions correspond correctly; one should not rely solely on whether the text flows smoothly. OmniDoc (product entry point) provides an entry point for translating multi-format documents, and the official website highlights its OCR, terminology database, and bilingual alignment features. For teams that wish to start processing directly from files, this is a path worth evaluating with real-world samples. Please use de-identified files that you are authorized to upload, and verify the results against the checklist provided in this document; we do not claim that OmniDoc utilizes the open-source libraries or internal algorithms referenced herein, nor do we substitute examples for product performance testing. - 1 -
Updated 2026-10-08