ughost 1.0.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.
ughost-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: ughost
3
+ Version: 1.0.0
4
+ Author-email: Helmut Konrad Schewe <helmutus@outlook.com>
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/anaticulae/ughost
7
+ Project-URL: Repository, https://github.com/anaticulae/ughost
8
+ Classifier: Programming Language :: Python :: 3.12
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Classifier: Programming Language :: Python :: 3.14
11
+ Requires-Python: >=3.12
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: utilo<3.0.0,>=2.107.5
14
+ Requires-Dist: iamraw<5.0.0,>=4.91.4
15
+ Requires-Dist: Pillow<13.0.0,>=12.2.0
16
+ Requires-Dist: pdflog<2.0.0,>=1.0.2
17
+ Provides-Extra: dev
18
+ Requires-Dist: utilotest<2.0.0,>=1.0.3; extra == "dev"
19
+ Requires-Dist: hoverpower<2.0.0,>=1.1.0; extra == "dev"
20
+ Requires-Dist: upainter<2.0.0,>=1.0.0; extra == "dev"
21
+
22
+ # ughost
23
+
24
+ ```
25
+ minidocks/ughostscript
26
+ minidocks/python
27
+ ```
ughost-1.0.0/README ADDED
@@ -0,0 +1,6 @@
1
+ # ughost
2
+
3
+ ```
4
+ minidocks/ughostscript
5
+ minidocks/python
6
+ ```
@@ -0,0 +1,67 @@
1
+ [project]
2
+ name = "ughost"
3
+ version = "1.0.0"
4
+ description = ""
5
+ readme = {file = "README", content-type = "text/markdown"}
6
+ requires-python = ">=3.12"
7
+ authors = [
8
+ {name = "Helmut Konrad Schewe", email = "helmutus@outlook.com"}
9
+ ]
10
+
11
+ dependencies = [
12
+ "utilo>=2.107.5,<3.0.0",
13
+ "iamraw>=4.91.4,<5.0.0",
14
+ "Pillow>=12.2.0,<13.0.0",
15
+ "pdflog>=1.0.2,<2.0.0",
16
+ ]
17
+
18
+ # Optional but recommended metadata
19
+ keywords = []
20
+ classifiers = [
21
+ 'Programming Language :: Python :: 3.12',
22
+ 'Programming Language :: Python :: 3.13',
23
+ 'Programming Language :: Python :: 3.14',
24
+ ]
25
+ license = "MIT"
26
+ license-files = ["LICENSE"]
27
+
28
+ [project.optional-dependencies]
29
+ dev = [
30
+ "utilotest>=1.0.3,<2.0.0",
31
+ "hoverpower>=1.1.0,<2.0.0",
32
+ "upainter>=1.0.0,<2.0.0",
33
+ ]
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/anaticulae/ughost"
37
+ Repository = "https://github.com/anaticulae/ughost"
38
+
39
+ [project.scripts]
40
+ ghost = "ughost.cli:main"
41
+
42
+ [build-system]
43
+ requires = [
44
+ "setuptools>=82.0.1",
45
+ "wheel>=0.47.0"
46
+ ]
47
+ build-backend = "setuptools.build_meta"
48
+
49
+ [tool.semantic_release]
50
+ version_toml = ["pyproject.toml:project.version"]
51
+ [tool.semantic_release.changelog.default_templates]
52
+ changelog_file = "CHANGELOG"
53
+ [tool.semantic_release.changelog]
54
+ mode = "init"
55
+ output_format = "md"
56
+ [tool.semantic_release.commit_parser_options]
57
+ # allways generate a new version
58
+ patch_tags = ["fix", "perf", "build", "chore", "ci", "docs", "style", "refactor", "test", "deps"]
59
+
60
+ [tool.setuptools.packages.find]
61
+ where = ["."]
62
+ include = [
63
+ 'ughost',
64
+ ]
65
+ exclude = [
66
+ "tests*",
67
+ ]
ughost-1.0.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,35 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2022-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import hoverpower
11
+ import utilo
12
+ import utilotest
13
+
14
+ import tests
15
+
16
+
17
+ def test_help(mp):
18
+ tests.run('--help', mp=mp)
19
+
20
+
21
+ @tests.ughostscript
22
+ def test_run(td, mp):
23
+ outpath = td.tmpdir
24
+ cmd = f'-i {hoverpower.TECH019_PDF} -o {outpath} --pages=3:8,12:15'
25
+ tests.run(cmd, mp=mp)
26
+ assert utilo.file_count(outpath) == 8
27
+
28
+
29
+ @tests.ughostscript
30
+ @utilotest.longrun
31
+ def test_all(td, mp):
32
+ outpath = td.tmpdir
33
+ cmd = f'-i {hoverpower.BACHELOR032_PDF} -o {outpath}'
34
+ tests.run(cmd, mp=mp)
35
+ assert utilo.file_count(outpath) == 32
@@ -0,0 +1,38 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2021-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import os
11
+
12
+ import hoverpower
13
+ import iamraw
14
+ import utilo
15
+ import utilotest
16
+
17
+ import tests
18
+ import ughost
19
+
20
+
21
+ @tests.ughostscript
22
+ def test_images(td):
23
+ boundings = [
24
+ iamraw.ImageInformation(
25
+ page=0,
26
+ bounding=(250, 250, 1000, 1000),
27
+ ),
28
+ ]
29
+ loaded = ughost.images(
30
+ source=hoverpower.BACHELOR051_PDF,
31
+ boundings=boundings,
32
+ )
33
+ assert len(loaded) == 1
34
+ png = os.path.join(td.tmpdir, 'test.png')
35
+ image = loaded[0]
36
+ utilo.file_create_binary(png, content=image)
37
+ # verify result
38
+ utilotest.assert_bin(image, (3555017284, 3680991176, 1320373311))
@@ -0,0 +1,26 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2021-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import os
11
+
12
+ import hoverpower
13
+ import pdflog
14
+
15
+ import tests
16
+ import ughost
17
+
18
+
19
+ @tests.ughostscript
20
+ def test_optimize_small(td):
21
+ """Shrink pdf to given number of pages."""
22
+ source = hoverpower.PAPER06B_PDF
23
+ outpath = os.path.join(td.tmpdir, 'optimo.pdf')
24
+ ughost.small(source, outpath, pages=(3, 4))
25
+ pages = pdflog.pagecount(outpath)
26
+ assert pages == 2
@@ -0,0 +1,48 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2022-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import hoverpower
11
+ import upainter
12
+
13
+ import tests
14
+ import ughost.parts
15
+
16
+
17
+ @tests.ughostscript
18
+ def test_parts(td): # pylint:disable=W0613
19
+ source = hoverpower.BACHELOR028_PDF
20
+ boundings = [
21
+ ughost.parts.Part(
22
+ page=0,
23
+ bounding=(800.0, 1000.0, 1000.0, 1800),
24
+ )
25
+ ]
26
+ extracted = ughost.parts.parts(
27
+ source=source,
28
+ boundings=boundings,
29
+ )
30
+ assert len(extracted) == 1
31
+ upainter.show_figure(extracted[0])
32
+
33
+
34
+ @tests.ughostscript
35
+ def test_run_extractor(td):
36
+ source = hoverpower.BACHELOR028_PDF
37
+ boundings = [
38
+ ughost.parts.Part(
39
+ page=0,
40
+ bounding=(800.0, 1000.0, 1000.0, 1800),
41
+ )
42
+ ]
43
+ extracted = ughost.parts.run(
44
+ src=source,
45
+ dst=td.tmpdir,
46
+ boundings=boundings,
47
+ )
48
+ assert len(extracted) == 1
@@ -0,0 +1,51 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2021-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import os
11
+
12
+ import hoverpower
13
+ import utilo
14
+ import utilotest
15
+
16
+ import tests
17
+ import ughost
18
+
19
+
20
+ @tests.ughostscript
21
+ @utilotest.longrun
22
+ def test_pdfwrite_all():
23
+ source = hoverpower.TECH019_PDF
24
+ path = ughost.pdfwrite(source)
25
+ extracted = utilo.file_list(path)
26
+ assert len(extracted) == 19
27
+
28
+
29
+ @tests.ughostscript
30
+ def test_pdfwrite_pages():
31
+ """ughost script page numbers are ascending instead of names by page
32
+ number."""
33
+ source = hoverpower.TECH019_PDF
34
+ path = ughost.pdfwrite(source, pages=(3, 7))
35
+ extracted = utilo.file_list(path)
36
+ expected = ['1.png', '2.png']
37
+ assert extracted == expected
38
+ loaded = [
39
+ utilo.file_read_binary(os.path.join(path, item)) for item in extracted
40
+ ]
41
+ # verify that page number converting works
42
+ utilotest.assert_bin(loaded[0], (3201675645, 1609777475, 2024650708))
43
+ utilotest.assert_bin(loaded[1], (1204049905, 3839788996, 2476290319))
44
+
45
+
46
+ @tests.ughostscript
47
+ def test_pdfwrite_with_spaces(td):
48
+ dst = td.tmpdir.join('space with space.pdf')
49
+ utilo.file_copy(src=hoverpower.TECH019_PDF, dst=dst)
50
+ ughost.pdfwrite(dst, root=td.tmpdir, pages=1)
51
+ assert len(utilo.file_list(path=td.tmpdir)) == 2
@@ -0,0 +1,27 @@
1
+ #==============================================================================
2
+ # C O P Y R I G H T
3
+ #------------------------------------------------------------------------------
4
+ # Copyright (c) 2021-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ #==============================================================================
9
+
10
+ import os
11
+
12
+ import utilo
13
+
14
+ from ughost.extract import images
15
+ from ughost.optimize import small
16
+ from ughost.parts import Part
17
+ from ughost.parts import bounding_convert
18
+ from ughost.parts import run
19
+ from ughost.utils import pdfwrite
20
+
21
+ __version__ = '0.9.1'
22
+
23
+ ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
24
+ PROCESS = 'ughost'
25
+
26
+ INSTALLED = utilo.hasprog('gs') or utilo.hasprog('gswin64c')
27
+ HAS_GHOST = INSTALLED
@@ -0,0 +1,89 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2022-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import pdflog
11
+ import utilo
12
+ import utilo.cli
13
+
14
+ import ughost
15
+
16
+ DESCRIPTION = ''
17
+ CONFIG = utilo.ParserConfiguration(
18
+ inputparameter=True,
19
+ outputparameter=True,
20
+ prefix=False,
21
+ multiprocessed=False,
22
+ cacheflag=False,
23
+ waitingflag=False,
24
+ )
25
+ DPI = 216.0
26
+
27
+
28
+ @utilo.saveme
29
+ def main():
30
+ inpath, outpath, dpi, pages = eval_cli()
31
+ write_images(
32
+ inpath,
33
+ outpath=outpath,
34
+ dpi=dpi,
35
+ pages=pages,
36
+ )
37
+ return utilo.SUCCESS
38
+
39
+
40
+ def eval_cli():
41
+ parser = utilo.cli.create_parser(
42
+ config=CONFIG,
43
+ description=DESCRIPTION,
44
+ todo=[
45
+ utilo.Parameter(
46
+ longcut='dpi',
47
+ message='use 216 as default',
48
+ args={'default': DPI},
49
+ )
50
+ ],
51
+ prog=ughost.PROCESS,
52
+ version=ughost.__version__,
53
+ )
54
+ args = utilo.parse(parser)
55
+ inpath, outpath = utilo.sources(args, singleinput=True) # pylint:disable=W0632
56
+ # It is only single path supported. Run program multiple times if more
57
+ # than one analysis is required.
58
+ inpath = inpath[0]
59
+ dpi = args.get('dpi', DPI)
60
+ pages = parse_pages(
61
+ args.get('pages', None),
62
+ inpath=inpath,
63
+ )
64
+ return inpath, outpath, dpi, pages
65
+
66
+
67
+ def write_images(inpath, outpath, dpi: float, pages: tuple = None):
68
+ root = ughost.pdfwrite(
69
+ source=inpath,
70
+ dpi=dpi,
71
+ pages=pages,
72
+ )
73
+ written = utilo.file_list(root, include='png', absolute=True)
74
+ for path, filename in zip(written, pages):
75
+ filename = f'{str(filename).zfill(3)}.png'
76
+ dst = utilo.join(outpath, filename)
77
+ utilo.debug(f'write {dst}')
78
+ utilo.file_copy(path, dst=dst)
79
+
80
+
81
+ def parse_pages(pages: tuple, inpath: str) -> tuple:
82
+ pagecount = pdflog.pagecount(inpath)
83
+ if not pages:
84
+ return utilo.rtuple(pagecount)
85
+ pages = utilo.parse_pages(
86
+ pages[0],
87
+ pagecount=pagecount,
88
+ )
89
+ return pages
@@ -0,0 +1,52 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2021-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import io
11
+ import os
12
+
13
+ import iamraw
14
+ import PIL.Image
15
+ import utilo
16
+
17
+ import ughost
18
+
19
+ DPI = 72
20
+ RENDERER = 300
21
+
22
+
23
+ def images(source: str, boundings: iamraw.ImageInformations, dpi=DPI) -> list:
24
+ # ensure that bounding box matches with correct page
25
+ pages = sorted(set(item.page for item in boundings))
26
+ root = ughost.pdfwrite(source, dpi=RENDERER, pages=pages)
27
+ pagenr = {page: index for index, page in enumerate(pages, start=1)}
28
+ loaded = [
29
+ load_image(
30
+ bounding,
31
+ path=os.path.join(root, f'{pagenr[bounding.page]}.png'),
32
+ dpi=dpi,
33
+ ) for bounding in boundings
34
+ ]
35
+ return loaded
36
+
37
+
38
+ def load_image(bounding: iamraw.ImageInformation, path: str, dpi=DPI) -> bytes:
39
+ raw = io.BytesIO()
40
+ with PIL.Image.open(path, formats=('png',)) as loaded:
41
+ # left, upper, right, lower
42
+ bounding = utilo.tuple_mult(
43
+ bounding.bounding,
44
+ value=RENDERER / dpi,
45
+ )
46
+ croped = loaded.crop(bounding)
47
+ croped.save(raw, format='png')
48
+ # rewind the buffer
49
+ raw.seek(0)
50
+ # convert to bytes
51
+ result = raw.getvalue()
52
+ return result
@@ -0,0 +1,25 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2021-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+ """Optimize PDF
10
+ ============
11
+
12
+ Use ughostScript to optimize pdf file.
13
+ """
14
+
15
+ import utilo
16
+
17
+ import ughost.utils
18
+
19
+
20
+ def small(source: str, destination: str, pages: tuple = None):
21
+ pages = ughost.utils.gpages_fromtuple(pages)
22
+ config = '-sDEVICE=pdfwrite -dBATCH -dNOPAUSE -SAFE'
23
+ source = f'"{source}"'
24
+ cmd = f'{ughost.utils.GHOST} {config} {pages} -sOutputFile={destination} {source}'
25
+ utilo.run(cmd)
@@ -0,0 +1,161 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2022-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import dataclasses
11
+ import io
12
+
13
+ import PIL.Image
14
+ import PIL.ImageChops
15
+ import PIL.ImageDraw
16
+ import utilo
17
+
18
+ import ughost
19
+ import ughost.cli
20
+
21
+
22
+ @dataclasses.dataclass
23
+ class Part:
24
+ page: int = None
25
+ bounding: tuple = None
26
+ color: tuple = None
27
+ name: str = None
28
+
29
+ def __getitem__(self, index):
30
+ if not index:
31
+ return self.page
32
+ if index == 1:
33
+ return self.bounding
34
+ if index == 2:
35
+ return self.color
36
+ if index == 3:
37
+ return self.name
38
+ raise IndexError
39
+
40
+
41
+ def run(src: str, dst: str, boundings: list) -> list:
42
+ result = []
43
+ extracted = parts(source=src, boundings=boundings)
44
+ for image, bounding in zip(extracted, boundings):
45
+ name = bounding.name
46
+ if name is None:
47
+ name = utilo.tmpname()
48
+ outpath = utilo.join(dst, f'{name}.png')
49
+ utilo.debug(outpath)
50
+ # TODO: SECURITY: BEFORE RELASE: USE PRIVATE LATER
51
+ utilo.file_replace_binary(outpath, content=image)
52
+ result.append(outpath)
53
+ return result
54
+
55
+
56
+ # TODO: HOLY VALUE
57
+ DPI_PDF = 72.0
58
+
59
+
60
+ def bounding_convert(pdf: tuple, dpi: int = ughost.cli.DPI) -> tuple:
61
+ """\
62
+ >>> bounding_convert((120, 120, 520, 520))
63
+ (360.0, 360.0, 1560.0, 1560.0)
64
+ """
65
+ assert dpi and DPI_PDF, f'invalid dpi: {dpi}, {DPI_PDF}'
66
+ result = utilo.tuple_mult(
67
+ pdf,
68
+ value=dpi / DPI_PDF,
69
+ )
70
+ return result
71
+
72
+
73
+ def parts(source: str, boundings: list) -> list:
74
+ extracted = extract(
75
+ source=source,
76
+ boundings=boundings,
77
+ )
78
+ result = []
79
+ for item in boundings:
80
+ page, bounding = item.page, item.bounding
81
+ color = item.color
82
+ path = extracted[page]
83
+ part = extract_part(path, bounding, color)
84
+ result.append(part)
85
+ return result
86
+
87
+
88
+ def extract(source, boundings: list) -> dict:
89
+ workdir = utilo.tmpdir(root=ughost.ROOT)
90
+ pages = set(item[0] for item in boundings)
91
+ pages = sorted(pages)
92
+ pagesraw: str = ','.join(str(item) for item in pages)
93
+ cmd = f'{ughost.PROCESS} -i {source} -o {workdir} --pages={pagesraw}'
94
+ utilo.run(cmd)
95
+ files = utilo.file_list(
96
+ workdir,
97
+ absolute=True,
98
+ )
99
+ result = dict(zip(
100
+ pages,
101
+ files,
102
+ ))
103
+ return result
104
+
105
+
106
+ def extract_part(path: str, bounding: tuple, color=None) -> bytes:
107
+ raw = io.BytesIO()
108
+ with PIL.Image.open(path, formats=('png',)) as loaded:
109
+ size = loaded._size # pylint:disable=W0212
110
+ mask = create_mask(
111
+ bounding,
112
+ size=size,
113
+ )
114
+ image = PIL.ImageChops.multiply(loaded, mask)
115
+ image = colorize(image, color=color)
116
+ image.save(raw, format='png')
117
+ # rewind the buffer
118
+ raw.seek(0)
119
+ # convert to bytes
120
+ result = raw.getvalue()
121
+ return result
122
+
123
+
124
+ def create_mask(bounding: tuple, size: tuple) -> PIL.Image:
125
+ """Color list of rectangles defined in `bounding`."""
126
+ single = isinstance(bounding[0], (int, float))
127
+ if single:
128
+ bounding = [bounding]
129
+ image = PIL.Image.new(
130
+ mode='RGBA',
131
+ size=size,
132
+ )
133
+ draw = PIL.ImageDraw.Draw(image)
134
+ color = (0, 0, 0, 255)
135
+ for bbox in bounding:
136
+ # TODO: VERYIFY OVERLAPPING RECTANLGES
137
+ draw.rectangle(
138
+ bbox,
139
+ fill=color,
140
+ )
141
+ return image
142
+
143
+
144
+ def colorize(image, color):
145
+ if color is None:
146
+ color = (255, 0, 0)
147
+ # split the image into individual bands
148
+ source = image.split()
149
+ alpha = 3
150
+ # select regions where alpha is selected
151
+ mask = source[alpha].point(lambda i: i)
152
+ # process the green band
153
+ for band, col in enumerate(color):
154
+ source[band].paste(
155
+ source[band].point(lambda i: col), # pylint:disable=cell-var-from-loop
156
+ None,
157
+ mask,
158
+ )
159
+ # build a new multiband image
160
+ image = PIL.Image.merge(image.mode, source)
161
+ return image
@@ -0,0 +1,56 @@
1
+ # =============================================================================
2
+ # C O P Y R I G H T
3
+ # -----------------------------------------------------------------------------
4
+ # Copyright (c) 2021-2023 by Helmut Konrad Schewe. All rights reserved.
5
+ # This file is property of Helmut Konrad Schewe. Any unauthorized copy,
6
+ # use or distribution is an offensive act against international law and may
7
+ # be prosecuted under federal law. Its content is company confidential.
8
+ # =============================================================================
9
+
10
+ import os
11
+
12
+ import utilo
13
+
14
+ import ughost
15
+
16
+ GHOST = 'gswin64c' if utilo.iswin() else 'gs'
17
+
18
+
19
+ def pdfwrite(
20
+ source: str,
21
+ dpi: int = 300,
22
+ formats: str = 'pngalpha',
23
+ root: str = None,
24
+ pages: tuple = None,
25
+ ):
26
+ root = utilo.tmpdir(root=ughost.ROOT) if root is None else root
27
+ if isinstance(pages, int): # pylint:disable=W0160
28
+ destination = os.path.join(root, f'{pages}.png')
29
+ else:
30
+ destination = os.path.join(root, '%d.png')
31
+ pages = gpages_fromtuple(pages)
32
+ config = f'-sDEVICE={formats} -r{dpi} -dBATCH -dNOPAUSE -SAFE'
33
+ source = f'"{source}"'
34
+ cmd = f'{GHOST} {config} {pages} -sOutputFile={destination} {source}'
35
+ utilo.run(cmd)
36
+ return root
37
+
38
+
39
+ def gpages_fromtuple(pages: tuple = None) -> str:
40
+ """\
41
+ >>> gpages_fromtuple((1, 2, 3))
42
+ '-sPageList=2,3,4'
43
+ >>> gpages_fromtuple()
44
+ ''
45
+ """
46
+ if pages is None:
47
+ return ''
48
+ if isinstance(pages, int):
49
+ pages = (pages,)
50
+ # ughost requires sorted page numbers
51
+ pages = sorted(pages)
52
+ # -sPageList=1,3,5
53
+ pages = utilo.tuple_plus(pages, value=1)
54
+ pages: str = utilo.from_tuple(pages, separator=',')
55
+ pages: str = f'-sPageList={pages}'
56
+ return pages
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: ughost
3
+ Version: 1.0.0
4
+ Author-email: Helmut Konrad Schewe <helmutus@outlook.com>
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/anaticulae/ughost
7
+ Project-URL: Repository, https://github.com/anaticulae/ughost
8
+ Classifier: Programming Language :: Python :: 3.12
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Classifier: Programming Language :: Python :: 3.14
11
+ Requires-Python: >=3.12
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: utilo<3.0.0,>=2.107.5
14
+ Requires-Dist: iamraw<5.0.0,>=4.91.4
15
+ Requires-Dist: Pillow<13.0.0,>=12.2.0
16
+ Requires-Dist: pdflog<2.0.0,>=1.0.2
17
+ Provides-Extra: dev
18
+ Requires-Dist: utilotest<2.0.0,>=1.0.3; extra == "dev"
19
+ Requires-Dist: hoverpower<2.0.0,>=1.1.0; extra == "dev"
20
+ Requires-Dist: upainter<2.0.0,>=1.0.0; extra == "dev"
21
+
22
+ # ughost
23
+
24
+ ```
25
+ minidocks/ughostscript
26
+ minidocks/python
27
+ ```
@@ -0,0 +1,19 @@
1
+ README
2
+ pyproject.toml
3
+ tests/test_cli.py
4
+ tests/test_extract.py
5
+ tests/test_optimize.py
6
+ tests/test_part.py
7
+ tests/test_pdfwrite.py
8
+ ughost/__init__.py
9
+ ughost/cli.py
10
+ ughost/extract.py
11
+ ughost/optimize.py
12
+ ughost/parts.py
13
+ ughost/utils.py
14
+ ughost.egg-info/PKG-INFO
15
+ ughost.egg-info/SOURCES.txt
16
+ ughost.egg-info/dependency_links.txt
17
+ ughost.egg-info/entry_points.txt
18
+ ughost.egg-info/requires.txt
19
+ ughost.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ghost = ughost.cli:main
@@ -0,0 +1,9 @@
1
+ utilo<3.0.0,>=2.107.5
2
+ iamraw<5.0.0,>=4.91.4
3
+ Pillow<13.0.0,>=12.2.0
4
+ pdflog<2.0.0,>=1.0.2
5
+
6
+ [dev]
7
+ utilotest<2.0.0,>=1.0.3
8
+ hoverpower<2.0.0,>=1.1.0
9
+ upainter<2.0.0,>=1.0.0
@@ -0,0 +1 @@
1
+ ughost