convert-stream 2.4.4__tar.gz → 2.5__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.
Files changed (31) hide show
  1. {convert_stream-2.4.4 → convert_stream-2.5}/PKG-INFO +3 -3
  2. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/__init__.py +10 -15
  3. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/_version.py +2 -2
  4. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/doc_stream.py +19 -22
  5. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/image/img_object.py +26 -15
  6. convert_stream-2.5/convert_stream/mod_types/__init__.py +11 -0
  7. convert_stream-2.5/convert_stream/mod_types/enums.py +37 -0
  8. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/mod_types/modules.py +6 -6
  9. convert_stream-2.5/convert_stream/pdf/__init__.py +12 -0
  10. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/pdf/pdf_document.py +14 -13
  11. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/pdf/pdf_page.py +12 -9
  12. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/table_files.py +1 -2
  13. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/text/__init__.py +1 -0
  14. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream.egg-info/PKG-INFO +3 -3
  15. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream.egg-info/SOURCES.txt +0 -3
  16. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream.egg-info/requires.txt +2 -2
  17. {convert_stream-2.4.4 → convert_stream-2.5}/pyproject.toml +3 -3
  18. convert_stream-2.4.4/convert_stream/mod_types/__init__.py +0 -13
  19. convert_stream-2.4.4/convert_stream/mod_types/enums.py +0 -65
  20. convert_stream-2.4.4/convert_stream/mod_types/table_types.py +0 -19
  21. convert_stream-2.4.4/convert_stream/pdf/__init__.py +0 -14
  22. convert_stream-2.4.4/convert_stream/pdf/image_to_pdf.py +0 -349
  23. convert_stream-2.4.4/convert_stream/pdf/pdf_to_image.py +0 -223
  24. {convert_stream-2.4.4 → convert_stream-2.5}/README.md +0 -0
  25. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/__main__.py +0 -0
  26. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/image/__init__.py +0 -0
  27. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/text/find_text.py +0 -0
  28. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream/text/terminal.py +0 -0
  29. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream.egg-info/dependency_links.txt +0 -0
  30. {convert_stream-2.4.4 → convert_stream-2.5}/convert_stream.egg-info/top_level.txt +0 -0
  31. {convert_stream-2.4.4 → convert_stream-2.5}/setup.cfg +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: convert_stream
3
- Version: 2.4.4
3
+ Version: 2.5
4
4
  Summary: Manipulação de documentos PDF e Imagens. Converter, Ler, rotacionar exportar etc.
5
5
  Author: Bruno Chaves
6
6
  Requires-Python: >=3.11
7
7
  Description-Content-Type: text/markdown
8
- Requires-Dist: soup_files>=1.4
8
+ Requires-Dist: soup_files>=1.4.2
9
9
  Requires-Dist: PyMuPDF
10
10
  Requires-Dist: scipy
11
11
  Requires-Dist: reportlab
@@ -15,7 +15,7 @@ Requires-Dist: pandas
15
15
  Requires-Dist: Pillow>=11.3.0
16
16
  Requires-Dist: opencv-python
17
17
  Requires-Dist: requests>=2.32.4
18
- Requires-Dist: sheet_stream
18
+ Requires-Dist: sheet_stream>=0.1.3
19
19
 
20
20
  # Configuração instalação:
21
21
  pip3 install -r requirements.txt
@@ -8,11 +8,17 @@ from ._version import (
8
8
  __module_name__, __author__, __license__, __modify_date__, __version__
9
9
  )
10
10
  from .mod_types import (
11
- LibPDF, LibImage, LibPdfToImage, LibImageToPdf, DictTextTable, RotationAngle,
11
+ LibPDF, LibImage, LibPdfToImage, LibImageToPdf, RotationAngle,
12
12
  )
13
- from .image import ImageObject, CollectionImages
14
- from .pdf import DocumentPdf, PageDocumentPdf, CollectionPagePdf, ConvertPdfToImages, ConvertImageToPdf
15
- from .pdf.pdf_document import SearchableTextPdf
13
+ from .image import ImageObject, CollectionImages, ProcessImageScanner
14
+ from .pdf import (
15
+ DocumentPdf, PageDocumentPdf, CollectionPagePdf, SearchableTextPdf
16
+ )
17
+ from .convert import (
18
+ ConvertPdfToImages, ConvertImageToPdf, ABCConvertPdf, ABCConvertImageToPdf,
19
+ DEFAULT_LIB_PDF_TO_IMG, DEFAULT_LIB_IMAGE_TO_PDF, LibPdfToImage, LibImageToPdf,
20
+ )
21
+
16
22
  from .doc_stream import PdfStream, SplitPdf
17
23
  from .table_files import PdfFinder
18
24
  from .text import print_title, print_line, FindStrings
@@ -71,14 +77,3 @@ def read_image(img: Union[str, File, bytes, BytesIO]) -> PdfStream:
71
77
  raise ValueError()
72
78
  return _pdf_stream
73
79
 
74
-
75
- __all__ = [
76
- '__modify_date__', '__author__', '__license__', '__module_name__', '__version__',
77
- 'PdfStream', 'DocumentPdf', 'PageDocumentPdf', 'CollectionPagePdf', 'CollectionImages',
78
- 'ImageObject', 'File', 'Directory', 'LibraryDocs', 'InputFiles', 'SearchableTextPdf',
79
- 'PdfFinder', 'SplitPdf', 'LibImageToPdf', 'RotationAngle', 'ConvertImageToPdf',
80
- 'ConvertPdfToImages', 'LibPDF', 'LibImage', 'LibPdfToImage',
81
- 'read_pdf', 'read_files_pdf', 'read_image', 'DictTextTable',
82
- 'print_title', 'print_line', 'FindStrings',
83
- ]
84
-
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
- __version__ = '2.2.7'
4
+ __version__ = '2.5'
5
5
  __author__ = 'Bruno Chaves'
6
6
  __license__ = 'MIT'
7
7
  __module_name__ = 'convert_stream'
8
- __modify_date__ = '2025-09-08'
8
+ __modify_date__ = '2025-11-15'
9
9
 
@@ -4,21 +4,18 @@
4
4
  Módulo para trabalhar com pdfs e imagens
