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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rasgapdf
3
- Version: 0.1.2
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 :: MIT License
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
  [![PyPI version](https://img.shields.io/pypi/v/rasgapdf.svg?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/rasgapdf/)
25
25
  [![Python versions](https://img.shields.io/pypi/pyversions/rasgapdf.svg?logo=python&logoColor=white)](https://pypi.org/project/rasgapdf/)
26
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
26
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](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
- MIT License. Copyright (c) 2026 Messias Martins.
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
  [![PyPI version](https://img.shields.io/pypi/v/rasgapdf.svg?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/rasgapdf/)
9
9
  [![Python versions](https://img.shields.io/pypi/pyversions/rasgapdf.svg?logo=python&logoColor=white)](https://pypi.org/project/rasgapdf/)
10
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
10
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](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
- MIT License. Copyright (c) 2026 Messias Martins.
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.1.2"
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 :: MIT License",
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.1.0 (unlinked)"
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 e tabelas.
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
- __all__ = ["parse_raw", "parse_pdf", "version"]
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"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rasgapdf
3
- Version: 0.1.2
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 :: MIT License
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
  [![PyPI version](https://img.shields.io/pypi/v/rasgapdf.svg?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/rasgapdf/)
25
25
  [![Python versions](https://img.shields.io/pypi/pyversions/rasgapdf.svg?logo=python&logoColor=white)](https://pypi.org/project/rasgapdf/)
26
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
26
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](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
- MIT License. Copyright (c) 2026 Messias Martins.
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