rasgapdf 0.1.2__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/PKG-INFO +35 -4
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/README.md +33 -2
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/pyproject.toml +2 -2
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/rasgapdf/__init__.py +68 -4
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/rasgapdf/librasgapdf.so +0 -0
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/rasgapdf.egg-info/PKG-INFO +35 -4
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/rasgapdf.egg-info/SOURCES.txt +0 -0
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/rasgapdf.egg-info/dependency_links.txt +0 -0
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/rasgapdf.egg-info/top_level.txt +0 -0
- {rasgapdf-0.1.2 → rasgapdf-0.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rasgapdf
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Ultra-fast 2D spatial PDF parser powered by Rust
|
|
5
5
|
Author: Messias Martins
|
|
6
6
|
Project-URL: Homepage, https://huggingface.co/martinsmessias/rasgapdf
|
|
@@ -8,7 +8,7 @@ Project-URL: Repository, https://huggingface.co/martinsmessias/rasgapdf
|
|
|
8
8
|
Project-URL: Discussions, https://huggingface.co/martinsmessias/rasgapdf/discussions
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: Programming Language :: Rust
|
|
11
|
-
Classifier: License :: OSI Approved ::
|
|
11
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
|
12
12
|
Classifier: Operating System :: POSIX :: Linux
|
|
13
13
|
Classifier: Topic :: Text Processing :: General
|
|
14
14
|
Requires-Python: >=3.8
|
|
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
|
|
24
24
|
[](https://pypi.org/project/rasgapdf/)
|
|
25
25
|
[](https://pypi.org/project/rasgapdf/)
|
|
26
|
-
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
27
27
|
|
|
28
28
|
</div>
|
|
29
29
|
|
|
@@ -149,9 +149,40 @@ for page in doc["pages"]:
|
|
|
149
149
|
| `min_table_cols` | `int` | `3` | Minimum number of columns required to classify as a table |
|
|
150
150
|
| `col_tolerance` | `float` | `16.0` | Horizontal alignment threshold in typographical points |
|
|
151
151
|
| `row_tolerance` | `float` | `6.0` | Vertical line clustering threshold in points |
|
|
152
|
+
| `extract_images` | `bool` | `False` | Fill `page["images"]` with embedded image metadata (dimensions, colour space, filter, SHA-256, placement `bbox`) |
|
|
153
|
+
| `extract_drawings` | `bool` | `False` | Fill `page["drawings"]` with vector paths (`line`/`curve`/`rect`/`quad` items, colours, dash, opacity) |
|
|
154
|
+
| `keep_background_fills` | `bool` | `False` | Keep fills that cover the whole page (backgrounds are dropped by default) |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### 🖼️ Embedded Images & Vector Graphics
|
|
159
|
+
|
|
160
|
+
Opt-in extraction of the graphics layer. Pixels are never decoded — metadata stays in the JSON and the original encoded stream is written to disk as-is:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
import rasgapdf
|
|
164
|
+
|
|
165
|
+
doc = rasgapdf.parse_pdf("report.pdf", extract_images=True, extract_drawings=True)
|
|
166
|
+
|
|
167
|
+
page = doc["pages"][0]
|
|
168
|
+
for image in page["images"]:
|
|
169
|
+
print(image["name"], image["pixel_width"], "x", image["pixel_height"],
|
|
170
|
+
image["filter"], image["bbox"])
|
|
171
|
+
|
|
172
|
+
for drawing in page["drawings"]:
|
|
173
|
+
print(drawing["drawing_id"], drawing["drawing_type"], drawing["stroke_color"])
|
|
174
|
+
|
|
175
|
+
# Writes report JPEGs (e.g. page_001_img_001_xref7.jpg) plus manifest.json
|
|
176
|
+
manifest = rasgapdf.extract_images("report.pdf", "./out")
|
|
177
|
+
print(manifest["written"], "files written")
|
|
178
|
+
```
|
|
152
179
|
|
|
153
180
|
---
|
|
154
181
|
|
|
155
182
|
## 📄 License
|
|
156
183
|
|
|
157
|
-
|
|
184
|
+
GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (c) 2026 Messias Martins.
|
|
185
|
+
|
|
186
|
+
RasgaPDF embeds and links against [MuPDF](https://mupdf.com/) (Artifex Software),
|
|
187
|
+
which is distributed under the AGPL-3.0. That is why this project is licensed
|
|
188
|
+
under the same terms.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
[](https://pypi.org/project/rasgapdf/)
|
|
9
9
|
[](https://pypi.org/project/rasgapdf/)
|
|
10
|
-
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -133,9 +133,40 @@ for page in doc["pages"]:
|
|
|
133
133
|
| `min_table_cols` | `int` | `3` | Minimum number of columns required to classify as a table |
|
|
134
134
|
| `col_tolerance` | `float` | `16.0` | Horizontal alignment threshold in typographical points |
|
|
135
135
|
| `row_tolerance` | `float` | `6.0` | Vertical line clustering threshold in points |
|
|
136
|
+
| `extract_images` | `bool` | `False` | Fill `page["images"]` with embedded image metadata (dimensions, colour space, filter, SHA-256, placement `bbox`) |
|
|
137
|
+
| `extract_drawings` | `bool` | `False` | Fill `page["drawings"]` with vector paths (`line`/`curve`/`rect`/`quad` items, colours, dash, opacity) |
|
|
138
|
+
| `keep_background_fills` | `bool` | `False` | Keep fills that cover the whole page (backgrounds are dropped by default) |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 🖼️ Embedded Images & Vector Graphics
|
|
143
|
+
|
|
144
|
+
Opt-in extraction of the graphics layer. Pixels are never decoded — metadata stays in the JSON and the original encoded stream is written to disk as-is:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
import rasgapdf
|
|
148
|
+
|
|
149
|
+
doc = rasgapdf.parse_pdf("report.pdf", extract_images=True, extract_drawings=True)
|
|
150
|
+
|
|
151
|
+
page = doc["pages"][0]
|
|
152
|
+
for image in page["images"]:
|
|
153
|
+
print(image["name"], image["pixel_width"], "x", image["pixel_height"],
|
|
154
|
+
image["filter"], image["bbox"])
|
|
155
|
+
|
|
156
|
+
for drawing in page["drawings"]:
|
|
157
|
+
print(drawing["drawing_id"], drawing["drawing_type"], drawing["stroke_color"])
|
|
158
|
+
|
|
159
|
+
# Writes report JPEGs (e.g. page_001_img_001_xref7.jpg) plus manifest.json
|
|
160
|
+
manifest = rasgapdf.extract_images("report.pdf", "./out")
|
|
161
|
+
print(manifest["written"], "files written")
|
|
162
|
+
```
|
|
136
163
|
|
|
137
164
|
---
|
|
138
165
|
|
|
139
166
|
## 📄 License
|
|
140
167
|
|
|
141
|
-
|
|
168
|
+
GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (c) 2026 Messias Martins.
|
|
169
|
+
|
|
170
|
+
RasgaPDF embeds and links against [MuPDF](https://mupdf.com/) (Artifex Software),
|
|
171
|
+
which is distributed under the AGPL-3.0. That is why this project is licensed
|
|
172
|
+
under the same terms.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rasgapdf"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Messias Martins" },
|
|
10
10
|
]
|
|
@@ -14,7 +14,7 @@ requires-python = ">=3.8"
|
|
|
14
14
|
classifiers = [
|
|
15
15
|
"Programming Language :: Python :: 3",
|
|
16
16
|
"Programming Language :: Rust",
|
|
17
|
-
"License :: OSI Approved ::
|
|
17
|
+
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
|
|
18
18
|
"Operating System :: POSIX :: Linux",
|
|
19
19
|
"Topic :: Text Processing :: General",
|
|
20
20
|
]
|
|
@@ -49,9 +49,14 @@ if _lib:
|
|
|
49
49
|
_lib.rasgapdf_version.argtypes = []
|
|
50
50
|
_lib.rasgapdf_version.restype = ctypes.c_char_p
|
|
51
51
|
|
|
52
|
+
# Disponível a partir da 0.1.4 (extração de imagens embutidas em disco).
|
|
53
|
+
if hasattr(_lib, "rasgapdf_extract_images"):
|
|
54
|
+
_lib.rasgapdf_extract_images.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
|
|
55
|
+
_lib.rasgapdf_extract_images.restype = ctypes.c_void_p
|
|
56
|
+
|
|
52
57
|
def version() -> str:
|
|
53
58
|
if not _lib:
|
|
54
|
-
return "0.
|
|
59
|
+
return "0.2.0 (unlinked)"
|
|
55
60
|
return _lib.rasgapdf_version().decode("utf-8")
|
|
56
61
|
|
|
57
62
|
def parse_raw(file_path: str) -> Dict[str, Any]:
|
|
@@ -108,20 +113,27 @@ def parse_pdf(
|
|
|
108
113
|
min_table_cols: int = 3,
|
|
109
114
|
col_tolerance: float = 16.0,
|
|
110
115
|
row_tolerance: float = 6.0,
|
|
116
|
+
extract_images: bool = False,
|
|
117
|
+
extract_drawings: bool = False,
|
|
118
|
+
keep_background_fills: bool = False,
|
|
111
119
|
) -> Dict[str, Any]:
|
|
112
120
|
"""
|
|
113
121
|
🎯 Modo 2 (Estruturado): Processa o PDF e retorna o layout espacial hierárquico
|
|
114
122
|
com blocos de texto, linhas, spans e tabelas detectadas.
|
|
115
|
-
|
|
123
|
+
|
|
116
124
|
Args:
|
|
117
125
|
file_path: Caminho do arquivo PDF.
|
|
118
126
|
detect_tables: Se deve detectar matrizes de tabelas automaticamente.
|
|
119
127
|
min_table_cols: Quantidade mínima de colunas para agrupar em tabela.
|
|
120
128
|
col_tolerance: Tolerância horizontal de alinhamento em pontos.
|
|
121
129
|
row_tolerance: Tolerância vertical de linha em pontos.
|
|
130
|
+
extract_images: Preenche `page["images"]` com os metadados das imagens embutidas.
|
|
131
|
+
extract_drawings: Preenche `page["drawings"]` com os caminhos vetoriais.
|
|
132
|
+
keep_background_fills: Mantém preenchimentos que cobrem a página inteira (fundos).
|
|
122
133
|
|
|
123
134
|
Returns:
|
|
124
|
-
dict: SpatialDocument contendo páginas, blocos, linhas
|
|
135
|
+
dict: SpatialDocument contendo páginas, blocos, linhas, tabelas,
|
|
136
|
+
imagens (opcional) e vetores (opcional).
|
|
125
137
|
"""
|
|
126
138
|
if not _lib:
|
|
127
139
|
raise RuntimeError(f"RasgaPDF native library ({_lib_path}) not loaded.")
|
|
@@ -135,6 +147,9 @@ def parse_pdf(
|
|
|
135
147
|
"min_table_columns": min_table_cols,
|
|
136
148
|
"column_tolerance": col_tolerance,
|
|
137
149
|
"row_tolerance": row_tolerance,
|
|
150
|
+
"extract_images": extract_images,
|
|
151
|
+
"extract_drawings": extract_drawings,
|
|
152
|
+
"filter_background_fills": not keep_background_fills,
|
|
138
153
|
}
|
|
139
154
|
|
|
140
155
|
path_bytes = os.path.abspath(file_path).encode("utf-8")
|
|
@@ -153,4 +168,53 @@ def parse_pdf(
|
|
|
153
168
|
finally:
|
|
154
169
|
_lib.rasgapdf_free_string(res_ptr)
|
|
155
170
|
|
|
156
|
-
|
|
171
|
+
def extract_images(file_path: str, output_dir: str) -> Dict[str, Any]:
|
|
172
|
+
"""
|
|
173
|
+
🖼️ Extrai os streams originais das imagens embutidas para `output_dir`.
|
|
174
|
+
|
|
175
|
+
Nenhum pixel é decodificado: o stream codificado é copiado como está
|
|
176
|
+
(ex.: `DCTDecode` → `.jpg`). Um `manifest.json` é gravado junto.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
file_path: Caminho do arquivo PDF.
|
|
180
|
+
output_dir: Pasta destino (criada se não existir).
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
dict: {
|
|
184
|
+
"total_images": int,
|
|
185
|
+
"written": int,
|
|
186
|
+
"images": [
|
|
187
|
+
{"page": int, "image": {..., "file": str}},
|
|
188
|
+
...
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
"""
|
|
192
|
+
if not _lib:
|
|
193
|
+
raise RuntimeError(f"RasgaPDF native library ({_lib_path}) not loaded.")
|
|
194
|
+
|
|
195
|
+
if not hasattr(_lib, "rasgapdf_extract_images"):
|
|
196
|
+
raise RuntimeError(
|
|
197
|
+
"A biblioteca nativa carregada não expõe `rasgapdf_extract_images`. "
|
|
198
|
+
"Recompile/atualize o RasgaPDF."
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
if not os.path.exists(file_path):
|
|
202
|
+
raise FileNotFoundError(f"PDF file not found: {file_path}")
|
|
203
|
+
|
|
204
|
+
path_bytes = os.path.abspath(file_path).encode("utf-8")
|
|
205
|
+
dir_bytes = os.path.abspath(output_dir).encode("utf-8")
|
|
206
|
+
|
|
207
|
+
res_ptr = _lib.rasgapdf_extract_images(path_bytes, dir_bytes)
|
|
208
|
+
if not res_ptr:
|
|
209
|
+
raise RuntimeError("Null pointer returned from native rasgapdf library.")
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
raw_json = ctypes.string_at(res_ptr).decode("utf-8")
|
|
213
|
+
parsed = json.loads(raw_json)
|
|
214
|
+
if isinstance(parsed, dict) and parsed.get("error"):
|
|
215
|
+
raise RuntimeError(f"RasgaPDF Error: {parsed.get('message')}")
|
|
216
|
+
return parsed
|
|
217
|
+
finally:
|
|
218
|
+
_lib.rasgapdf_free_string(res_ptr)
|
|
219
|
+
|
|
220
|
+
__all__ = ["parse_raw", "parse_pdf", "extract_images", "version"]
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rasgapdf
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Ultra-fast 2D spatial PDF parser powered by Rust
|
|
5
5
|
Author: Messias Martins
|
|
6
6
|
Project-URL: Homepage, https://huggingface.co/martinsmessias/rasgapdf
|
|
@@ -8,7 +8,7 @@ Project-URL: Repository, https://huggingface.co/martinsmessias/rasgapdf
|
|
|
8
8
|
Project-URL: Discussions, https://huggingface.co/martinsmessias/rasgapdf/discussions
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: Programming Language :: Rust
|
|
11
|
-
Classifier: License :: OSI Approved ::
|
|
11
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
|
12
12
|
Classifier: Operating System :: POSIX :: Linux
|
|
13
13
|
Classifier: Topic :: Text Processing :: General
|
|
14
14
|
Requires-Python: >=3.8
|
|
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
|
|
24
24
|
[](https://pypi.org/project/rasgapdf/)
|
|
25
25
|
[](https://pypi.org/project/rasgapdf/)
|
|
26
|
-
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
27
27
|
|
|
28
28
|
</div>
|
|
29
29
|
|
|
@@ -149,9 +149,40 @@ for page in doc["pages"]:
|
|
|
149
149
|
| `min_table_cols` | `int` | `3` | Minimum number of columns required to classify as a table |
|
|
150
150
|
| `col_tolerance` | `float` | `16.0` | Horizontal alignment threshold in typographical points |
|
|
151
151
|
| `row_tolerance` | `float` | `6.0` | Vertical line clustering threshold in points |
|
|
152
|
+
| `extract_images` | `bool` | `False` | Fill `page["images"]` with embedded image metadata (dimensions, colour space, filter, SHA-256, placement `bbox`) |
|
|
153
|
+
| `extract_drawings` | `bool` | `False` | Fill `page["drawings"]` with vector paths (`line`/`curve`/`rect`/`quad` items, colours, dash, opacity) |
|
|
154
|
+
| `keep_background_fills` | `bool` | `False` | Keep fills that cover the whole page (backgrounds are dropped by default) |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### 🖼️ Embedded Images & Vector Graphics
|
|
159
|
+
|
|
160
|
+
Opt-in extraction of the graphics layer. Pixels are never decoded — metadata stays in the JSON and the original encoded stream is written to disk as-is:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
import rasgapdf
|
|
164
|
+
|
|
165
|
+
doc = rasgapdf.parse_pdf("report.pdf", extract_images=True, extract_drawings=True)
|
|
166
|
+
|
|
167
|
+
page = doc["pages"][0]
|
|
168
|
+
for image in page["images"]:
|
|
169
|
+
print(image["name"], image["pixel_width"], "x", image["pixel_height"],
|
|
170
|
+
image["filter"], image["bbox"])
|
|
171
|
+
|
|
172
|
+
for drawing in page["drawings"]:
|
|
173
|
+
print(drawing["drawing_id"], drawing["drawing_type"], drawing["stroke_color"])
|
|
174
|
+
|
|
175
|
+
# Writes report JPEGs (e.g. page_001_img_001_xref7.jpg) plus manifest.json
|
|
176
|
+
manifest = rasgapdf.extract_images("report.pdf", "./out")
|
|
177
|
+
print(manifest["written"], "files written")
|
|
178
|
+
```
|
|
152
179
|
|
|
153
180
|
---
|
|
154
181
|
|
|
155
182
|
## 📄 License
|
|
156
183
|
|
|
157
|
-
|
|
184
|
+
GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Copyright (c) 2026 Messias Martins.
|
|
185
|
+
|
|
186
|
+
RasgaPDF embeds and links against [MuPDF](https://mupdf.com/) (Artifex Software),
|
|
187
|
+
which is distributed under the AGPL-3.0. That is why this project is licensed
|
|
188
|
+
under the same terms.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|