5
5
  """
6
6
  from __future__ import annotations
7
- from convert_stream.mod_types.modules import (
8
- DEFAULT_LIB_PDF, DEFAULT_LIB_IMAGE, DEFAULT_LIB_PDF_TO_IMG, DEFAULT_LIB_IMAGE_TO_PDF,
9
- )
10
7
  from convert_stream.mod_types.enums import LibPDF, LibImage, LibPdfToImage
11
8
  from convert_stream.pdf.pdf_page import PageDocumentPdf
12
9
  from convert_stream.image.img_object import ImageObject, CollectionImages
13
10
  from convert_stream.pdf.pdf_document import DocumentPdf, CollectionPagePdf
14
- from convert_stream.pdf.image_to_pdf import LibImageToPdf, ConvertImageToPdf
15
- from convert_stream.pdf.pdf_to_image import ConvertPdfToImages
11
+ from convert_stream.convert.image_to_pdf import LibImageToPdf, ConvertImageToPdf
12
+ from convert_stream.convert.pdf_to_image import ConvertPdfToImages
16
13
  from soup_files import File, Directory, ProgressBarAdapter
17
14
 
18
15
 
19
16
  class ImageStream(CollectionImages):
20
17
 
21
- def __init__(self, images: list[ImageObject]) -> None:
18
+ def __init__(self, images: list[ImageObject] = None) -> None:
22
19
  super().__init__(images)
23
20
 
24
21
  def add_image_bytes(self, bt: bytes) -> None:
@@ -39,7 +36,7 @@ class PdfStream(object):
39
36
  ) -> None:
40
37
  self.dpi = dpi
41
38
  self.progress: ProgressBarAdapter = pbar
42
- self.collection_pages: CollectionPagePdf = CollectionPagePdf([])
39
+ self.collection_pages: CollectionPagePdf = CollectionPagePdf()
43
40
  self.collection_images: CollectionImages = CollectionImages([], lib_img=lib_img)
44
41
  self.collection_images.set_pbar(self.progress)
45
42
  self.collection_pages.set_pbar(self.progress)
@@ -132,25 +129,25 @@ class PdfStream(object):
132
129
  return _doc
133
130
 
134
131
  def thresold(self, *, land_scape: bool = False, a4: bool = False) -> DocumentPdf:
135
- if self.collection_images.length == 0:
136
- images: list[ImageObject] = []
137
- else:
138
- images: list[ImageObject] = self.collection_images.copy()
139
132
 
140
133
  if not self.collection_pages.is_empty:
141
134
  # Converter as páginas PDF em imagens.
142
135
  conv_pdf_to_img: ConvertPdfToImages = self.convert_pdf_to_images
143
- images.extend(
144
- conv_pdf_to_img.to_images(dpi=self.dpi, lib_image=self.lib_img),
145
- )
146
- if len(images) == 0:
136
+ _images: list[ImageObject] = conv_pdf_to_img.to_images(dpi=self.dpi, lib_image=self.lib_img)
137
+ _collection = CollectionImages(_images)
138
+ else:
139
+ _collection = CollectionImages()
140
+
141
+ if self.collection_images.length > 0:
142
+ _collection.add_images(self.collection_images)
143
+ if _collection.length == 0:
147
144
  raise ValueError('Adicione imagens para prosseguir!')
148
- if land_scape:
149
- for img in images:
150
- img.set_landscape()
151
- for i in images:
152
- i.set_threshold_gray()
153
- conv_img_to_pdf = ConvertImageToPdf(CollectionImages(images), lib_img_to_pdf=self.lib_img_to_pdf)
145
+
146
+ for num, i in enumerate(_collection):
147
+ if land_scape:
148
+ _collection[num].set_landscape()
149
+ _collection[num].set_threshold_black(max_value=255)
150
+ conv_img_to_pdf = ConvertImageToPdf(_collection, lib_img_to_pdf=self.lib_img_to_pdf)
154
151
  return conv_img_to_pdf.to_document(a4=a4)
155
152
 
156
153
  def to_files_images(
@@ -163,7 +160,7 @@ class PdfStream(object):
163
160
  raise ValueError('Adicione imagens e/ou documentos para prosseguir!')
164
161
  self.progress.start()
165
162
 
166
- image_stream = ImageStream([])
163
+ image_stream = ImageStream()
167
164
  image_stream.set_pbar(self.progress)
168
165
  if not self.collection_images.is_empty:
169
166
  image_stream.add_images(self.collection_images)
@@ -4,17 +4,16 @@
4
4
  Módulo para trabalhar com imagens
5
5
  """
6
6
  from __future__ import annotations
7
-
8
7
  import os.path
9
8
  from typing import Union
10
9
  from abc import ABC, abstractmethod
11
- from soup_files import File, Directory, InputFiles, LibraryDocs, ProgressBarAdapter
10
+ from soup_files import File, Directory, InputFiles, LibraryDocs, ProgressBarAdapter, TextProgress
12
11
  from io import BytesIO
13
12
  import numpy as np
14
13
  from scipy.ndimage import uniform_filter
15
14
  from sheet_stream.type_utils import get_hash_from_bytes, MetaDataFile, MetaDataItem
