We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[document] Check integrity of PDF --> img conversion with default DPI
The current PDF reading implies a conversion to an image. As we are using the default args for this conversion, the DPI value might be low. We need to check that the default parameter is not bringing about performance issues due to low resolution rendering.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `doctr/documents/reader.py`
Content:
```
1 # Copyright (C) 2021, Mindee.
2 
3 # This program is licensed under the Apache License version 2.
4 # See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0.txt> for full license details.
5 
6 import numpy as np
7 import cv2
8 from pathlib import Path
9 import fitz
10 from weasyprint import HTML
11 from typing import List, Tuple, Optional, Any, Union, Sequence
12 
13 __all__ = ['read_pdf', 'read_img', 'read_html', 'DocumentFile']
14 
15 
16 AbstractPath = Union[str, Path]
17 AbstractFile = Union[AbstractPath, bytes]
18 Bbox = Tuple[float, float, float, float]
19 
20 
21 def read_img(
22     file: AbstractFile,
23     output_size: Optional[Tuple[int, int]] = None,
24     rgb_output: bool = True,
25 ) -> np.ndarray:
26     """Read an image file into numpy format
27 
28     Example::
29         >>> from doctr.documents import read_img
30         >>> page = read_img("path/to/your/doc.jpg")
31 
32     Args:
33         file: the path to the image file
34         output_size: the expected output size of each page in format H x W
35         rgb_output: whether the output ndarray channel order should be RGB instead of BGR.
36     Returns:
37         the page decoded as numpy ndarray of shape H x W x 3
38     """
39 
40     if isinstance(file, (str, Path)):
41         if not Path(file).is_file():
42             raise FileNotFoundError(f"unable to access {file}")
43         img = cv2.imread(str(file), cv2.IMREAD_COLOR)
44     elif isinstance(file, bytes):
45         file = np.frombuffer(file, np.uint8)
46         img = cv2.imdecode(file, cv2.IMREAD_COLOR)
47     else:
48         raise TypeError("unsupported object type for argument 'file'")
49 
50     # Validity check
51     if img is None:
52         raise ValueError("unable to read file.")
53     # Resizing
54     if isinstance(output_size, tuple):
55         img = cv2.resize(img, output_size[::-1], interpolation=cv2.INTER_LINEAR)
56     # Switch the channel order
57     if rgb_output:
58         img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
59     return img
60 
61 
62 def read_pdf(file: AbstractFile, **kwargs: Any) -> fitz.Document:
63     """Read a PDF file and convert it into an image in numpy format
64 
65     Example::
66         >>> from doctr.documents import read_pdf
67         >>> doc = read_pdf("path/to/your/doc.pdf")
68 
69     Args:
70         file: the path to the PDF file
71     Returns:
72         the list of pages decoded as numpy ndarray of shape H x W x 3
73     """
74 
75     if isinstance(file, (str, Path)) and not Path(file).is_file():
76         raise FileNotFoundError(f"unable to access {file}")
77 
78     fitz_args = {}
79 
80     if isinstance(file, (str, Path)):
81         fitz_args['filename'] = file
82     elif isinstance(file, bytes):
83         fitz_args['stream'] = file
84     else:
85         raise TypeError("unsupported object type for argument 'file'")
86 
87     # Read pages with fitz and convert them to numpy ndarrays
88     return fitz.open(**fitz_args, filetype="pdf", **kwargs)
89 
90 
91 def convert_page_to_numpy(
92     page: fitz.fitz.Page,
93     output_size: Optional[Tuple[int, int]] = None,
94     rgb_output: bool = True,
95 ) -> np.ndarray:
96     """Convert a fitz page to a numpy-formatted image
97 
98     Args:
99         page: the page of a file read with PyMuPDF
100         output_size: the expected output size of each page in format H x W. Default goes to 840 x 595 for A4 pdf,
101         if you want to increase the resolution while preserving the original A4 aspect ratio can pass (1024, 726)
102         rgb_output: whether the output ndarray channel order should be RGB instead of BGR.
103 
104     Returns:
105         the rendered image in numpy format
106     """
107 
108     transform_matrix = None
109 
110     # If no output size is specified, keep the origin one
111     if output_size is not None:
112         scales = (output_size[1] / page.MediaBox[2], output_size[0] / page.MediaBox[3])
113         transform_matrix = fitz.Matrix(*scales)
114 
115     # Generate the pixel map using the transformation matrix
116     stream = page.getPixmap(matrix=transform_matrix).getImageData()
117     # Decode it into a numpy
118     img = cv2.imdecode(np.frombuffer(stream, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
119 
120     # Switch the channel order
121     if rgb_output:
122         img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
123 
124     return img
125 
126 
127 def read_html(url: str, **kwargs: Any) -> bytes:
128     """Read a PDF file and convert it into an image in numpy format
129 
130     Example::
131         >>> from doctr.documents import read_html
132         >>> doc = read_html("https://www.yoursite.com")
133 
134     Args:
135         url: URL of the target web page
136     Returns:
137         decoded PDF file as a bytes stream
138     """
139 
140     return HTML(url, **kwargs).write_pdf()
141 
142 
143 class PDF:
144     """PDF document template
145 
146     Args:
147         doc: input PDF document
148     """
149     def __init__(self, doc: fitz.Document) -> None:
150         self.doc = doc
151 
152     def as_images(self, **kwargs) -> List[np.ndarray]:
153         """Convert all document pages to images
154 
155         Example::
156             >>> from doctr.documents import DocumentFile
157             >>> pages = DocumentFile.from_pdf("path/to/your/doc.pdf").as_images()
158 
159         Args:
160             kwargs: keyword arguments of `convert_page_to_numpy`
161         Returns:
162             the list of pages decoded as numpy ndarray of shape H x W x 3
163         """
164         return [convert_page_to_numpy(page, **kwargs) for page in self.doc]
165 
166     def get_page_words(self, idx, **kwargs) -> List[Tuple[Bbox, str]]:
167         """Get the annotations for all words of a given page"""
168 
169         # xmin, ymin, xmax, ymax, value, block_idx, line_idx, word_idx
170         return [(info[:4], info[4]) for info in self.doc[idx].getTextWords(**kwargs)]
171 
172     def get_words(self, **kwargs) -> List[List[Tuple[Bbox, str]]]:
173         """Get the annotations for all words in the document
174 
175         Example::
176             >>> from doctr.documents import DocumentFile
177             >>> words = DocumentFile.from_pdf("path/to/your/doc.pdf").get_words()
178 
179         Args:
180             kwargs: keyword arguments of `fitz.Page.getTextWords`
181         Returns:
182             the list of pages annotations, represented as a list of tuple (bounding box, value)
183         """
184         return [self.get_page_words(idx, **kwargs) for idx in range(len(self.doc))]
185 
186     def get_page_artefacts(self, idx) -> List[Tuple[float, float, float, float]]:
187         return [tuple(self.doc[idx].getImageBbox(artefact)) for artefact in self.doc[idx].get_images(full=True)]
188 
189     def get_artefacts(self) -> List[List[Tuple[float, float, float, float]]]:
190         """Get the artefacts for the entire document
191 
192         Example::
193             >>> from doctr.documents import DocumentFile
194             >>> artefacts = DocumentFile.from_pdf("path/to/your/doc.pdf").get_artefacts()
195 
196         Returns:
197             the list of pages artefacts, represented as a list of bounding boxes
198         """
199 
200         return [self.get_page_artefacts(idx) for idx in range(len(self.doc))]
201 
202 
203 class DocumentFile:
204     """Read a document from multiple extensions"""
205 
206     @classmethod
207     def from_pdf(cls, file: AbstractFile, **kwargs) -> PDF:
208         """Read a PDF file
209 
210         Example::
211             >>> from doctr.documents import DocumentFile
212             >>> doc = DocumentFile.from_pdf("path/to/your/doc.pdf")
213 
214         Args:
215             file: the path to the PDF file or a binary stream
216         Returns:
217             a PDF document
218         """
219 
220         doc = read_pdf(file, **kwargs)
221 
222         return PDF(doc)
223 
224     @classmethod
225     def from_url(cls, url: str, **kwargs) -> PDF:
226         """Interpret a web page as a PDF document
227 
228         Example::
229             >>> from doctr.documents import DocumentFile
230             >>> doc = DocumentFile.from_url("https://www.yoursite.com")
231 
232         Args:
233             url: the URL of the target web page
234         Returns:
235             a PDF document
236         """
237         pdf_stream = read_html(url)
238         return cls.from_pdf(pdf_stream, **kwargs)
239 
240     @classmethod
241     def from_images(cls, files: Union[Sequence[AbstractFile], AbstractFile], **kwargs) -> List[np.ndarray]:
242         """Read an image file (or a collection of image files) and convert it into an image in numpy format
243 
244         Example::
245             >>> from doctr.documents import DocumentFile
246             >>> pages = DocumentFile.from_images(["path/to/your/page1.png", "path/to/your/page2.png"])
247 
248         Args:
249             files: the path to the image file or a binary stream, or a collection of those
250         Returns:
251             the list of pages decoded as numpy ndarray of shape H x W x 3
252         """
253         if isinstance(files, (str, Path, bytes)):
254             files = [files]
255 
256         return [read_img(file, **kwargs) for file in files]
257
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/doctr/documents/reader.py b/doctr/documents/reader.py
--- a/doctr/documents/reader.py
+++ b/doctr/documents/reader.py
@@ -10,7 +10,7 @@
 from weasyprint import HTML
 from typing import List, Tuple, Optional, Any, Union, Sequence
 
-__all__ = ['read_pdf', 'read_img', 'read_html', 'DocumentFile']
+__all__ = ['read_pdf', 'read_img', 'read_html', 'DocumentFile', 'PDF']
 
 
 AbstractPath = Union[str, Path]
@@ -92,6 +92,7 @@
     page: fitz.fitz.Page,
     output_size: Optional[Tuple[int, int]] = None,
     rgb_output: bool = True,
+    default_scales: Tuple[float, float] = (2, 2),
 ) -> np.ndarray:
     """Convert a fitz page to a numpy-formatted image
 
@@ -100,17 +101,21 @@
         output_size: the expected output size of each page in format H x W. Default goes to 840 x 595 for A4 pdf,
         if you want to increase the resolution while preserving the original A4 aspect ratio can pass (1024, 726)
         rgb_output: whether the output ndarray channel order should be RGB instead of BGR.
+        default_scales: spatial scaling to be applied when output_size is not specified where (1, 1)
+            corresponds to 72 dpi rendering.
 
     Returns:
         the rendered image in numpy format
     """
 
-    transform_matrix = None
-
     # If no output size is specified, keep the origin one
     if output_size is not None:
         scales = (output_size[1] / page.MediaBox[2], output_size[0] / page.MediaBox[3])
-        transform_matrix = fitz.Matrix(*scales)
+    else:
+        # Default 72 DPI (scales of (1, 1)) is unnecessarily low
+        scales = default_scales
+
+    transform_matrix = fitz.Matrix(*scales)
 
     # Generate the pixel map using the transformation matrix
     stream = page.getPixmap(matrix=transform_matrix).getImageData()

{"golden_diff": "diff --git a/doctr/documents/reader.py b/doctr/documents/reader.py\n--- a/doctr/documents/reader.py\n+++ b/doctr/documents/reader.py\n@@ -10,7 +10,7 @@\n from weasyprint import HTML\n from typing import List, Tuple, Optional, Any, Union, Sequence\n \n-__all__ = ['read_pdf', 'read_img', 'read_html', 'DocumentFile']\n+__all__ = ['read_pdf', 'read_img', 'read_html', 'DocumentFile', 'PDF']\n \n \n AbstractPath = Union[str, Path]\n@@ -92,6 +92,7 @@\n     page: fitz.fitz.Page,\n     output_size: Optional[Tuple[int, int]] = None,\n     rgb_output: bool = True,\n+    default_scales: Tuple[float, float] = (2, 2),\n ) -> np.ndarray:\n     \"\"\"Convert a fitz page to a numpy-formatted image\n \n@@ -100,17 +101,21 @@\n         output_size: the expected output size of each page in format H x W. Default goes to 840 x 595 for A4 pdf,\n         if you want to increase the resolution while preserving the original A4 aspect ratio can pass (1024, 726)\n         rgb_output: whether the output ndarray channel order should be RGB instead of BGR.\n+        default_scales: spatial scaling to be applied when output_size is not specified where (1, 1)\n+            corresponds to 72 dpi rendering.\n \n     Returns:\n         the rendered image in numpy format\n     \"\"\"\n \n-    transform_matrix = None\n-\n     # If no output size is specified, keep the origin one\n     if output_size is not None:\n         scales = (output_size[1] / page.MediaBox[2], output_size[0] / page.MediaBox[3])\n-        transform_matrix = fitz.Matrix(*scales)\n+    else:\n+        # Default 72 DPI (scales of (1, 1)) is unnecessarily low\n+        scales = default_scales\n+\n+    transform_matrix = fitz.Matrix(*scales)\n \n     # Generate the pixel map using the transformation matrix\n     stream = page.getPixmap(matrix=transform_matrix).getImageData()\n", "issue": "[document] Check integrity of PDF --> img conversion with default DPI\nThe current PDF reading implies a conversion to an image. As we are using the default args for this conversion, the DPI value might be low. We need to check that the default parameter is not bringing about performance issues due to low resolution rendering.\n", "before_files": [{"content": "# Copyright (C) 2021, Mindee.\n\n# This program is licensed under the Apache License version 2.\n# See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0.txt> for full license details.\n\nimport numpy as np\nimport cv2\nfrom pathlib import Path\nimport fitz\nfrom weasyprint import HTML\nfrom typing import List, Tuple, Optional, Any, Union, Sequence\n\n__all__ = ['read_pdf', 'read_img', 'read_html', 'DocumentFile']\n\n\nAbstractPath = Union[str, Path]\nAbstractFile = Union[AbstractPath, bytes]\nBbox = Tuple[float, float, float, float]\n\n\ndef read_img(\n    file: AbstractFile,\n    output_size: Optional[Tuple[int, int]] = None,\n    rgb_output: bool = True,\n) -> np.ndarray:\n    \"\"\"Read an image file into numpy format\n\n    Example::\n        >>> from doctr.documents import read_img\n        >>> page = read_img(\"path/to/your/doc.jpg\")\n\n    Args:\n        file: the path to the image file\n        output_size: the expected output size of each page in format H x W\n        rgb_output: whether the output ndarray channel order should be RGB instead of BGR.\n    Returns:\n        the page decoded as numpy ndarray of shape H x W x 3\n    \"\"\"\n\n    if isinstance(file, (str, Path)):\n        if not Path(file).is_file():\n            raise FileNotFoundError(f\"unable to access {file}\")\n        img = cv2.imread(str(file), cv2.IMREAD_COLOR)\n    elif isinstance(file, bytes):\n        file = np.frombuffer(file, np.uint8)\n        img = cv2.imdecode(file, cv2.IMREAD_COLOR)\n    else:\n        raise TypeError(\"unsupported object type for argument 'file'\")\n\n    # Validity check\n    if img is None:\n        raise ValueError(\"unable to read file.\")\n    # Resizing\n    if isinstance(output_size, tuple):\n        img = cv2.resize(img, output_size[::-1], interpolation=cv2.INTER_LINEAR)\n    # Switch the channel order\n    if rgb_output:\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    return img\n\n\ndef read_pdf(file: AbstractFile, **kwargs: Any) -> fitz.Document:\n    \"\"\"Read a PDF file and convert it into an image in numpy format\n\n    Example::\n        >>> from doctr.documents import read_pdf\n        >>> doc = read_pdf(\"path/to/your/doc.pdf\")\n\n    Args:\n        file: the path to the PDF file\n    Returns:\n        the list of pages decoded as numpy ndarray of shape H x W x 3\n    \"\"\"\n\n    if isinstance(file, (str, Path)) and not Path(file).is_file():\n        raise FileNotFoundError(f\"unable to access {file}\")\n\n    fitz_args = {}\n\n    if isinstance(file, (str, Path)):\n        fitz_args['filename'] = file\n    elif isinstance(file, bytes):\n        fitz_args['stream'] = file\n    else:\n        raise TypeError(\"unsupported object type for argument 'file'\")\n\n    # Read pages with fitz and convert them to numpy ndarrays\n    return fitz.open(**fitz_args, filetype=\"pdf\", **kwargs)\n\n\ndef convert_page_to_numpy(\n    page: fitz.fitz.Page,\n    output_size: Optional[Tuple[int, int]] = None,\n    rgb_output: bool = True,\n) -> np.ndarray:\n    \"\"\"Convert a fitz page to a numpy-formatted image\n\n    Args:\n        page: the page of a file read with PyMuPDF\n        output_size: the expected output size of each page in format H x W. Default goes to 840 x 595 for A4 pdf,\n        if you want to increase the resolution while preserving the original A4 aspect ratio can pass (1024, 726)\n        rgb_output: whether the output ndarray channel order should be RGB instead of BGR.\n\n    Returns:\n        the rendered image in numpy format\n    \"\"\"\n\n    transform_matrix = None\n\n    # If no output size is specified, keep the origin one\n    if output_size is not None:\n        scales = (output_size[1] / page.MediaBox[2], output_size[0] / page.MediaBox[3])\n        transform_matrix = fitz.Matrix(*scales)\n\n    # Generate the pixel map using the transformation matrix\n    stream = page.getPixmap(matrix=transform_matrix).getImageData()\n    # Decode it into a numpy\n    img = cv2.imdecode(np.frombuffer(stream, dtype=np.uint8), cv2.IMREAD_UNCHANGED)\n\n    # Switch the channel order\n    if rgb_output:\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n\n    return img\n\n\ndef read_html(url: str, **kwargs: Any) -> bytes:\n    \"\"\"Read a PDF file and convert it into an image in numpy format\n\n    Example::\n        >>> from doctr.documents import read_html\n        >>> doc = read_html(\"https://www.yoursite.com\")\n\n    Args:\n        url: URL of the target web page\n    Returns:\n        decoded PDF file as a bytes stream\n    \"\"\"\n\n    return HTML(url, **kwargs).write_pdf()\n\n\nclass PDF:\n    \"\"\"PDF document template\n\n    Args:\n        doc: input PDF document\n    \"\"\"\n    def __init__(self, doc: fitz.Document) -> None:\n        self.doc = doc\n\n    def as_images(self, **kwargs) -> List[np.ndarray]:\n        \"\"\"Convert all document pages to images\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> pages = DocumentFile.from_pdf(\"path/to/your/doc.pdf\").as_images()\n\n        Args:\n            kwargs: keyword arguments of `convert_page_to_numpy`\n        Returns:\n            the list of pages decoded as numpy ndarray of shape H x W x 3\n        \"\"\"\n        return [convert_page_to_numpy(page, **kwargs) for page in self.doc]\n\n    def get_page_words(self, idx, **kwargs) -> List[Tuple[Bbox, str]]:\n        \"\"\"Get the annotations for all words of a given page\"\"\"\n\n        # xmin, ymin, xmax, ymax, value, block_idx, line_idx, word_idx\n        return [(info[:4], info[4]) for info in self.doc[idx].getTextWords(**kwargs)]\n\n    def get_words(self, **kwargs) -> List[List[Tuple[Bbox, str]]]:\n        \"\"\"Get the annotations for all words in the document\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> words = DocumentFile.from_pdf(\"path/to/your/doc.pdf\").get_words()\n\n        Args:\n            kwargs: keyword arguments of `fitz.Page.getTextWords`\n        Returns:\n            the list of pages annotations, represented as a list of tuple (bounding box, value)\n        \"\"\"\n        return [self.get_page_words(idx, **kwargs) for idx in range(len(self.doc))]\n\n    def get_page_artefacts(self, idx) -> List[Tuple[float, float, float, float]]:\n        return [tuple(self.doc[idx].getImageBbox(artefact)) for artefact in self.doc[idx].get_images(full=True)]\n\n    def get_artefacts(self) -> List[List[Tuple[float, float, float, float]]]:\n        \"\"\"Get the artefacts for the entire document\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> artefacts = DocumentFile.from_pdf(\"path/to/your/doc.pdf\").get_artefacts()\n\n        Returns:\n            the list of pages artefacts, represented as a list of bounding boxes\n        \"\"\"\n\n        return [self.get_page_artefacts(idx) for idx in range(len(self.doc))]\n\n\nclass DocumentFile:\n    \"\"\"Read a document from multiple extensions\"\"\"\n\n    @classmethod\n    def from_pdf(cls, file: AbstractFile, **kwargs) -> PDF:\n        \"\"\"Read a PDF file\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> doc = DocumentFile.from_pdf(\"path/to/your/doc.pdf\")\n\n        Args:\n            file: the path to the PDF file or a binary stream\n        Returns:\n            a PDF document\n        \"\"\"\n\n        doc = read_pdf(file, **kwargs)\n\n        return PDF(doc)\n\n    @classmethod\n    def from_url(cls, url: str, **kwargs) -> PDF:\n        \"\"\"Interpret a web page as a PDF document\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> doc = DocumentFile.from_url(\"https://www.yoursite.com\")\n\n        Args:\n            url: the URL of the target web page\n        Returns:\n            a PDF document\n        \"\"\"\n        pdf_stream = read_html(url)\n        return cls.from_pdf(pdf_stream, **kwargs)\n\n    @classmethod\n    def from_images(cls, files: Union[Sequence[AbstractFile], AbstractFile], **kwargs) -> List[np.ndarray]:\n        \"\"\"Read an image file (or a collection of image files) and convert it into an image in numpy format\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> pages = DocumentFile.from_images([\"path/to/your/page1.png\", \"path/to/your/page2.png\"])\n\n        Args:\n            files: the path to the image file or a binary stream, or a collection of those\n        Returns:\n            the list of pages decoded as numpy ndarray of shape H x W x 3\n        \"\"\"\n        if isinstance(files, (str, Path, bytes)):\n            files = [files]\n\n        return [read_img(file, **kwargs) for file in files]\n", "path": "doctr/documents/reader.py"}], "after_files": [{"content": "# Copyright (C) 2021, Mindee.\n\n# This program is licensed under the Apache License version 2.\n# See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0.txt> for full license details.\n\nimport numpy as np\nimport cv2\nfrom pathlib import Path\nimport fitz\nfrom weasyprint import HTML\nfrom typing import List, Tuple, Optional, Any, Union, Sequence\n\n__all__ = ['read_pdf', 'read_img', 'read_html', 'DocumentFile', 'PDF']\n\n\nAbstractPath = Union[str, Path]\nAbstractFile = Union[AbstractPath, bytes]\nBbox = Tuple[float, float, float, float]\n\n\ndef read_img(\n    file: AbstractFile,\n    output_size: Optional[Tuple[int, int]] = None,\n    rgb_output: bool = True,\n) -> np.ndarray:\n    \"\"\"Read an image file into numpy format\n\n    Example::\n        >>> from doctr.documents import read_img\n        >>> page = read_img(\"path/to/your/doc.jpg\")\n\n    Args:\n        file: the path to the image file\n        output_size: the expected output size of each page in format H x W\n        rgb_output: whether the output ndarray channel order should be RGB instead of BGR.\n    Returns:\n        the page decoded as numpy ndarray of shape H x W x 3\n    \"\"\"\n\n    if isinstance(file, (str, Path)):\n        if not Path(file).is_file():\n            raise FileNotFoundError(f\"unable to access {file}\")\n        img = cv2.imread(str(file), cv2.IMREAD_COLOR)\n    elif isinstance(file, bytes):\n        file = np.frombuffer(file, np.uint8)\n        img = cv2.imdecode(file, cv2.IMREAD_COLOR)\n    else:\n        raise TypeError(\"unsupported object type for argument 'file'\")\n\n    # Validity check\n    if img is None:\n        raise ValueError(\"unable to read file.\")\n    # Resizing\n    if isinstance(output_size, tuple):\n        img = cv2.resize(img, output_size[::-1], interpolation=cv2.INTER_LINEAR)\n    # Switch the channel order\n    if rgb_output:\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    return img\n\n\ndef read_pdf(file: AbstractFile, **kwargs: Any) -> fitz.Document:\n    \"\"\"Read a PDF file and convert it into an image in numpy format\n\n    Example::\n        >>> from doctr.documents import read_pdf\n        >>> doc = read_pdf(\"path/to/your/doc.pdf\")\n\n    Args:\n        file: the path to the PDF file\n    Returns:\n        the list of pages decoded as numpy ndarray of shape H x W x 3\n    \"\"\"\n\n    if isinstance(file, (str, Path)) and not Path(file).is_file():\n        raise FileNotFoundError(f\"unable to access {file}\")\n\n    fitz_args = {}\n\n    if isinstance(file, (str, Path)):\n        fitz_args['filename'] = file\n    elif isinstance(file, bytes):\n        fitz_args['stream'] = file\n    else:\n        raise TypeError(\"unsupported object type for argument 'file'\")\n\n    # Read pages with fitz and convert them to numpy ndarrays\n    return fitz.open(**fitz_args, filetype=\"pdf\", **kwargs)\n\n\ndef convert_page_to_numpy(\n    page: fitz.fitz.Page,\n    output_size: Optional[Tuple[int, int]] = None,\n    rgb_output: bool = True,\n    default_scales: Tuple[float, float] = (2, 2),\n) -> np.ndarray:\n    \"\"\"Convert a fitz page to a numpy-formatted image\n\n    Args:\n        page: the page of a file read with PyMuPDF\n        output_size: the expected output size of each page in format H x W. Default goes to 840 x 595 for A4 pdf,\n        if you want to increase the resolution while preserving the original A4 aspect ratio can pass (1024, 726)\n        rgb_output: whether the output ndarray channel order should be RGB instead of BGR.\n        default_scales: spatial scaling to be applied when output_size is not specified where (1, 1)\n            corresponds to 72 dpi rendering.\n\n    Returns:\n        the rendered image in numpy format\n    \"\"\"\n\n    # If no output size is specified, keep the origin one\n    if output_size is not None:\n        scales = (output_size[1] / page.MediaBox[2], output_size[0] / page.MediaBox[3])\n    else:\n        # Default 72 DPI (scales of (1, 1)) is unnecessarily low\n        scales = default_scales\n\n    transform_matrix = fitz.Matrix(*scales)\n\n    # Generate the pixel map using the transformation matrix\n    stream = page.getPixmap(matrix=transform_matrix).getImageData()\n    # Decode it into a numpy\n    img = cv2.imdecode(np.frombuffer(stream, dtype=np.uint8), cv2.IMREAD_UNCHANGED)\n\n    # Switch the channel order\n    if rgb_output:\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n\n    return img\n\n\ndef read_html(url: str, **kwargs: Any) -> bytes:\n    \"\"\"Read a PDF file and convert it into an image in numpy format\n\n    Example::\n        >>> from doctr.documents import read_html\n        >>> doc = read_html(\"https://www.yoursite.com\")\n\n    Args:\n        url: URL of the target web page\n    Returns:\n        decoded PDF file as a bytes stream\n    \"\"\"\n\n    return HTML(url, **kwargs).write_pdf()\n\n\nclass PDF:\n    \"\"\"PDF document template\n\n    Args:\n        doc: input PDF document\n    \"\"\"\n    def __init__(self, doc: fitz.Document) -> None:\n        self.doc = doc\n\n    def as_images(self, **kwargs) -> List[np.ndarray]:\n        \"\"\"Convert all document pages to images\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> pages = DocumentFile.from_pdf(\"path/to/your/doc.pdf\").as_images()\n\n        Args:\n            kwargs: keyword arguments of `convert_page_to_numpy`\n        Returns:\n            the list of pages decoded as numpy ndarray of shape H x W x 3\n        \"\"\"\n        return [convert_page_to_numpy(page, **kwargs) for page in self.doc]\n\n    def get_page_words(self, idx, **kwargs) -> List[Tuple[Bbox, str]]:\n        \"\"\"Get the annotations for all words of a given page\"\"\"\n\n        # xmin, ymin, xmax, ymax, value, block_idx, line_idx, word_idx\n        return [(info[:4], info[4]) for info in self.doc[idx].getTextWords(**kwargs)]\n\n    def get_words(self, **kwargs) -> List[List[Tuple[Bbox, str]]]:\n        \"\"\"Get the annotations for all words in the document\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> words = DocumentFile.from_pdf(\"path/to/your/doc.pdf\").get_words()\n\n        Args:\n            kwargs: keyword arguments of `fitz.Page.getTextWords`\n        Returns:\n            the list of pages annotations, represented as a list of tuple (bounding box, value)\n        \"\"\"\n        return [self.get_page_words(idx, **kwargs) for idx in range(len(self.doc))]\n\n    def get_page_artefacts(self, idx) -> List[Tuple[float, float, float, float]]:\n        return [tuple(self.doc[idx].getImageBbox(artefact)) for artefact in self.doc[idx].get_images(full=True)]\n\n    def get_artefacts(self) -> List[List[Tuple[float, float, float, float]]]:\n        \"\"\"Get the artefacts for the entire document\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> artefacts = DocumentFile.from_pdf(\"path/to/your/doc.pdf\").get_artefacts()\n\n        Returns:\n            the list of pages artefacts, represented as a list of bounding boxes\n        \"\"\"\n\n        return [self.get_page_artefacts(idx) for idx in range(len(self.doc))]\n\n\nclass DocumentFile:\n    \"\"\"Read a document from multiple extensions\"\"\"\n\n    @classmethod\n    def from_pdf(cls, file: AbstractFile, **kwargs) -> PDF:\n        \"\"\"Read a PDF file\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> doc = DocumentFile.from_pdf(\"path/to/your/doc.pdf\")\n\n        Args:\n            file: the path to the PDF file or a binary stream\n        Returns:\n            a PDF document\n        \"\"\"\n\n        doc = read_pdf(file, **kwargs)\n\n        return PDF(doc)\n\n    @classmethod\n    def from_url(cls, url: str, **kwargs) -> PDF:\n        \"\"\"Interpret a web page as a PDF document\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> doc = DocumentFile.from_url(\"https://www.yoursite.com\")\n\n        Args:\n            url: the URL of the target web page\n        Returns:\n            a PDF document\n        \"\"\"\n        pdf_stream = read_html(url)\n        return cls.from_pdf(pdf_stream, **kwargs)\n\n    @classmethod\n    def from_images(cls, files: Union[Sequence[AbstractFile], AbstractFile], **kwargs) -> List[np.ndarray]:\n        \"\"\"Read an image file (or a collection of image files) and convert it into an image in numpy format\n\n        Example::\n            >>> from doctr.documents import DocumentFile\n            >>> pages = DocumentFile.from_images([\"path/to/your/page1.png\", \"path/to/your/page2.png\"])\n\n        Args:\n            files: the path to the image file or a binary stream, or a collection of those\n        Returns:\n            the list of pages decoded as numpy ndarray of shape H x W x 3\n        \"\"\"\n        if isinstance(files, (str, Path, bytes)):\n            files = [files]\n\n        return [read_img(file, **kwargs) for file in files]\n", "path": "doctr/documents/reader.py"}]}