Skip to content

Commit 0cc7e73

Browse files
authored
Refactor fitz_doc_to_image for page rendering
PR: studio-dots-ai#138
1 parent 1fa296f commit 0cc7e73

1 file changed

Lines changed: 38 additions & 13 deletions

File tree

dots_ocr/utils/doc_utils.py

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,51 @@ class PageInfo(BaseModel):
1717
h: float = Field(description='the height of page')
1818

1919

20-
def fitz_doc_to_image(doc, target_dpi=200, origin_dpi=None) -> dict:
21-
"""Convert fitz.Document to image, Then convert the image to numpy array.
20+
def fitz_doc_to_image(page, target_dpi=200, max_side=4500, max_pixels=None) -> dict:
21+
"""Convert a PyMuPDF page to a NumPy-compatible image array.
22+
23+
This function renders a single `fitz.Page` object to an image with a
24+
target DPI, while ensuring constraints on maximum side length and
25+
maximum pixel count are respected.
2226
2327
Args:
24-
doc (_type_): pymudoc page
25-
dpi (int, optional): reset the dpi of dpi. Defaults to 200.
28+
page (fitz.Page): A PyMuPDF page object to render.
29+
target_dpi (int, optional): Desired resolution in DPI.
30+
Defaults to 200.
31+
max_side (int, optional): Maximum allowed width or height (in pixels)
32+
of the rendered image. Defaults to 4500.
33+
max_pixels (int, optional): Maximum allowed total number of pixels
34+
in the rendered image. If provided, the image will be scaled down
35+
to respect this constraint. Defaults to None.
2636
2737
Returns:
28-
dict: {'img': numpy array, 'width': width, 'height': height }
38+
PIL.Image.Image: The rendered page as a PIL Image object.
39+
40+
Raises:
41+
ValueError: If the input `page` is not a `fitz.Page`.
2942
"""
3043
from PIL import Image
31-
mat = fitz.Matrix(target_dpi / 72, target_dpi / 72)
32-
pm = doc.get_pixmap(matrix=mat, alpha=False)
44+
# base zoom for requested DPI
45+
zoom = target_dpi / 72.0
46+
47+
# predict size at requested DPI
48+
w0 = page.rect.width * zoom
49+
h0 = page.rect.height * zoom
50+
51+
# compute an extra scale factor s to stay within limits
52+
s = 1.0
53+
if max_side:
54+
s = min(s, max_side / max(w0, h0))
55+
if max_pixels:
56+
s = min(s, (max_pixels / (w0 * h0)) ** 0.5)
57+
58+
# don’t upscale beyond requested dpi
59+
s = min(s, 1.0)
3360

34-
if pm.width > 4500 or pm.height > 4500:
35-
mat = fitz.Matrix(72 / 72, 72 / 72) # use fitz default dpi
36-
pm = doc.get_pixmap(matrix=mat, alpha=False)
61+
mat = fitz.Matrix(zoom * s, zoom * s)
62+
pm = page.get_pixmap(matrix=mat, alpha=False)
3763

38-
image = Image.frombytes('RGB', (pm.width, pm.height), pm.samples)
39-
return image
64+
return Image.frombytes("RGB", (pm.width, pm.height), pm.samples)
4065

4166

4267
def load_images_from_pdf(pdf_file, dpi=200, start_page_id=0, end_page_id=None) -> list:
@@ -57,4 +82,4 @@ def load_images_from_pdf(pdf_file, dpi=200, start_page_id=0, end_page_id=None) -
5782
page = doc[index]
5883
img = fitz_doc_to_image(page, target_dpi=dpi)
5984
images.append(img)
60-
return images
85+
return images

0 commit comments

Comments
 (0)