16
- from convert_stream.mod_types.enums import LibImage, RotationAngle
17
- from convert_stream.mod_types.table_types import ListItems
15
+ from convert_stream.mod_types.enums import RotationAngle
16
+ from sheet_stream import ListItems
18
17
  from convert_stream.mod_types.modules import (
19
18
  MOD_IMG_PIL, ModuleImage, DEFAULT_LIB_IMAGE,
20
19
  cv2, MatLike, Image, ImageFilter, LibImage
@@ -500,16 +499,28 @@ class ImageObject(object):
500
499
 
501
500
  class CollectionImages(ListItems):
502
501
 
503
- def __init__(self, images: list[ImageObject], *, lib_img: LibImage = LibImage.OPENCV) -> None:
502
+ def __init__(self, images: list[ImageObject] = None, *, lib_img: LibImage = LibImage.OPENCV) -> None:
504
503
  """
505
504
  Gerir uma lista de Imagens
506
505
  :type images: list[ImageObject]
507
506
  """
508
507
  super().__init__(images)
509
508
  self.lib_img: LibImage = lib_img
510
- self.pbar: ProgressBarAdapter = ProgressBarAdapter()
509
+ self.__pbar: TextProgress = TextProgress()
510
+ self.set_list_type(ImageObject)
511
511
  self.__count: int = 0
512
512
 
513
+ @property
514
+ def pbar(self) -> ProgressBarAdapter:
515
+ return self.__pbar.pbar
516
+
517
+ @pbar.setter
518
+ def pbar(self, pbar: ProgressBarAdapter) -> None:
519
+ self.__pbar.pbar = pbar
520
+
521
+ def set_list_type(self, cls_type=object):
522
+ super().set_list_type(ImageObject)
523
+
513
524
  def clear(self) -> None:
514
525
  super().clear()
515
526
  self.__count = 0
@@ -533,12 +544,12 @@ class CollectionImages(ListItems):
533
544
 
534
545
  def add_files_image(self, files: list[File]) -> None:
535
546
  self.pbar.start()
536
- max_num: int = len(files)
547
+ self.__pbar.total = len(files)
548
+ self.__pbar.start = 0
549
+ self.__pbar.text = 'Adicionando imagem'
550
+
537
551
  for num, f in enumerate(files):
538
- self.pbar.update(
539
- ((num+1) / max_num) * 100,
540
- f'Adicionando imagem: [{num+1} de {max_num}]'
541
- )
552
+ self.__pbar.set_update()
542
553
  self.append(ImageObject.create_from_file(f, lib_image=self.lib_img))
543
554
  self.pbar.stop()
544
555
 
@@ -559,7 +570,7 @@ class CollectionImages(ListItems):
559
570
  max_num = self.length
560
571
  img: ImageObject
561
572
  for n, img in enumerate(self):
562
- if img.metadata.file_path is not None:
573
+ if (img.metadata.file_path is not None) and (img.metadata.file_path != ''):
563
574
  filename = f'{os.path.basename(img.metadata.file_path)}-{n}.png'
564
575
  else:
565
576
  filename = f'{img.metadata.name}-{n}.png'
@@ -611,9 +622,9 @@ class ProcessImageScanner(object):
611
622
 
612
623
  def select_doc(self) -> ImageObject | None:
613
624
  """
614
- Detecta e recorta automaticamente a área do documento principal
615
- (texto ou folha digitalizada) em uma imagem.
616
- Retorna um novo ImageObject contendo apenas o recorte detectado.
625
+ Deteta e recorta automaticamente a área do documento principal
626
+ (texto ou folha digitalizada) em imagem.
627
+ Retorna um novo ImageObject contendo apenas o recorte detetado.
617
628
  """
618
629
  # Converte para matriz OpenCV
619
630
  img_cv: np.ndarray = cv2.imdecode(self.image.to_numpy(), cv2.IMREAD_COLOR)
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from __future__ import annotations
4
+ from .enums import (
5
+ RotationAngle, LibImage, LibPdfToImage, LibPDF, LibImageToPdf
6
+ )
7
+
8
+ __all__ = [
9
+ 'RotationAngle', 'LibPDF',
10
+ 'LibImageToPdf', 'LibPdfToImage', 'LibImage',
11
+ ]
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python3
2
+ from enum import Enum
3
+
4
+
5
+ class LibPdfToImage(Enum):
6
+ """Enumerar as bibliotecas externas que convertem PDF em imagem"""
7
+ PDF_TO_IMG_FITZ = 'fitz'
8
+ NOT_IMPLEMENTED = 'null'
9
+
10
+
11
+ class LibImageToPdf(Enum):
12
+
13
+ IMAGE_TO_PDF_FITZ = 'fitz'
14
+ IMAGE_TO_PDF_CANVAS = 'canvas'
15
+ IMAGE_TO_PDF_PIL = 'pil'
16
+ NOT_IMPLEMENTED = 'null'
17
+
18
+
19
+ class LibPDF(Enum):
20
+
21
+ PYPDF = 'pypdf'
22
+ FITZ = 'fitz'
23
+ NOT_IMPLEMENTED = 'null'
24
+
25
+
26
+ class LibImage(Enum):
27
+
28
+ PIL = 'pil'
29
+ OPENCV = 'opencv'
30
+ NOT_IMPLEMENTED = 'null'
31
+
32
+
33
+ class RotationAngle(Enum):
34
+
35
+ ROTATION_90 = 90
36
+ ROTATION_180 = 180
37
+ ROTATION_270 = 270
@@ -29,15 +29,15 @@ try:
29
29
  from cv2.typing import MatLike
30
30
  MOD_IMG_OPENCV = True
31
31
  except ImportError:
32
- MatLike = FakeType
32
+ MatLike = object
33
33
 
34
34
  try:
35
35
  from PIL import Image
36
36
  from PIL import ImageOps, ImageFilter
37
37
  MOD_IMG_PIL = True
38
38
  except ImportError:
39
- Image = FakeType
40
- Image.Image = FakeType
39
+ Image = object
40
+ Image.Image = object
41
41
 
42
42
  if MOD_IMG_OPENCV and MOD_IMG_PIL:
43
43
  ModuleImage: TypeAlias = Union[MatLike, Image.Image]
@@ -50,7 +50,7 @@ elif MOD_IMG_PIL:
50
50
  DEFAULT_LIB_IMAGE = LibImage.PIL
51
51
  else:
52
52
  DEFAULT_LIB_IMAGE = LibImage.NOT_IMPLEMENTED
53
- ModuleImage = FakeType
53
+ ModuleImage: TypeAlias = Union[MatLike, Image]
54
54
 
55
55
  #=================================================================#
56
56
  # Módulos para PDF fitz e pypdf
@@ -90,8 +90,8 @@ elif MOD_PYPDF:
90
90
  ModDocPdf = Union[PdfWriter]
91
91
  DEFAULT_LIB_PDF = LibPDF.PYPDF
92
92
  else:
93
- ModPagePdf = FakeType # fallback para runtime
94
- ModDocPdf = FakeType
93
+ ModPagePdf = Union[PageObject, fitz.Page]
94
+ ModDocPdf = Union[fitz.Document, PdfWriter]
95
95
  DEFAULT_LIB_PDF = LibPDF.NOT_IMPLEMENTED
96
96
 
97
97
  #=================================================================#
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env python3
2
+ from .pdf_page import PageDocumentPdf
3
+ from .pdf_document import (
4
+ DocumentPdf, CollectionPagePdf, SearchableTextPdf, ABCDocument,
5
+ MOD_FITZ, MOD_PYPDF, ModDocPdf,
6
+ )
7
+
8
+ __all__ = [
9
+ 'DocumentPdf', 'CollectionPagePdf', 'PageDocumentPdf',
10
+ 'SearchableTextPdf', 'ModDocPdf', 'ABCDocument', 'MOD_PYPDF', 'MOD_FITZ',
11
+ ]
12
+
@@ -9,14 +9,10 @@ from io import BytesIO
9
9
  from typing import Union
10
10
  import pandas as pd
11
11
  from soup_files import File, Directory, LibraryDocs, InputFiles, ProgressBarAdapter, JsonConvert
12
- from sheet_stream.type_utils import (
13
- get_hash_from_bytes, MetaDataFile, MetaDataItem
12
+ from sheet_stream import (
13
+ ListItems, HeadCell, HeadValues, ColumnsTable, TableDocuments, ListColumnBody, ListString,
14
+ MetaDataItem, MetaDataFile, get_hash_from_bytes,
14
15
  )
15
-
16
- from sheet_stream.type_utils import (
17
- ListItems, HeadCell, HeadValues, ColumnsTable, TableDocuments, ListColumnBody, ListString
18
- )
19
- from convert_stream.mod_types.table_types import DictTextTable, ColumnBody
20
16
  from convert_stream.mod_types.enums import LibPDF
21
17
  from convert_stream.mod_types.modules import (
22
18
  DEFAULT_LIB_PDF, ModDocPdf, PdfWriter, PdfReader, fitz, MOD_FITZ, MOD_PYPDF
@@ -70,7 +66,7 @@ class SearchableTextPdf(object):
70
66
  """
71
67
  def __init__(self, silent: bool = False):
72
68
  self.silent = silent
73
- self.elements: dict[str, ColumnBody] = DictTextTable.create_void_dict()
69
+ self.elements: TableDocuments = TableDocuments.create_void_dict()
74
70
 
75
71
  def __repr__(self):
76
72
  return f'SearchableTextPdf: {self.elements}'
@@ -221,9 +217,9 @@ class ImplementDocumentFitz(ABCDocument):
221
217
  """
222
218
  Implementação usando a biblioteca fitz.
223
219
  """
224
- def __init__(self, mod_doc_pdf: ModDocPdf):
220
+ def __init__(self, mod_doc_pdf: fitz.Document):
225
221
  super().__init__(mod_doc_pdf)
226
- self.mod_doc_pdf: ModDocPdf = mod_doc_pdf
222
+ self.mod_doc_pdf: fitz.Document = mod_doc_pdf
227
223
  self.lib_pdf: LibPDF = LibPDF.FITZ
228
224
 
229
225
  def lenght(self) -> int:
@@ -592,11 +588,12 @@ class DocumentPdf(object):
592
588
  list_data: list[TableDocuments] = []
593
589
  pages: list[PageDocumentPdf] = self.to_pages()
594
590
 
591
+ _mp: TableDocuments
595
592
  for page_pdf in pages:
596
- _mp: TableDocuments = self._create_map(page_pdf, separator=separator)
593
+ _mp = self._create_map(page_pdf, separator=separator)
597
594
  list_data.append(_mp)
598
595
  if len(list_data) == 0:
599
- return DictTextTable.create_void_dict()
596
+ return TableDocuments.create_void_dict()
600
597
  return concat_table(list_data)
601
598
 
602
599
  def to_data(self, separator: str = '\n') -> pd.DataFrame:
@@ -712,9 +709,10 @@ class CollectionPagePdf(ListItems):
712
709
  """
713
710
  Gerir uma coleção de páginas PDF.
714
711
  """
715
- def __init__(self, pages: list[PageDocumentPdf]) -> None:
712
+ def __init__(self, pages: list[PageDocumentPdf] = None) -> None:
716
713
  super().__init__(pages)
717
714
  self.pbar: ProgressBarAdapter = ProgressBarAdapter()
715
+ self.set_list_type(PageDocumentPdf)
718
716
 
719
717
  @property
720
718
  def name(self) -> str | None:
@@ -722,6 +720,9 @@ class CollectionPagePdf(ListItems):
722
720
  return None
723
721
  return self[0].__hash__()
724
722
 
723
+ def set_list_type(self, cls_type=PageDocumentPdf):
724
+ super().set_list_type(PageDocumentPdf)
725
+
725
726
  def set_pbar(self, p: ProgressBarAdapter):
726
727
  self.pbar = p
727
728
 
@@ -6,11 +6,8 @@
6
6
  from __future__ import annotations
7
7
  from abc import ABC, abstractmethod
8
8
  import pandas as pd
9
-
9
+ from sheet_stream import ListString, TableDocuments
10
10
  from convert_stream.mod_types.enums import LibPDF
11
- from convert_stream.mod_types.table_types import (
12
- DictTextTable, ListString
13
- )
14
11
  from convert_stream.mod_types.modules import (
15
12
  ModPagePdf, PageObject, fitz
16
13
  )
@@ -230,10 +227,16 @@ class PageDocumentPdf(object):
230
227
  return ListString([])
231
228
  return ListString(txt.split(separator))
232
229
 
233
- def to_dict(self, separator: str = '\n') -> DictTextTable:
230
+ def to_dict(self, separator: str = '\n') -> TableDocuments:
231
+ """
232
+ Converte o texto da página em tabela/dicionário
233
+ """
234
234
  _values = self.to_list(separator)
235
- return DictTextTable.create_from_values(
236
- _values, page_num=f'{self.number_page}', file_type='.pdf'
235
+ return TableDocuments.create_from_values(
236
+ _values,
237
+ page_num=f'{self.number_page}',
238
+ file_type='.pdf',
239
+ file_path=self.metadata.file_path
237
240
  )
238
241
 
239
242
  def to_map(self, separator: str = '\n') -> pd.DataFrame:
@@ -246,9 +249,9 @@ class PageDocumentPdf(object):
246
249
  fd = FindText(self.to_string(), separator=separator)
247
250
  return fd.find(text, iqual=iqual, case=case)
248
251
 
249
- def find_all(self, text: str, *, separator: str = '\n', iqual: bool = False, case: bool = True) -> list[str]:
252
+ def find_all(self, text: str, *, separator: str = '\n', iqual: bool = False, case: bool = True) -> ListString:
250
253
  fd = FindText(self.to_string(), separator=separator)
251
- return fd.find_all(text, iqual=iqual, case=case)
254
+ return ListString(fd.find_all(text, iqual=iqual, case=case))
252
255
 
253
256
  def get_width(self) -> float:
254
257
  return self.implement_page_pdf.get_width()
@@ -3,12 +3,11 @@
3
3
  from __future__ import annotations
4
4
  from io import BytesIO
5
5
  from soup_files import File, Directory, InputFiles, LibraryDocs
6
-
7
6
  from convert_stream import PageDocumentPdf
8
7
  from convert_stream.text.find_text import FindText
9
8
  from convert_stream.pdf.pdf_document import SearchableTextPdf, DocumentPdf
10
- from convert_stream.mod_types.table_types import ColumnsTable
11
9
  from convert_stream.image import ImageObject
10
+ from sheet_stream import ColumnsTable, TableDocuments
12
11
 
13
12
 
14
13
  class PdfFinder(object):
@@ -8,4 +8,5 @@ from sheet_stream import ConvertStringDate, fmt_col_to_date
8
8
  __all__ = [
9
9
  'ConvertStringDate', 'print_title', 'print_line', 'fmt_col_to_date',
10
10
  'show_info', 'Colors', 'show_error', 'show_warning', 'FindText',
11
+ 'FindStrings',
11
12
  ]
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: convert_stream
3
- Version: 2.4.4
3
+ Version: 2.5
4
4
  Summary: Manipulação de documentos PDF e Imagens. Converter, Ler, rotacionar exportar etc.
5
5
  Author: Bruno Chaves
6
6
  Requires-Python: >=3.11
7
7
  Description-Content-Type: text/markdown
8
- Requires-Dist: soup_files>=1.4
8
+ Requires-Dist: soup_files>=1.4.2
9
9
  Requires-Dist: PyMuPDF
10
10
  Requires-Dist: scipy
11
11
  Requires-Dist: reportlab
@@ -15,7 +15,7 @@ Requires-Dist: pandas
15
15
  Requires-Dist: Pillow>=11.3.0
16
16
  Requires-Dist: opencv-python
17
17
  Requires-Dist: requests>=2.32.4
18
- Requires-Dist: sheet_stream
18
+ Requires-Dist: sheet_stream>=0.1.3
19
19
 
20
20
  # Configuração instalação:
21
21
  pip3 install -r requirements.txt
@@ -15,12 +15,9 @@ convert_stream/image/img_object.py
15
15
  convert_stream/mod_types/__init__.py
16
16
  convert_stream/mod_types/enums.py
17
17
  convert_stream/mod_types/modules.py
18
- convert_stream/mod_types/table_types.py
19
18
  convert_stream/pdf/__init__.py
20
- convert_stream/pdf/image_to_pdf.py
21
19
  convert_stream/pdf/pdf_document.py
22
20
  convert_stream/pdf/pdf_page.py
23
- convert_stream/pdf/pdf_to_image.py
24
21
  convert_stream/text/__init__.py
25
22
  convert_stream/text/find_text.py
26
23
  convert_stream/text/terminal.py
@@ -1,4 +1,4 @@
1
- soup_files>=1.4
1
+ soup_files>=1.4.2
2
2
  PyMuPDF
3
3
  scipy
4
4
  reportlab
@@ -8,4 +8,4 @@ pandas
8
8
  Pillow>=11.3.0
9
9
  opencv-python
10
10
  requests>=2.32.4
11
- sheet_stream
11
+ sheet_stream>=0.1.3
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "convert_stream"
7
- version = "2.4.4"
7
+ version = "2.5"
8
8
  authors = [
9
9
  { name="Bruno Chaves"},
10
10
  ]
@@ -14,7 +14,7 @@ readme = "README.md"
14
14
  requires-python = ">=3.11"
15
15
 
16
16
  dependencies = [
17
- "soup_files>=1.4",
17
+ "soup_files>=1.4.2",
18
18
  "PyMuPDF",
19
19
  "scipy",
20
20
  "reportlab",
@@ -24,7 +24,7 @@ dependencies = [
24
24
  "Pillow>=11.3.0",
25
25
  "opencv-python",
26
26
  "requests>=2.32.4",
27
- "sheet_stream",
27
+ "sheet_stream>=0.1.3",
28
28
  ]
29
29
 
30
30
  [tool.setuptools]
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env python3
2
- #
3
- from __future__ import annotations
4
- from .enums import (
5
- RotationAngle, ColumnsTable, LibImage, LibPdfToImage, LibPDF, LibImageToPdf
6
- )
7
- from .table_types import DictTextTable
8
-
9
-
10
- __all__ = [
11
- 'DictTextTable', 'RotationAngle', 'LibPDF',
12
- 'LibImageToPdf', 'LibPdfToImage', 'LibImage',
13
- ]
@@ -1,65 +0,0 @@
1
- #!/usr/bin/env python3
2
- from enum import Enum
3
-
4
-
5
- class ColumnsTable(Enum):
6
- """
7
- Classe enum para padronizar os nomes das tabelas geradas por este módulo.
8
- """
9
-
10
- NUM_LINE = 'LINHA'
11
- NUM_PAGE = 'PÁGINA'
12
- TEXT = 'TEXTO'
13
- FILE_PATH = 'ARQUIVO'
14
- FILE_NAME = 'NOME_ARQUIVO'
15
- DIR = 'PASTA'
16
- FILETYPE = 'TIPO_ARQUIVO'
17
- KEY = 'KEY'
18
-
19
- @classmethod
20
- def to_list(cls) -> list[str]:
21
- return [
22
- cls.NUM_LINE.value,
23
- cls.NUM_PAGE.value,
24
- cls.TEXT.value,
25
- cls.FILE_PATH.value,
26
- cls.FILE_NAME.value,
27
- cls.FILETYPE.value,
28
- cls.DIR.value,
29
- cls.KEY.value,
30
- ]
31
-
32
-
33
- class LibPdfToImage(Enum):
34
- """Enumerar as bibliotecas externas que convertem PDF em imagem"""
35
- PDF_TO_IMG_FITZ = 'fitz'
36
- NOT_IMPLEMENTED = 'null'
37
-
38
-
39
- class LibImageToPdf(Enum):
40
-
41
- IMAGE_TO_PDF_FITZ = 'fitz'
42
- IMAGE_TO_PDF_CANVAS = 'canvas'
43
- IMAGE_TO_PDF_PIL = 'pil'
44
- NOT_IMPLEMENTED = 'null'
45
-
46
-
47
- class LibPDF(Enum):
48
-
49
- PYPDF = 'pypdf'
50
- FITZ = 'fitz'
51
- NOT_IMPLEMENTED = 'null'
52
-
53
-
54
- class LibImage(Enum):
55
-
56
- PIL = 'pil'
57
- OPENCV = 'opencv'
58
- NOT_IMPLEMENTED = 'null'
59
-
60
-
61
- class RotationAngle(Enum):
62
-
63
- ROTATION_90 = 90
64
- ROTATION_180 = 180
65
- ROTATION_270 = 270
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- from __future__ import annotations
4
- from sheet_stream import (
5
- ColumnsTable, ListString, ListItems, ListColumnBody, ArrayString, TableDocuments, TableRow, TableTextKeyWord
6
- )
7
- from sheet_stream.type_utils import HeadCell
8
-
9
-
10
- class ColumnBody(ListColumnBody):
11
-
12
- def __init__(self, col_name: HeadCell | str, col_body: list[str]):
13
- super().__init__(col_name, col_body)
14
-
15
-
16
- class DictTextTable(TableDocuments):
17
-
18
- def __init__(self, body_list: list[ListColumnBody]):
19
- super().__init__(body_list)
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- from .pdf_page import PageDocumentPdf
4
- from .pdf_document import (
5
- DocumentPdf, CollectionPagePdf
6
- )
7
- from .pdf_to_image import ConvertPdfToImages
8
- from .image_to_pdf import ConvertImageToPdf
9
-
10
- __all__ = [
11
- 'ConvertPdfToImages', 'ConvertImageToPdf', 'DocumentPdf',
12
- 'CollectionPagePdf', 'PageDocumentPdf',
13
- ]
14
-
@@ -1,349 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- Módulo para trabalhar com imagens
5
- """
6
-
7
- from __future__ import annotations
8
- from io import BytesIO
9
- from soup_files import File, Directory, ProgressBarAdapter
10
- from abc import ABC, abstractmethod
11
- from convert_stream.mod_types.enums import LibImageToPdf
12
- from convert_stream.mod_types.modules import (
13
- MOD_CANVAS, DEFAULT_LIB_IMAGE_TO_PDF, canvas, letter, ImageReader
14
- )
15
- from convert_stream.pdf import DocumentPdf
16
- from convert_stream.pdf.pdf_page import fitz
17
- from convert_stream.image.img_object import MOD_IMG_PIL, Image, ImageObject, CollectionImages
18
-
19
-
20
- class ABCConvertImageToPdf(ABC):
21
-
22
- def __init__(self, collection_images: CollectionImages):
23
- self.collection_images: CollectionImages = collection_images
24
- self.pbar: ProgressBarAdapter = ProgressBarAdapter()
25
-
26
- @abstractmethod
27
- def set_pbar(self, p: ProgressBarAdapter):
28
- pass
29
-
30
- @abstractmethod
31
- def to_document(self, land_scape: bool = True, a4: bool = False) -> DocumentPdf:
32
- pass
33
-
34
- @abstractmethod
35
- def to_file_pdf(self, output_file: File, *, land_scape: bool = True, a4: bool = False) -> None:
36
- pass
37
-
38
-
39
- class ImplementImageToPdfCanvas(ABCConvertImageToPdf):
40
-
41
- def __init__(self, collection_images: CollectionImages):
42
- super().__init__(collection_images)
43
-
44
- def set_pbar(self, p: ProgressBarAdapter):
45
- self.pbar = p
46
- self.collection_images.set_pbar(p)
47
-
48
- def to_document(self, land_scape: bool = True, a4: bool = False) -> DocumentPdf:
49
- if not MOD_CANVAS:
50
- raise RuntimeError("A biblioteca 'reportlab' não está disponível.")
51
-
52
- if self.collection_images.is_empty:
53
- raise ValueError("A lista de imagens não pode estar vazia.")
54
-
55
- buffer = BytesIO()
56
- max_num: int = self.collection_images.length
57
- self.pbar.start()
58
- if land_scape:
59
- self.collection_images.set_land_scape()
60
-
61
- # Lógica para determinar o tamanho inicial da página
62
- first_img_obj = self.collection_images[0]
63
- first_img_width, first_img_height = first_img_obj.get_dimensions()
64
-
65
- if a4:
66
- # Se for A4, o tamanho da página é fixo desde o início
67
- c = canvas.Canvas(buffer, pagesize=letter)
68
- else:
69
- # Se não for A4, o canvas é inicializado com as dimensões da primeira imagem
70
- c = canvas.Canvas(buffer, pagesize=(first_img_width, first_img_height))
71
-
72
- # Processa a primeira imagem
73
- self.pbar.update(
74
- (1 / max_num) * 100,
75
- f'Adicionando imagem ao Documento [1 de {max_num}]'
76
- )
77
- img_bytes: BytesIO = first_img_obj.to_bytes()
78
- img_bytes.seek(0)
79
- img_reader = ImageReader(img_bytes)
80
-
81
- if a4:
82
- # Lógica de redimensionamento e centralização para A4
83
- page_width, page_height = letter
84
- scale_factor = min(page_width / first_img_width, page_height / first_img_height)
85
- scaled_width = first_img_width * scale_factor
86
- scaled_height = first_img_height * scale_factor
87
- x_pos = (page_width - scaled_width) / 2
88
- y_pos = (page_height - scaled_height) / 2
89
- c.drawImage(img_reader, x_pos, y_pos, width=scaled_width, height=scaled_height)
90
- else:
91
- # Desenha a imagem preenchendo a página que já tem o tamanho correto
92
- c.drawImage(img_reader, 0, 0, width=first_img_width, height=first_img_height)
93
-
94
- # Processa as imagens restantes
95
- for num, img_obj in enumerate(self.collection_images[1:], 1):
96
-
97
- self.pbar.update(
98
- ((num + 1) / max_num) * 100,
99
- f'Adicionando imagem ao Documento [{num + 1} de {max_num}]'
100
- )
101
- img_bytes = img_obj.to_bytes()
102
- img_bytes.seek(0)
103
- img_reader = ImageReader(img_bytes)
104
- img_width, img_height = img_obj.get_dimensions()
105
- # Cria nova página
106
- c.showPage()
107
-
108
- if a4:
109
- # O tamanho da página é fixo, apenas desenha a imagem centralizada e redimensionada
110
- page_width, page_height = letter
111
- scale_factor = min(page_width / img_width, page_height / img_height)
112
- scaled_width = img_width * scale_factor
113
- scaled_height = img_height * scale_factor
114
- x_pos = (page_width - scaled_width) / 2
115
- y_pos = (page_height - scaled_height) / 2
116
- c.drawImage(img_reader, x_pos, y_pos, width=scaled_width, height=scaled_height)
117
- else:
118
- # Ajusta o tamanho da nova página para as dimensões da imagem atual
119
- c.setPageSize((img_width, img_height))
120
- c.drawImage(img_reader, 0, 0, width=img_width, height=img_height)
121
-
122
- c.save()
123
- buffer.seek(0)
124
- self.pbar.stop()
125
- return DocumentPdf.create_from_bytes(buffer)
126
-
127
- def to_file_pdf(self, output_file: File, *, land_scape: bool = True, a4: bool = False) -> None:
128
- self.to_document(land_scape=land_scape, a4=a4).to_file(output_file)
129
-
130
-
131
- class ImplementImageToPdfPil(ABCConvertImageToPdf):
132
- """
133
- Classe para converter uma lista de ImageObject em um DocumentPdf
134
- usando a biblioteca Pillow (PIL).
135
- """
136
-
137
- def __init__(self, collection_images: CollectionImages):
138
- super().__init__(collection_images)
139
-
140
- def set_pbar(self, p: ProgressBarAdapter):
141
- self.pbar = p
142
- self.collection_images.set_pbar(p)
143
-
144
- def to_document(self, land_scape: bool = True, a4: bool = False) -> DocumentPdf:
145
- if not MOD_IMG_PIL:
146
- raise RuntimeError("A biblioteca 'Pillow' não está disponível.")
147
-
148
- if self.collection_images:
149
- raise ValueError("A lista de imagens não pode estar vazia.")
150
-
151
- if land_scape:
152
- self.collection_images.set_land_scape()
153
-
154
- pil_images_to_save = []
155
- if a4:
156
- # Obtém as dimensões da página A4 em píxels
157
- # Usando uma resolução de 100 DPI para consistência
158
- page_width, page_height = letter # Padrão do reportlab
159
- page_size = (int(page_width), int(page_height))
160
-
161
- self.pbar.start()
162
- max_num = self.collection_images.length
163
- for num, img_obj in enumerate(self.collection_images):
164
- self.pbar.update(
165
- ((num + 1) / max_num) * 100,
166
- f'Redimensionando e ajustando imagem para A4 [{num + 1} de {max_num}]'
167
- )
168
- original_pil_image = img_obj.to_pil()
169
- img_width, img_height = original_pil_image.size
170
-
171
- # Calcula o fator de escala para ajustar a imagem à página, mantendo a proporção
172
- scale_factor = min(page_size[0] / img_width, page_size[1] / img_height)
173
- scaled_width = int(img_width * scale_factor)
174
- scaled_height = int(img_height * scale_factor)
175
-
176
- # Redimensiona a imagem
177
- resized_image = original_pil_image.resize(
178
- (scaled_width, scaled_height), Image.Resampling.LANCZOS
179
- )
180
-
181
- # Criar imagem de fundo branca com o tamanho A4
182
- new_image = Image.new('RGB', page_size, 'white')
183
-
184
- # Centraliza a imagem redimensionada na nova imagem
185
- x_pos = (page_size[0] - scaled_width) // 2
186
- y_pos = (page_size[1] - scaled_height) // 2
187
- new_image.paste(resized_image, (x_pos, y_pos))
188
-
189
- pil_images_to_save.append(new_image)
190
- self.pbar.stop()
191
- else:
192
- # Para a4 = False, não precisa redimensionar. Pillow ajusta o tamanho da página.
193
- pil_images_to_save = [img.to_pil() for img in self.collection_images]
194
-
195
- buffer = BytesIO()
196
- try:
197
- first_image_pil = pil_images_to_save[0]
198
- other_images_pil = pil_images_to_save[1:]
199
-
200
- first_image_pil.save(
201
- buffer,
202
- 'PDF',
203
- resolution=140.0,
204
- save_all=True,
205
- append_images=other_images_pil
206
- )
207
- except Exception as e:
208
- raise RuntimeError(f"Erro ao criar o PDF com Pillow: {e}") from e
209
-
210
- buffer.seek(0)
211
- return DocumentPdf.create_from_bytes(buffer)
212
-
213
- def to_file_pdf(self, output_file: File, *, land_scape: bool = True, a4: bool = False) -> None:
214
- self.to_document(land_scape=land_scape, a4=a4).to_file(output_file)
215
-
216
-
217
- class ImplementImageToPdfFitz(ABCConvertImageToPdf):
218
- """
219
- Classe para converter uma lista de ImageObject em um DocumentPdf
220
- usando a biblioteca PyMuPDF (fitz).
221
- """
222
-
223
- def __init__(self, collection_images: CollectionImages):
224
- super().__init__(collection_images)
225
-
226
- def set_pbar(self, p: ProgressBarAdapter):
227
- self.pbar = p
228
- self.collection_images.set_pbar(p)
229
-
230
- def to_document(self, land_scape: bool = True, a4: bool = False) -> DocumentPdf:
231
- max_num: int = self.collection_images.length
232
- if max_num == 0:
233
- raise ValueError('Adicione imagens para prosseguir')
234
- self.pbar.start()
235
- self.pbar.update(0, f'Convertendo {max_num} imagens em Documento PDF')
236
- buffer = BytesIO()
237
- doc = fitz.open() # Cria um novo documento PDF vazio
238
-
239
- for num, img_obj in enumerate(self.collection_images):
240
- self.pbar.update(
241
- ((num + 1) / max_num) * 100,
242
- f'Convertendo: [{num + 1} de {max_num}]'
243
- )
244
- if land_scape:
245
- img_obj.set_landscape()
246
-
247
- # Converte a imagem para bytes
248
- img_bytes_obj = img_obj.to_bytes()
249
- # Obtém as dimensões da imagem e da página
250
- img_width, img_height = img_obj.get_dimensions()
251
-
252
- # Adiciona uma nova página ao documento
253
- if a4:
254
- page = doc.new_page()
255
- else:
256
- page = doc.new_page(width=img_width, height=img_height)
257
-
258
- # Cria um retângulo que preenche a página
259
- rect = page.rect
260
- page_width, page_height = rect.width, rect.height
261
-
262
- # Calcula o fator de escala para ajustar a imagem à página
263
- scale_factor_w = page_width / img_width
264
- scale_factor_h = page_height / img_height
265
- scale_factor = min(scale_factor_w, scale_factor_h)
266
-
267
- # Ajusta o retângulo de inserção para centralizar a imagem
268
- scaled_width = img_width * scale_factor
269
- scaled_height = img_height * scale_factor
270
- x0 = (page_width - scaled_width) / 2
271
- y0 = (page_height - scaled_height) / 2
272
-
273
- # Insere a imagem no retângulo calculado
274
- page.insert_image(
275
- fitz.Rect(x0, y0, x0 + scaled_width, y0 + scaled_height),
276
- stream=img_bytes_obj
277
- )
278
-
279
- # Salva o documento no buffer de memória
280
- doc.save(buffer)
281
- doc.close()
282
- buffer.seek(0)
283
- self.pbar.update(100, 'Conversão concluída')
284
- print()
285
- self.pbar.stop()
286
- return DocumentPdf.create_from_bytes(buffer)
287
-
288
- def to_file_pdf(self, output_file: File, *, land_scape: bool = True, a4: bool = False) -> None:
289
- self.to_document(land_scape=land_scape).to_file(output_file)
290
-
291
-
292
- class ConvertImageToPdf(object):
293
- """
294
- Classe com padrão ADAPTER para converter Imagens em documento(s) PDF.
295
- """
296
-
297
- def __init__(
298
- self,
299
- collection_images: CollectionImages, *,
300
- lib_img_to_pdf: LibImageToPdf = LibImageToPdf.IMAGE_TO_PDF_FITZ
301
- ):
302
- if lib_img_to_pdf == LibImageToPdf.IMAGE_TO_PDF_CANVAS:
303
- self.convert: ABCConvertImageToPdf = ImplementImageToPdfCanvas(collection_images)
304
- elif lib_img_to_pdf == LibImageToPdf.IMAGE_TO_PDF_PIL:
305
- self.convert: ABCConvertImageToPdf = ImplementImageToPdfPil(collection_images)
306
- elif lib_img_to_pdf == LibImageToPdf.IMAGE_TO_PDF_FITZ:
307
- self.convert: ABCConvertImageToPdf = ImplementImageToPdfFitz(collection_images)
308
- else:
309
- raise NotImplementedError()
310
-
311
- self._count: int = 0
312
-
313
- @property
314
- def is_null(self) -> bool:
315
- return self.convert.collection_images.is_empty
316
-
317
- @property
318
- def pbar(self) -> ProgressBarAdapter:
319
- return self.convert.pbar
320
-
321
- def set_pbar(self, p: ProgressBarAdapter):
322
- self.convert.set_pbar(p)
323
-
324
- def add_file(self, file: File) -> None:
325
- self.convert.collection_images.add_file_image(file)
326
-
327
- def add_files(self, files: list[File]) -> None:
328
- self.convert.collection_images.add_files_image(files)
329
-
330
- def add_image(self, image: ImageObject) -> None:
331
- self.convert.collection_images.add_image(image)
332
-
333
- def add_images(self, images: list[ImageObject]) -> None:
334
- self.convert.collection_images.add_images(images)
335
-
336
- def add_directory(self, src_dir: Directory, max_files: int = 4000) -> None:
337
- self.convert.collection_images.add_directory_images(src_dir, max_files=max_files)
338
-
339
- def to_document(self, land_scape: bool = True, *, a4: bool = False) -> DocumentPdf:
340
- return self.convert.to_document(land_scape, a4=a4)
341
-
342
- def to_file_pdf(self, output_file: File, *, land_scape: bool = True, a4: bool = False) -> None:
343
- self.convert.to_file_pdf(output_file, land_scape=land_scape, a4=a4)
344
-
345
- def set_gausian_blur(self, sigma: float = 0.8) -> None:
346
- self.convert.collection_images.set_gausian_blur(sigma)
347
-
348
- def set_land_scape(self):
349
- self.convert.collection_images.set_land_scape()
@@ -1,223 +0,0 @@
1
- #!/usr/bin/env python3
2
- #
3
- """
4
- Módulo para trabalhar com imagens
5
- """
6
- from __future__ import annotations
7
- from abc import ABC, abstractmethod
8
-
9
- from sheet_stream.type_utils import MetaDataFile
10
-
11
- from convert_stream import CollectionImages
12
- from soup_files import Directory, ProgressBarAdapter, CreatePbar
13
- from convert_stream.mod_types.enums import LibPdfToImage
14
- from convert_stream.mod_types.modules import DEFAULT_LIB_PDF_TO_IMG, DEFAULT_LIB_IMAGE, LibPDF
15
- from convert_stream.image.img_object import ImageObject, LibImage
16
- from convert_stream.pdf.pdf_document import DocumentPdf
17
-
18
-
19
- try:
20
- import fitz
21
- MOD_FITZ = True
22
- except ImportError:
23
- try:
24
- import pymupdf as fitz
25
- from pymupdf import Page, Pixmap
26
- MOD_FITZ = True
27
- except ImportError:
28
- fitz = object
29
- fitz.Page = object
30
- fitz.TextPage = object
31
- Page = object
32
- Pixmap = object
33
-
34
-
35
- class ABCConvertPdf(ABC):
36
-
37
- def __init__(self, document: DocumentPdf):
38
- self.document: DocumentPdf = document
39
- self.lib_pdf_to_image: LibPdfToImage = DEFAULT_LIB_PDF_TO_IMG
40
- self.pbar: ProgressBarAdapter = CreatePbar().get()
41
-
42
- def set_pbar(self, pbar: ProgressBarAdapter):
43
- self.pbar = pbar
44
-
45
- @abstractmethod
46
- def to_images(
47
- self, *,
48
- dpi: int = 150,
49
- lib_image: LibImage = DEFAULT_LIB_IMAGE,
50
- ) -> list[ImageObject]:
51
- """
52
- Converte as páginas PDF do documento em lista de objetos imagem ImageObject
53
-
54
- :param dpi: DPI do documento, resolução da renderização.
55
- :param lib_image: Biblioteca para manipular imagens PIL/OpenCv
56
- """
57
- pass
58
-
59
- @abstractmethod
60
- def to_files_image(
61
- self,
62
- output_dir: Directory, *,
63
- replace: bool = False,
64
- gaussian_filter: bool = False,
65
- dpi: int = 300,
66
- lib_image: LibImage = DEFAULT_LIB_IMAGE,
67
- ) -> None:
68
- """
69
- Converte todas as páginas do documento em objeto de imagem e salva no disco
70
- em formato de imagem PNG.
71
- """
72
- pass
73
-
74
-
75
- class ImplementConvertPdfFitz(ABCConvertPdf):
76
-
77
- def __init__(self, document: DocumentPdf):
78
- super().__init__(document)
79
- self.lib_pdf_to_image: LibPdfToImage = LibPdfToImage.PDF_TO_IMG_FITZ
80
-
81
- def __get_pages(self) -> list[Page]:
82
- pages = self.document.to_pages()
83
- fitz_pages = []
84
- for p in pages:
85
- fitz_pages.append(p.implement_page_pdf.mod_page)
86
- return fitz_pages
87
-
88
- def to_images(
89
- self, *,
90
- dpi: int = 200,
91
- lib_image: LibImage = LibImage.PIL
92
- ) -> list[ImageObject]:
93
- """
94
- Converte um Documento em lista de objetos ImageObject.
95
- """
96
- images: list[ImageObject] = []
97
- _metadata: MetaDataFile = self.document.metadata
98
-
99
- pages_fitz: list[Page] = self.__get_pages()
100
- _count = len(pages_fitz)
101
- for n, pg in enumerate(pages_fitz):
102
- self.pbar.update(
103
- ((n+1)/_count) * 100,
104
- f'[Documento para Imagens]: página {n+1}/{_count}'
105
- )
106
- pix: Pixmap = pg.get_pixmap(dpi=dpi)
107
- img = ImageObject.create_from_bytes(
108
- pix.tobytes('png', jpg_quality=100),
109
- lib_image=LibImage.PIL,
110
- )
111
- img.metadata.name = _metadata.name
112
- img.metadata.file_path = _metadata.file_path
113
- images.append(img)
114
- return images
115
-
116
- def to_files_image(
117
- self,
118
- output_dir: Directory, *,
119
- replace: bool = False,
120
- gaussian_filter: bool = False,
121
- dpi: int = 300,
122
- lib_image: LibImage = LibImage.PIL
123
- ) -> None:
124
- pages_fitz: list[Page] = self.__get_pages()
125
- _count = len(pages_fitz)
126
- for n, pg in enumerate(pages_fitz):
127
- self.pbar.update(
128
- ((n + 1) / _count) * 100,
129
- f'[Documento para arquivos de imagens]: {n + 1}/{_count}'
130
- )
131
- out_file = output_dir.join_file(f'pag-{n+1}.png')
132
- if not replace:
133
- if out_file.exists():
134
- self.pbar.update_text(f'Pulando: {out_file.basename()}')
135
- continue
136
- pix: Pixmap = pg.get_pixmap(dpi=dpi)
137
- img = ImageObject.create_from_bytes(
138
- pix.tobytes('png', jpg_quality=100),
139
- lib_image=LibImage.PIL,
140
- )
141
- img.to_file(out_file)
142
- print()
143
-
144
-
145
- class ConvertPdfToImages(object):
146
-
147
- def __init__(self, mod_conv_to_img: ABCConvertPdf | DocumentPdf):
148
- if isinstance(mod_conv_to_img, ABCConvertPdf):
149
- self.mod_convert_to_image: ABCConvertPdf = mod_conv_to_img
150
- elif isinstance(mod_conv_to_img, ImplementConvertPdfFitz):
151
- self.mod_convert_to_image: ABCConvertPdf = mod_conv_to_img
152
- elif isinstance(mod_conv_to_img, DocumentPdf):
153
- self.mod_convert_to_image = ImplementConvertPdfFitz(mod_conv_to_img)
154
- else:
155
- raise NotImplementedError()
156
-
157
- def set_pbar(self, pbar: ProgressBarAdapter):
158
- self.mod_convert_to_image.set_pbar(pbar)
159
-
160
- def to_images(
161
- self, *,
162
- dpi: int = 300,
163
- lib_image: LibImage = LibImage.PIL,
164
- ) -> list[ImageObject]:
165
- return self.mod_convert_to_image.to_images(dpi=dpi, lib_image=lib_image)
166
-
167
- def to_files_image(
168
- self,
169
- output_dir: Directory, *,
170
- replace: bool = False,
171
- gaussian_filter: bool = False,
172
- dpi: int = 300,
173
- lib_image: LibImage = LibImage.PIL,
174
- ) -> None:
175
- self.mod_convert_to_image.to_files_image(
176
- dpi=dpi,
177
- lib_image=lib_image,
178
- replace=replace,
179
- output_dir=output_dir,
180
- gaussian_filter=gaussian_filter
181
- )
182
-
183
- def inner_images(self) -> CollectionImages:
184
- """
185
- Extrair imagens embutidas nas páginas PDF.
186
- """
187
- # doc = Document(stream=page_bytes, filetype="pdf")
188
- collection_imgs: CollectionImages = CollectionImages([])
189
- tmp_doc: fitz.Document
190
- if self.mod_convert_to_image.document.lib_pdf == LibPDF.FITZ:
191
- tmp_doc: fitz.Document = self.mod_convert_to_image.document.get_real_document()
192
- elif self.mod_convert_to_image.document.lib_pdf == LibPDF.PYPDF:
193
- tmp_doc = fitz.Document(
194
- stream=self.mod_convert_to_image.document.to_bytes().getvalue(), filetype="pdf"
195
- )
196
- else:
197
- raise NotImplementedError()
198
-
199
- page: fitz.Page
200
- for num, page in enumerate(tmp_doc):
201
- # Extrair imagens embutidas na página
202
- images_list: list = page.get_images(full=True)
203
- for img in images_list:
204
- try:
205
- # Referência do objeto da imagem
206
- xref = img[0]
207
- # Extrair imagem
208
- base_image = tmp_doc.extract_image(xref)
209
- # Bytes da imagem
210
- image_bytes = base_image["image"]
211
- # Extensão (jpg, png, etc.)
212
- #image_ext = base_image["ext"]
213
- except Exception as e:
214
- print(e)
215
- else:
216
- img = ImageObject(image_bytes)
217
- collection_imgs.append(img)
218
- return collection_imgs
219
-
220
- @classmethod
221
- def create(cls, doc: DocumentPdf) -> ConvertPdfToImages:
222
- _mod = ImplementConvertPdfFitz(doc)
223
- return cls(_mod)
File without changes
File without changes