fotolab 0.17.0__tar.gz → 0.18.1__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.
- {fotolab-0.17.0 → fotolab-0.18.1}/.pre-commit-config.yaml +1 -1
- {fotolab-0.17.0 → fotolab-0.18.1}/.python-version +1 -1
- {fotolab-0.17.0 → fotolab-0.18.1}/CHANGELOG.md +12 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/PKG-INFO +3 -2
- {fotolab-0.17.0 → fotolab-0.18.1}/Pipfile.lock +7 -7
- {fotolab-0.17.0 → fotolab-0.18.1}/README.md +2 -1
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/__init__.py +1 -1
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/auto.py +2 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/cli.py +1 -1
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/env.py +1 -3
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/info.py +11 -5
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/watermark.py +35 -3
- {fotolab-0.17.0 → fotolab-0.18.1}/.coveragerc +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/.gitignore +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/CONTRIBUTING.md +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/LICENSE.md +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/Pipfile +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/Makefile +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/make.bat +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/source/CHANGELOG.md +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/source/CONTRIBUTING.md +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/source/LICENSE.md +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/source/README.md +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/source/_static/logo.jpg +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/source/conf.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/docs/source/index.rst +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/__main__.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/animate.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/border.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/contrast.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/montage.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/resize.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/rotate.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/fotolab/sharpen.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/noxfile.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/pyproject.toml +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/tests/__init__.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/tests/conftest.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/tests/test_env.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/tests/test_help_flag.py +0 -0
- {fotolab-0.17.0 → fotolab-0.18.1}/tests/test_quiet_flag.py +0 -0
@@ -7,6 +7,18 @@ and this project adheres to [0-based versioning](https://0ver.org/).
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
## v0.18.1 (2024-10-06)
|
11
|
+
|
12
|
+
- Bump deps and Python version in `pyenv`
|
13
|
+
- Use `prog` field in `argparse` when show program version
|
14
|
+
- Set watermark text default to lowercase
|
15
|
+
|
16
|
+
## v0.18.0 (2024-09-29)
|
17
|
+
|
18
|
+
- Add `--camera` flag to `watermark` subcommand to use camera's metadata as text
|
19
|
+
- Add `--lowercase` flag to `watermark` subcommand to use lowercase the watermark text
|
20
|
+
- Bump deps and `pre-commit` hooks
|
21
|
+
|
10
22
|
## v0.17.0 (2024-09-22)
|
11
23
|
|
12
24
|
- Bump Python versions for `pyenv`
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fotolab
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.18.1
|
4
4
|
Summary: A console program that manipulate images.
|
5
5
|
Keywords: photography,photo
|
6
6
|
Author-email: Kian-Meng Ang <kianmeng@cpan.org>
|
@@ -328,7 +328,7 @@ fotolab watermark -h
|
|
328
328
|
usage: fotolab watermark [-h] [-t WATERMARK_TEXT]
|
329
329
|
[-p {top-left,top-right,bottom-left,bottom-right}]
|
330
330
|
[-pd PADDING] [-fs FONT_SIZE] [-fc FONT_COLOR]
|
331
|
-
[-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR]
|
331
|
+
[-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR] [--camera]
|
332
332
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
333
333
|
|
334
334
|
positional arguments:
|
@@ -355,6 +355,7 @@ options:
|
|
355
355
|
-oc OUTLINE_COLOR, --outline-color OUTLINE_COLOR
|
356
356
|
set the outline color of the watermark text (default:
|
357
357
|
'black')
|
358
|
+
--camera use camera metadata as watermark
|
358
359
|
```
|
359
360
|
|
360
361
|
<!--help-watermark !-->
|
@@ -953,12 +953,12 @@
|
|
953
953
|
},
|
954
954
|
"tomli": {
|
955
955
|
"hashes": [
|
956
|
-
"sha256:
|
957
|
-
"sha256:
|
956
|
+
"sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38",
|
957
|
+
"sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"
|
958
958
|
],
|
959
959
|
"index": "pypi",
|
960
|
-
"markers": "python_version >= '3.
|
961
|
-
"version": "==2.0.
|
960
|
+
"markers": "python_version >= '3.8'",
|
961
|
+
"version": "==2.0.2"
|
962
962
|
},
|
963
963
|
"urllib3": {
|
964
964
|
"hashes": [
|
@@ -970,11 +970,11 @@
|
|
970
970
|
},
|
971
971
|
"virtualenv": {
|
972
972
|
"hashes": [
|
973
|
-
"sha256:
|
974
|
-
"sha256:
|
973
|
+
"sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48",
|
974
|
+
"sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2"
|
975
975
|
],
|
976
976
|
"markers": "python_version >= '3.7'",
|
977
|
-
"version": "==20.26.
|
977
|
+
"version": "==20.26.6"
|
978
978
|
},
|
979
979
|
"zipp": {
|
980
980
|
"hashes": [
|
@@ -306,7 +306,7 @@ fotolab watermark -h
|
|
306
306
|
usage: fotolab watermark [-h] [-t WATERMARK_TEXT]
|
307
307
|
[-p {top-left,top-right,bottom-left,bottom-right}]
|
308
308
|
[-pd PADDING] [-fs FONT_SIZE] [-fc FONT_COLOR]
|
309
|
-
[-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR]
|
309
|
+
[-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR] [--camera]
|
310
310
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
311
311
|
|
312
312
|
positional arguments:
|
@@ -333,6 +333,7 @@ options:
|
|
333
333
|
-oc OUTLINE_COLOR, --outline-color OUTLINE_COLOR
|
334
334
|
set the outline color of the watermark text (default:
|
335
335
|
'black')
|
336
|
+
--camera use camera metadata as watermark
|
336
337
|
```
|
337
338
|
|
338
339
|
<!--help-watermark !-->
|
@@ -67,6 +67,8 @@ def run(args: argparse.Namespace) -> None:
|
|
67
67
|
"outline_width": 2,
|
68
68
|
"outline_color": "black",
|
69
69
|
"padding": 15,
|
70
|
+
"camera": False,
|
71
|
+
"lowercase": False,
|
70
72
|
}
|
71
73
|
combined_args = argparse.Namespace(**vars(args), **extra_args)
|
72
74
|
combined_args.overwrite = True
|
@@ -34,7 +34,7 @@ def build_subparser(subparsers) -> None:
|
|
34
34
|
env_parser.set_defaults(func=run)
|
35
35
|
|
36
36
|
|
37
|
-
def run(
|
37
|
+
def run(_args: argparse.Namespace) -> None:
|
38
38
|
"""Run env subcommand.
|
39
39
|
|
40
40
|
Args:
|
@@ -43,8 +43,6 @@ def run(args: argparse.Namespace) -> None:
|
|
43
43
|
Returns:
|
44
44
|
None
|
45
45
|
"""
|
46
|
-
log.debug(args)
|
47
|
-
|
48
46
|
sys_version = sys.version.replace("\n", "")
|
49
47
|
print(
|
50
48
|
f"fotolab: {__version__}",
|
@@ -58,16 +58,22 @@ def run(args: argparse.Namespace) -> None:
|
|
58
58
|
"""
|
59
59
|
log.debug(args)
|
60
60
|
|
61
|
-
|
61
|
+
exif_tags = extract_exif_tags(args.image.filename)
|
62
|
+
tag_name_width = max(map(len, exif_tags))
|
63
|
+
for tag_name, tag_value in exif_tags.items():
|
64
|
+
print(f"{tag_name:<{tag_name_width}}: {tag_value}")
|
65
|
+
|
66
|
+
|
67
|
+
def extract_exif_tags(image_filename: str, sort: bool = False) -> dict:
|
68
|
+
"""Extract Exif metadata from image."""
|
69
|
+
image = Image.open(image_filename)
|
62
70
|
exif = image._getexif()
|
63
71
|
info = {ExifTags.TAGS.get(tag_id): exif.get(tag_id) for tag_id in exif}
|
64
72
|
|
65
73
|
filtered_info = {
|
66
74
|
key: value for key, value in info.items() if key is not None
|
67
75
|
}
|
68
|
-
if
|
76
|
+
if sort:
|
69
77
|
filtered_info = dict(sorted(filtered_info.items()))
|
70
78
|
|
71
|
-
|
72
|
-
for tag_name, tag_value in filtered_info.items():
|
73
|
-
print(f"{tag_name:<{tag_name_width}}: {tag_value}")
|
79
|
+
return filtered_info
|
@@ -22,6 +22,7 @@ import math
|
|
22
22
|
from PIL import Image, ImageColor, ImageDraw, ImageFont
|
23
23
|
|
24
24
|
from fotolab import save_image
|
25
|
+
from fotolab.info import extract_exif_tags
|
25
26
|
|
26
27
|
log = logging.getLogger(__name__)
|
27
28
|
|
@@ -126,12 +127,29 @@ def build_subparser(subparsers) -> None:
|
|
126
127
|
metavar="OUTLINE_COLOR",
|
127
128
|
)
|
128
129
|
|
130
|
+
watermark_parser.add_argument(
|
131
|
+
"--camera",
|
132
|
+
default=False,
|
133
|
+
action="store_true",
|
134
|
+
dest="camera",
|
135
|
+
help="use camera metadata as watermark",
|
136
|
+
)
|
137
|
+
|
138
|
+
watermark_parser.add_argument(
|
139
|
+
"-l",
|
140
|
+
"--lowercase",
|
141
|
+
default=True,
|
142
|
+
action="store_true",
|
143
|
+
dest="lowercase",
|
144
|
+
help="lowercase the watermark text",
|
145
|
+
)
|
146
|
+
|
129
147
|
|
130
148
|
def run(args: argparse.Namespace) -> None:
|
131
149
|
"""Run watermark subcommand.
|
132
150
|
|
133
151
|
Args:
|
134
|
-
|
152
|
+
args (argparse.Namespace): Config from command line arguments
|
135
153
|
|
136
154
|
Returns:
|
137
155
|
None
|
@@ -147,8 +165,15 @@ def run(args: argparse.Namespace) -> None:
|
|
147
165
|
font = ImageFont.load_default(calc_font_size(original_image, args))
|
148
166
|
log.debug("default font: %s", " ".join(font.getname()))
|
149
167
|
|
168
|
+
text = args.text
|
169
|
+
if args.camera and camera_metadata(image_filename):
|
170
|
+
text = camera_metadata(image_filename)
|
171
|
+
|
172
|
+
if args.lowercase:
|
173
|
+
text = text.lower()
|
174
|
+
|
150
175
|
(left, top, right, bottom) = draw.textbbox(
|
151
|
-
xy=(0, 0), text=
|
176
|
+
xy=(0, 0), text=text, font=font
|
152
177
|
)
|
153
178
|
text_width = right - left
|
154
179
|
text_height = bottom - top
|
@@ -162,7 +187,7 @@ def run(args: argparse.Namespace) -> None:
|
|
162
187
|
|
163
188
|
draw.text(
|
164
189
|
(position_x, position_y),
|
165
|
-
|
190
|
+
text,
|
166
191
|
font=font,
|
167
192
|
fill=(*ImageColor.getrgb(args.font_color), 128),
|
168
193
|
stroke_width=calc_font_outline_width(original_image, args),
|
@@ -172,6 +197,13 @@ def run(args: argparse.Namespace) -> None:
|
|
172
197
|
save_image(args, watermarked_image, image_filename, "watermark")
|
173
198
|
|
174
199
|
|
200
|
+
def camera_metadata(image_filename):
|
201
|
+
"""Extract camera and model metadata."""
|
202
|
+
exif_tags = extract_exif_tags(image_filename)
|
203
|
+
metadata = f'{exif_tags["Make"]} {exif_tags["Model"]}'
|
204
|
+
return metadata.strip()
|
205
|
+
|
206
|
+
|
175
207
|
def calc_font_size(image, args) -> int:
|
176
208
|
"""Calculate the font size based on the width of the image."""
|
177
209
|
width, _height = image.size
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|