fotolab 0.33.1__py3-none-any.whl → 0.34.0__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.
- fotolab/__init__.py +7 -22
- fotolab/__main__.py +0 -1
- fotolab/cli.py +9 -3
- fotolab/subcommands/animate.py +2 -2
- fotolab/subcommands/contrast.py +19 -3
- fotolab/subcommands/halftone.py +2 -2
- {fotolab-0.33.1.dist-info → fotolab-0.34.0.dist-info}/METADATA +4 -3
- {fotolab-0.33.1.dist-info → fotolab-0.34.0.dist-info}/RECORD +12 -12
- {fotolab-0.33.1.dist-info → fotolab-0.34.0.dist-info}/WHEEL +0 -0
- {fotolab-0.33.1.dist-info → fotolab-0.34.0.dist-info}/entry_points.txt +0 -0
- {fotolab-0.33.1.dist-info → fotolab-0.34.0.dist-info}/licenses/LICENSE.md +0 -0
- {fotolab-0.33.1.dist-info → fotolab-0.34.0.dist-info}/top_level.txt +0 -0
fotolab/__init__.py
CHANGED
@@ -15,16 +15,17 @@
|
|
15
15
|
|
16
16
|
"""A console program that manipulate images."""
|
17
17
|
|
18
|
+
from importlib import metadata
|
19
|
+
from pathlib import Path
|
18
20
|
import argparse
|
19
21
|
import logging
|
20
22
|
import os
|
21
23
|
import subprocess
|
22
24
|
import sys
|
23
|
-
from pathlib import Path
|
24
25
|
|
25
26
|
from PIL import Image
|
26
27
|
|
27
|
-
__version__ =
|
28
|
+
__version__ = metadata.version("fotolab")
|
28
29
|
|
29
30
|
log = logging.getLogger(__name__)
|
30
31
|
|
@@ -45,12 +46,10 @@ def save_gif_image(
|
|
45
46
|
"loop": 0,
|
46
47
|
"optimize": True,
|
47
48
|
}
|
48
|
-
|
49
|
-
args, original_image, image_filepath, subcommand, **gif_kwargs
|
50
|
-
)
|
49
|
+
save_image(args, original_image, image_filepath, subcommand, **gif_kwargs)
|
51
50
|
|
52
51
|
|
53
|
-
def
|
52
|
+
def save_image(
|
54
53
|
args: argparse.Namespace,
|
55
54
|
image: Image.Image,
|
56
55
|
output_filepath: Path,
|
@@ -71,21 +70,7 @@ def _save_image_with_options(
|
|
71
70
|
image.save(new_filename, **kwargs)
|
72
71
|
|
73
72
|
if args.open:
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def save_image(
|
78
|
-
args: argparse.Namespace,
|
79
|
-
new_image: Image.Image,
|
80
|
-
output_filepath: Path,
|
81
|
-
subcommand: str,
|
82
|
-
) -> None:
|
83
|
-
"""Save image after image operation.
|
84
|
-
|
85
|
-
Returns:
|
86
|
-
None
|
87
|
-
"""
|
88
|
-
_save_image_with_options(args, new_image, output_filepath, subcommand)
|
73
|
+
open_image(new_filename)
|
89
74
|
|
90
75
|
|
91
76
|
def _get_output_filename(
|
@@ -100,7 +85,7 @@ def _get_output_filename(
|
|
100
85
|
return output_dir / image_file.with_name(f"{subcommand}_{image_file.name}")
|
101
86
|
|
102
87
|
|
103
|
-
def
|
88
|
+
def open_image(filename: Path):
|
104
89
|
"""Open generated image using default program."""
|
105
90
|
try:
|
106
91
|
if sys.platform == "linux":
|
fotolab/__main__.py
CHANGED
fotolab/cli.py
CHANGED
@@ -23,7 +23,9 @@ issues: https://github.com/kianmeng/fotolab/issues
|
|
23
23
|
import argparse
|
24
24
|
import logging
|
25
25
|
import sys
|
26
|
-
from typing import
|
26
|
+
from typing import Sequence
|
27
|
+
|
28
|
+
from PIL import Image
|
27
29
|
|
28
30
|
import fotolab.subcommands
|
29
31
|
from fotolab import __version__
|
@@ -122,7 +124,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
122
124
|
return parser
|
123
125
|
|
124
126
|
|
125
|
-
def main(args:
|
127
|
+
def main(args: Sequence[str] | None = None) -> None:
|
126
128
|
"""Run the main program flow."""
|
127
129
|
args = args or sys.argv[1:]
|
128
130
|
log.debug(args)
|
@@ -150,7 +152,11 @@ def main(args: Optional[Sequence[str]] = None) -> None:
|
|
150
152
|
else:
|
151
153
|
parser.print_help(sys.stderr)
|
152
154
|
|
153
|
-
except
|
155
|
+
except (
|
156
|
+
FileNotFoundError,
|
157
|
+
ValueError,
|
158
|
+
Image.UnidentifiedImageError,
|
159
|
+
) as error:
|
154
160
|
log.error(
|
155
161
|
"error: %s",
|
156
162
|
getattr(error, "message", str(error)),
|
fotolab/subcommands/animate.py
CHANGED
@@ -22,7 +22,7 @@ from contextlib import ExitStack
|
|
22
22
|
|
23
23
|
from PIL import Image
|
24
24
|
|
25
|
-
from fotolab import
|
25
|
+
from fotolab import open_image
|
26
26
|
|
27
27
|
log = logging.getLogger(__name__)
|
28
28
|
|
@@ -205,4 +205,4 @@ def run(args: argparse.Namespace) -> None:
|
|
205
205
|
main_frame.save(new_filename, **save_kwargs)
|
206
206
|
|
207
207
|
if args.open:
|
208
|
-
|
208
|
+
open_image(new_filename)
|
fotolab/subcommands/contrast.py
CHANGED
@@ -104,8 +104,24 @@ def run(args: argparse.Namespace) -> None:
|
|
104
104
|
|
105
105
|
for image_filename in args.image_filenames:
|
106
106
|
original_image = Image.open(image_filename)
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
|
108
|
+
if original_image.mode == "RGBA":
|
109
|
+
# Split the image into RGB and Alpha channels
|
110
|
+
rgb_image = original_image.convert("RGB")
|
111
|
+
alpha_channel = original_image.getchannel("A")
|
112
|
+
|
113
|
+
# Apply autocontrast to the RGB part
|
114
|
+
contrasted_rgb = ImageOps.autocontrast(
|
115
|
+
rgb_image, cutoff=args.cutoff
|
116
|
+
)
|
117
|
+
|
118
|
+
# Merge the contrasted RGB part with the original Alpha channel
|
119
|
+
contrasted_rgb.putalpha(alpha_channel)
|
120
|
+
contrast_image = contrasted_rgb
|
121
|
+
else:
|
122
|
+
# For other modes (like RGB, L, etc.), apply autocontrast directly
|
123
|
+
contrast_image = ImageOps.autocontrast(
|
124
|
+
original_image, cutoff=args.cutoff
|
125
|
+
)
|
110
126
|
|
111
127
|
save_image(args, contrast_image, Path(image_filename), "contrast")
|
fotolab/subcommands/halftone.py
CHANGED
@@ -19,7 +19,7 @@ import argparse
|
|
19
19
|
import logging
|
20
20
|
import math
|
21
21
|
from pathlib import Path
|
22
|
-
from typing import NamedTuple
|
22
|
+
from typing import NamedTuple
|
23
23
|
|
24
24
|
from PIL import Image, ImageDraw
|
25
25
|
|
@@ -200,7 +200,7 @@ def create_halftone_image(
|
|
200
200
|
Image.Image: The halftone converted image
|
201
201
|
"""
|
202
202
|
output_mode: str
|
203
|
-
fill_color_black:
|
203
|
+
fill_color_black: int | tuple[int, int, int]
|
204
204
|
fill_color_dot_for_grayscale: int
|
205
205
|
|
206
206
|
if grayscale:
|
@@ -1,6 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fotolab
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.34.0
|
4
|
+
Summary: A console program to manipulate photos.
|
4
5
|
Author-email: Kian-Meng Ang <kianmeng@cpan.org>
|
5
6
|
License-Expression: AGPL-3.0-or-later
|
6
7
|
Project-URL: Changelog, https://github.com/kianmeng/fotolab/blob/master/CHANGELOG.md
|
@@ -10,13 +11,13 @@ Keywords: photography,photo
|
|
10
11
|
Classifier: Development Status :: 3 - Alpha
|
11
12
|
Classifier: Environment :: Console
|
12
13
|
Classifier: Programming Language :: Python :: 3 :: Only
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
18
19
|
Classifier: Programming Language :: Python
|
19
|
-
Requires-Python: >=3.
|
20
|
+
Requires-Python: >=3.10
|
20
21
|
Description-Content-Type: text/markdown
|
21
22
|
License-File: LICENSE.md
|
22
23
|
Requires-Dist: pillow
|
@@ -1,22 +1,22 @@
|
|
1
|
-
fotolab/__init__.py,sha256=
|
2
|
-
fotolab/__main__.py,sha256=
|
3
|
-
fotolab/cli.py,sha256=
|
1
|
+
fotolab/__init__.py,sha256=0UZ6OZFCRkc2Fwc4LT1UtE9JdK3uq0uL8fSSVSOuVyo,3161
|
2
|
+
fotolab/__main__.py,sha256=Wk11t_zKs3wJ-okM3yv7Mtj1pRwQZu3NCmpteBwn4Hs,810
|
3
|
+
fotolab/cli.py,sha256=Ebx6RQM5Dr8PsIqQ4NOySxnGMzGGI0U7CTawYfHROlk,4499
|
4
4
|
fotolab/subcommands/__init__.py,sha256=l3DlIaJ3u3jGjnC1H1yV8LZ_nPqOLJ6gikD4BCaMAQ0,1129
|
5
|
-
fotolab/subcommands/animate.py,sha256=
|
5
|
+
fotolab/subcommands/animate.py,sha256=pyoMfRtE-07EhFni2yS8xEoRV9up5T4VcF4Qw8me4Hs,5879
|
6
6
|
fotolab/subcommands/auto.py,sha256=gkpZ15JwzSlQPYSqGSeeGu0SLKps3A2cEn1dYpyQEyk,3584
|
7
7
|
fotolab/subcommands/border.py,sha256=TSr1rqAPWe1ZThkZan_WiMQdSTuua2YPXg6fYcvFitQ,4715
|
8
|
-
fotolab/subcommands/contrast.py,sha256=
|
8
|
+
fotolab/subcommands/contrast.py,sha256=yoIcJbqz3S0kzMOD39MVIcLMj2GTtVN3uPI8wsoHysQ,3711
|
9
9
|
fotolab/subcommands/env.py,sha256=QoxRvzZKgmoHTUxDV4QYhdChCpMWs5TbXFY_qIpIQpE,1469
|
10
|
-
fotolab/subcommands/halftone.py,sha256=
|
10
|
+
fotolab/subcommands/halftone.py,sha256=a0rZWE6elXhMSCyE-w_FKEMoDGK9Afs9oF3yT09ZhcA,6768
|
11
11
|
fotolab/subcommands/info.py,sha256=H3voMi67cKoHT2Mu4RUNQBPdb_MspetPjhOvy-YyNnE,3563
|
12
12
|
fotolab/subcommands/montage.py,sha256=ax-TG5FixBRFHPGkVTq8kOtRL900K6nujeBYHZ0yBAE,2622
|
13
13
|
fotolab/subcommands/resize.py,sha256=d1-_xoTB8Vf62bm7H_9MfXrMaJhlzLiUbePgTdYzaKs,5816
|
14
14
|
fotolab/subcommands/rotate.py,sha256=-yZ7pNW7PDOPBWbKPDut9z8bBe1NocfVBV_6V6tqq-4,2945
|
15
15
|
fotolab/subcommands/sharpen.py,sha256=vGBJHHHUaQ2_SHS-E1mHfNVIfnnNYcCk5ritajWTik8,3594
|
16
16
|
fotolab/subcommands/watermark.py,sha256=BkUa1tH86Ii_u03ypj9Tm0u9v7s9y9Jiz3aLpjmFDb8,11355
|
17
|
-
fotolab-0.
|
18
|
-
fotolab-0.
|
19
|
-
fotolab-0.
|
20
|
-
fotolab-0.
|
21
|
-
fotolab-0.
|
22
|
-
fotolab-0.
|
17
|
+
fotolab-0.34.0.dist-info/licenses/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
|
18
|
+
fotolab-0.34.0.dist-info/METADATA,sha256=AFHeSlX8rf-ueN9HHsJ9nBzfu_Nw2UoeGSJaqsFDBrc,14816
|
19
|
+
fotolab-0.34.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
20
|
+
fotolab-0.34.0.dist-info/entry_points.txt,sha256=0e1go9plFpqj5FP-OpV2acxTAx3ViI59PMXuhejvgcQ,45
|
21
|
+
fotolab-0.34.0.dist-info/top_level.txt,sha256=XUJ3gdpsbjohoZCLdVlbQrxAUDkbQg7WwGQG2DaN0t4,8
|
22
|
+
fotolab-0.34.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|