convert-stream 1.1__py3-none-any.whl
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.
Potentially problematic release.
This version of convert-stream might be problematic. Click here for more details.
- convert_stream/__init__.py +19 -0
- convert_stream/__main__.py +29 -0
- convert_stream/_version.py +7 -0
- convert_stream/convert.py +300 -0
- convert_stream/imagelib.py +493 -0
- convert_stream/library.py +5 -0
- convert_stream/models/__init__.py +10 -0
- convert_stream/models/m_imgelib.py +107 -0
- convert_stream/models/m_pdf_convert.py +171 -0
- convert_stream/models/m_pdf_document.py +139 -0
- convert_stream/models/m_pdf_page.py +88 -0
- convert_stream/models/m_text.py +480 -0
- convert_stream/pdf_convert.py +282 -0
- convert_stream/pdf_document.py +534 -0
- convert_stream/pdf_page.py +251 -0
- convert_stream/text.py +8 -0
- convert_stream-1.1.dist-info/METADATA +45 -0
- convert_stream-1.1.dist-info/RECORD +20 -0
- convert_stream-1.1.dist-info/WHEEL +5 -0
- convert_stream-1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
from typing import List, Dict
|
|
6
|
+
from io import BytesIO
|
|
7
|
+
from PyPDF2 import PdfReader, PdfWriter, PageObject
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from fitz import Page, Pixmap, Document
|
|
11
|
+
except:
|
|
12
|
+
from pymupdf import Page, Pixmap, Document
|
|
13
|
+
|
|
14
|
+
from soup_files import File, Directory
|
|
15
|
+
from convertlib.models.m_text import TableText
|
|
16
|
+
from convertlib.models.m_imgelib import LibraryImage
|
|
17
|
+
from convertlib.models.m_pdf_page import LibraryPDF, ABCPagePdf
|
|
18
|
+
from convertlib.imagelib import ImageObject, ImageInverColor
|
|
19
|
+
|
|
20
|
+
#======================================================================#
|
|
21
|
+
# Página PDF
|
|
22
|
+
#======================================================================#
|
|
23
|
+
|
|
24
|
+
class PyPdf2PagePdf(ABCPagePdf):
|
|
25
|
+
"""Implementação para manipular páginas PDF com PyPDF2"""
|
|
26
|
+
def __init__(self, page:PageObject, page_number: int):
|
|
27
|
+
if not isinstance(page, PageObject):
|
|
28
|
+
raise ValueError(f'{__class__.__name__} Use: PageObject(), não {type(page)}')
|
|
29
|
+
self.page:PageObject = page
|
|
30
|
+
self.page_number:int = page_number
|
|
31
|
+
self.current_library = LibraryPDF.PYPDF
|
|
32
|
+
|
|
33
|
+
def to_string(self) -> str:
|
|
34
|
+
s = self.page.extract_text()
|
|
35
|
+
if (s is None) or (s == ''):
|
|
36
|
+
return None
|
|
37
|
+
return s
|
|
38
|
+
|
|
39
|
+
def to_list(self, separator:str='\n') -> List[str]:
|
|
40
|
+
return self.to_string().split(separator) if self.to_string() is not None else []
|
|
41
|
+
|
|
42
|
+
def to_table(self, separator:str='\n') -> TableText:
|
|
43
|
+
s = self.to_string()
|
|
44
|
+
if s is None:
|
|
45
|
+
return TableText('', separator=separator)
|
|
46
|
+
return TableText(s, separator=separator)
|
|
47
|
+
|
|
48
|
+
def rotate(self, degrees: int):
|
|
49
|
+
self.page.rotate(degrees)
|
|
50
|
+
|
|
51
|
+
def to_bytes(self) -> bytes:
|
|
52
|
+
pdf_writer = PdfWriter()
|
|
53
|
+
pdf_writer.add_page(self.page)
|
|
54
|
+
output_bytes = BytesIO()
|
|
55
|
+
pdf_writer.write(output_bytes)
|
|
56
|
+
pdf_bytes = output_bytes.getvalue()
|
|
57
|
+
output_bytes.close()
|
|
58
|
+
return pdf_bytes
|
|
59
|
+
|
|
60
|
+
def set_paisagem(self):
|
|
61
|
+
if not self.is_paisagem():
|
|
62
|
+
self.rotate(-90)
|
|
63
|
+
|
|
64
|
+
def is_paisagem(self):
|
|
65
|
+
return False if self.page.mediabox.width < self.page.mediabox.height else True
|
|
66
|
+
|
|
67
|
+
def set_page_fitz(self):
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
def set_page_pypdf2(self):
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def create_from_page_bytes(cls, page_bytes) -> PyPdf2PagePdf:
|
|
75
|
+
try:
|
|
76
|
+
pdf_writer = PdfWriter()
|
|
77
|
+
pdf_reader = PdfReader(BytesIO(page_bytes)) # Carrega o PDF a partir dos bytes
|
|
78
|
+
pdf_writer.add_page(pdf_reader.pages[0]) # Adiciona cada página ao escritor
|
|
79
|
+
except Exception as e:
|
|
80
|
+
print(e)
|
|
81
|
+
return None
|
|
82
|
+
else:
|
|
83
|
+
return cls(pdf_writer.pages[0], 1)
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def create_from_page_pypdf2(cls, page:PageObject):
|
|
87
|
+
if not isinstance(page, PageObject):
|
|
88
|
+
raise ValueError(f'{__class__.__name__}Use: PageObject(), não {type(page)}')
|
|
89
|
+
return cls(page, 1)
|
|
90
|
+
|
|
91
|
+
@classmethod
|
|
92
|
+
def create_from_page_fitz(cls, page) -> None:
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class FitzPagePdf(ABCPagePdf):
|
|
97
|
+
"""Implementação para manipular páginas PDF com fitz"""
|
|
98
|
+
def __init__(self, page: Page, page_number:int):
|
|
99
|
+
self.page:Page = page
|
|
100
|
+
self.page_number:int = page_number
|
|
101
|
+
self.current_library = LibraryPDF.FITZ
|
|
102
|
+
|
|
103
|
+
def to_string(self) -> str:
|
|
104
|
+
s = self.page.get_text()
|
|
105
|
+
if (s is None) or (s == ''):
|
|
106
|
+
return None
|
|
107
|
+
return s
|
|
108
|
+
|
|
109
|
+
def to_list(self, separator:str='\n') -> List[str]:
|
|
110
|
+
return self.to_string().split(separator) if self.to_string() is not None else []
|
|
111
|
+
|
|
112
|
+
def to_table(self, separator:str='\n') -> TableText:
|
|
113
|
+
s = self.to_string()
|
|
114
|
+
if s is None:
|
|
115
|
+
return TableText('', separator=separator)
|
|
116
|
+
return TableText(s, separator=separator)
|
|
117
|
+
|
|
118
|
+
def rotate(self, degrees: int):
|
|
119
|
+
# Ajuste para rotação anti-horária
|
|
120
|
+
current_rotation = self.page.rotation # Obter rotação atual da página
|
|
121
|
+
new_rotation = (current_rotation + degrees) % 360 # Atualizar a rotação acumulativa
|
|
122
|
+
self.page.set_rotation(new_rotation) # Aplicar a nova rotação
|
|
123
|
+
|
|
124
|
+
def to_bytes(self) -> bytes:
|
|
125
|
+
temp_doc = Document()
|
|
126
|
+
temp_doc.insert_pdf(self.page.parent, from_page=self.page.number, to_page=self.page.number)
|
|
127
|
+
return temp_doc.write()
|
|
128
|
+
|
|
129
|
+
def set_paisagem(self):
|
|
130
|
+
if not self.is_paisagem():
|
|
131
|
+
self.page.set_rotation(-90) # Rotaciona 90 graus para paisagem
|
|
132
|
+
|
|
133
|
+
def is_paisagem(self):
|
|
134
|
+
return False if self.page.rect.height > self.page.rect.width else True
|
|
135
|
+
|
|
136
|
+
def set_page_fitz(self):
|
|
137
|
+
pass
|
|
138
|
+
|
|
139
|
+
def set_page_pypdf2(self):
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
@classmethod
|
|
143
|
+
def create_from_page_bytes(cls, page_bytes) -> FitzPagePdf:
|
|
144
|
+
try:
|
|
145
|
+
merged_document = Document()
|
|
146
|
+
temp_doc:Document = Document(stream=page_bytes, filetype="pdf")
|
|
147
|
+
merged_document.insert_pdf(temp_doc)
|
|
148
|
+
current_page:Page = merged_document[0]
|
|
149
|
+
except Exception as e:
|
|
150
|
+
print(e)
|
|
151
|
+
return None
|
|
152
|
+
else:
|
|
153
|
+
return cls(current_page, current_page.number)
|
|
154
|
+
|
|
155
|
+
@classmethod
|
|
156
|
+
def create_from_page_pypdf2(cls, page:object) -> None:
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
@classmethod
|
|
160
|
+
def create_from_page_fitz(cls, page) -> FitzPagePdf:
|
|
161
|
+
if not isinstance(page, Page):
|
|
162
|
+
raise ValueError(f'{__class__.__name__}Use: Page(), não {type(page)}')
|
|
163
|
+
return cls(page, 1)
|
|
164
|
+
|
|
165
|
+
#======================================================================#
|
|
166
|
+
# FACADE para trabalhar com uma página PDF.
|
|
167
|
+
#======================================================================#
|
|
168
|
+
class PageDocumentPdf(ABCPagePdf):
|
|
169
|
+
def __init__(self, page:ABCPagePdf):
|
|
170
|
+
self.__page:ABCPagePdf = page
|
|
171
|
+
self.page_number:int = page.page_number
|
|
172
|
+
self.current_library:LibraryPDF = page.current_library
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def page(self) -> ABCPagePdf:
|
|
176
|
+
return self.__page
|
|
177
|
+
|
|
178
|
+
@page.setter
|
|
179
|
+
def page(self, new:ABCPagePdf):
|
|
180
|
+
if isinstance(new, PyPdf2PagePdf):
|
|
181
|
+
self.__page = new
|
|
182
|
+
elif isinstance(new, FitzPagePdf):
|
|
183
|
+
self.__page = new
|
|
184
|
+
elif isinstance(new, PageDocumentPdf):
|
|
185
|
+
self.__page = new.page
|
|
186
|
+
else:
|
|
187
|
+
raise ValueError(f'{__class__.__name__} Use: ABCPagePdf(), não {type(new)}')
|
|
188
|
+
self.page_number = self.__page.page_number
|
|
189
|
+
self.current_library = self.__page.current_library
|
|
190
|
+
|
|
191
|
+
def __eq__(self, value: ABCPagePdf):
|
|
192
|
+
return (self.to_string() == value.to_string()) and (self.page_number == value.page_number)
|
|
193
|
+
|
|
194
|
+
def __hash__(self) -> int:
|
|
195
|
+
h1 = hash(self.page_number)
|
|
196
|
+
h2 = hash(self.to_string())
|
|
197
|
+
return hash(f'{h1}_{h2}')
|
|
198
|
+
|
|
199
|
+
def to_string(self) -> str | None:
|
|
200
|
+
return self.page.to_string()
|
|
201
|
+
|
|
202
|
+
def to_list(self, separator:str='\n') -> List[str]:
|
|
203
|
+
return self.page.to_list(separator)
|
|
204
|
+
|
|
205
|
+
def to_table(self, separator:str='\n') -> TableText:
|
|
206
|
+
return self.page.to_table(separator)
|
|
207
|
+
|
|
208
|
+
def to_bytes(self) -> bytes:
|
|
209
|
+
return self.page.to_bytes()
|
|
210
|
+
|
|
211
|
+
def is_paisagem(self) -> bool:
|
|
212
|
+
return self.page.is_paisagem()
|
|
213
|
+
|
|
214
|
+
def set_paisagem(self):
|
|
215
|
+
self.page.set_paisagem()
|
|
216
|
+
|
|
217
|
+
def set_page_fitz(self):
|
|
218
|
+
if self.page.current_library == LibraryPDF.FITZ:
|
|
219
|
+
return
|
|
220
|
+
pg = FitzPagePdf.create_from_page_bytes(self.to_bytes())
|
|
221
|
+
self.page = pg
|
|
222
|
+
|
|
223
|
+
def set_page_pypdf2(self):
|
|
224
|
+
if self.page.current_library == LibraryPDF.PYPDF:
|
|
225
|
+
return
|
|
226
|
+
pg = PyPdf2PagePdf.create_from_page_bytes(self.to_bytes())
|
|
227
|
+
self.page = pg
|
|
228
|
+
|
|
229
|
+
def rotate(self, degrees: int):
|
|
230
|
+
self.page.rotate(degrees)
|
|
231
|
+
|
|
232
|
+
@classmethod
|
|
233
|
+
def create_from_page_bytes(cls, page_bytes:bytes, *, library:LibraryPDF=LibraryPDF.PYPDF) -> PageDocumentPdf:
|
|
234
|
+
if library == LibraryPDF.PYPDF:
|
|
235
|
+
pg = PyPdf2PagePdf.create_from_page_bytes(page_bytes)
|
|
236
|
+
elif library == LibraryPDF.FITZ:
|
|
237
|
+
pg = FitzPagePdf.create_from_page_bytes(page_bytes)
|
|
238
|
+
else:
|
|
239
|
+
raise ValueError("Biblioteca inválida: escolha 'fitz' ou 'pypdf2'.")
|
|
240
|
+
#
|
|
241
|
+
return cls(pg)
|
|
242
|
+
|
|
243
|
+
@classmethod
|
|
244
|
+
def create_from_page_pypdf2(cls, page:PageObject) -> None:
|
|
245
|
+
pg = PyPdf2PagePdf.create_from_page_pypdf2(page)
|
|
246
|
+
return cls(pg)
|
|
247
|
+
|
|
248
|
+
@classmethod
|
|
249
|
+
def create_from_page_fitz(cls, page) -> FitzPagePdf:
|
|
250
|
+
pg = FitzPagePdf.create_from_page_fitz(page)
|
|
251
|
+
return cls(pg)
|
convert_stream/text.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: convert_stream
|
|
3
|
+
Version: 1.1
|
|
4
|
+
Summary: Manipulação de documentos PDF e Imagens. Converter, Ler, rotacionar exportar etc.
|
|
5
|
+
Author: Bruno Chaves
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: soup_files==1.0.1
|
|
9
|
+
Requires-Dist: PyPDF2==3.0.1
|
|
10
|
+
Requires-Dist: PyMuPDF==1.25.5
|
|
11
|
+
Requires-Dist: reportlab==4.3.1
|
|
12
|
+
Requires-Dist: openpyxl==3.1.5
|
|
13
|
+
Requires-Dist: pandas==2.2.3
|
|
14
|
+
Requires-Dist: Pillow==11.2.1
|
|
15
|
+
Requires-Dist: opencv-python==4.11.0.86
|
|
16
|
+
Requires-Dist: requests==2.32.3
|
|
17
|
+
|
|
18
|
+
# Configuração instalação:
|
|
19
|
+
pip3 install -r requirements.txt
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Uso dividir páginas de um arquivo PDF:
|
|
23
|
+
>>> from file import File, Directory
|
|
24
|
+
>>> from pdflib import PdfStream
|
|
25
|
+
# instâncie o caminho do arquivo PDF e o diretório para exportar os dados.
|
|
26
|
+
f = File('path/to/file.pdf')
|
|
27
|
+
d = Directory('path/to/save')
|
|
28
|
+
|
|
29
|
+
pdf_stream = PdfStream()
|
|
30
|
+
pdf_stream.add_file_pdf(f)
|
|
31
|
+
pdf_stream.to_files_pdf(d) # isso irá converter cada página em um arquivo PDF
|
|
32
|
+
|
|
33
|
+
# Uso para unir vários arquivos PDF.
|
|
34
|
+
>>> from file import File, Directory
|
|
35
|
+
>>> from pdflib import PdfStream
|
|
36
|
+
# instâncie o caminho dos arquivos PDF que deseja unir.
|
|
37
|
+
f = File('path/to/file.pdf')
|
|
38
|
+
f2 = File('path/to/file2.pdf)
|
|
39
|
+
...
|
|
40
|
+
... # Adicione quantos arquivos desejar.
|
|
41
|
+
|
|
42
|
+
pdf_stream = PdfStream()
|
|
43
|
+
pdf_stream.add_file_pdf(f)
|
|
44
|
+
pdf_stream.add_file_pdf(f2)
|
|
45
|
+
pdf_stream.to_file_pdf(File('path/to/new_file.pdf'))
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
convert_stream/__init__.py,sha256=18yF0aKg1TurBEuN52X-m_-Kucvj4rCRUe4mBIc2dSY,605
|
|
2
|
+
convert_stream/__main__.py,sha256=P8AoCKLEwJDZz7RViIbUs2waHXVtblvvDSJgl9nh6u8,762
|
|
3
|
+
convert_stream/_version.py,sha256=_bhIn9J0WZrzFZygDF5NNOJC59lTtcupK9R0-atfshI,172
|
|
4
|
+
convert_stream/convert.py,sha256=fLpmdWf4j3jHMiYWWgO1nMXtTz4_id_m_8ZHpTvk6Ts,11258
|
|
5
|
+
convert_stream/imagelib.py,sha256=HtMndduCW92toRr2mEJWuj-fgdwfuwYk8D1O5UWvpc8,19644
|
|
6
|
+
convert_stream/library.py,sha256=x2Wnj6yGdXd0AOD_rALHW_lAk1XZ9-IACip3OuWiRNs,148
|
|
7
|
+
convert_stream/pdf_convert.py,sha256=3PGDJMlRneyd4MQFJWbInzqR83dIKHGWegQW8UmuyXE,11804
|
|
8
|
+
convert_stream/pdf_document.py,sha256=1_Pn8pFU9vHtdJ9cZaOU72BInm1JUzb4N48pF1xj4-M,18935
|
|
9
|
+
convert_stream/pdf_page.py,sha256=H9xjbhlz8EbeVT6XiRTkUC2RRc0foUvSsPt07Pmr6Ew,8666
|
|
10
|
+
convert_stream/text.py,sha256=apRYAV8POoJfQqosXO_6QxqCwJGG_UGKU0u1o-71o8s,169
|
|
11
|
+
convert_stream/models/__init__.py,sha256=gXVkNtXXUokv_u5h52mx2Io9DCDZCZRDwBocUlCJli8,392
|
|
12
|
+
convert_stream/models/m_imgelib.py,sha256=qMrcSkUBf3NYlkaJQR5-vb1ZDVGiLbLJap-14UpGUBU,2022
|
|
13
|
+
convert_stream/models/m_pdf_convert.py,sha256=W3eBW8sWXhABKsSwUtXHj3vOYXxpkE_yXy4TYVgXK0k,4533
|
|
14
|
+
convert_stream/models/m_pdf_document.py,sha256=r1W6MIpUmUgutLTIaaKkqiux6sBYogqXRfGeHbVPbjs,3027
|
|
15
|
+
convert_stream/models/m_pdf_page.py,sha256=Ghr1wTdrzxax-tlCawsxORUGy0M6WiGApIYsu_YosRk,1687
|
|
16
|
+
convert_stream/models/m_text.py,sha256=27pNjdmcj7XrE80Ha4zcuBrnE4F5Ue27uXESMYNw5Ms,15723
|
|
17
|
+
convert_stream-1.1.dist-info/METADATA,sha256=ReupXsW67Yhyvt9H7qVHwimHvoecUGAsPaM7lHjirT0,1453
|
|
18
|
+
convert_stream-1.1.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
|
19
|
+
convert_stream-1.1.dist-info/top_level.txt,sha256=km2_p00LQvaGe1uG4rF7lFnoLiU4pBfSrsa-2JomPDk,15
|
|
20
|
+
convert_stream-1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
convert_stream
|