fotolab 0.21.1__py3-none-any.whl → 0.24.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 +1 -1
- fotolab/cli.py +26 -42
- fotolab/subcommands/__init__.py +32 -0
- fotolab/{auto.py → subcommands/auto.py} +8 -8
- fotolab/{env.py → subcommands/env.py} +3 -3
- fotolab/{info.py → subcommands/info.py} +30 -6
- fotolab/{rotate.py → subcommands/rotate.py} +20 -1
- fotolab/{watermark.py → subcommands/watermark.py} +79 -32
- {fotolab-0.21.1.dist-info → fotolab-0.24.0.dist-info}/METADATA +18 -11
- fotolab-0.24.0.dist-info/RECORD +20 -0
- fotolab-0.21.1.dist-info/RECORD +0 -19
- /fotolab/{animate.py → subcommands/animate.py} +0 -0
- /fotolab/{border.py → subcommands/border.py} +0 -0
- /fotolab/{contrast.py → subcommands/contrast.py} +0 -0
- /fotolab/{montage.py → subcommands/montage.py} +0 -0
- /fotolab/{resize.py → subcommands/resize.py} +0 -0
- /fotolab/{sharpen.py → subcommands/sharpen.py} +0 -0
- {fotolab-0.21.1.dist-info → fotolab-0.24.0.dist-info}/LICENSE.md +0 -0
- {fotolab-0.21.1.dist-info → fotolab-0.24.0.dist-info}/WHEEL +0 -0
- {fotolab-0.21.1.dist-info → fotolab-0.24.0.dist-info}/entry_points.txt +0 -0
fotolab/__init__.py
CHANGED
fotolab/cli.py
CHANGED
@@ -23,46 +23,40 @@
|
|
23
23
|
import argparse
|
24
24
|
import logging
|
25
25
|
import sys
|
26
|
-
from typing import
|
27
|
-
|
28
|
-
import fotolab.
|
29
|
-
import fotolab.auto
|
30
|
-
import fotolab.border
|
31
|
-
import fotolab.contrast
|
32
|
-
import fotolab.env
|
33
|
-
import fotolab.info
|
34
|
-
import fotolab.montage
|
35
|
-
import fotolab.resize
|
36
|
-
import fotolab.rotate
|
37
|
-
import fotolab.sharpen
|
38
|
-
import fotolab.watermark
|
26
|
+
from typing import Optional, Sequence
|
27
|
+
|
28
|
+
import fotolab.subcommands
|
39
29
|
from fotolab import __version__
|
40
30
|
|
41
31
|
log = logging.getLogger(__name__)
|
42
32
|
|
43
33
|
|
44
34
|
def setup_logging(args: argparse.Namespace) -> None:
|
45
|
-
"""
|
46
|
-
if args.verbose == 0:
|
47
|
-
logging.getLogger("PIL").setLevel(logging.ERROR)
|
35
|
+
"""Sets up logging configuration based on command-line arguments.
|
48
36
|
|
37
|
+
Args:
|
38
|
+
args (argparse.Namespace): Namespace containing parsed arguments.
|
39
|
+
"""
|
49
40
|
if args.quiet:
|
50
41
|
logging.disable(logging.NOTSET)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
42
|
+
return
|
43
|
+
|
44
|
+
if args.verbose == 0:
|
45
|
+
logging.getLogger("PIL").setLevel(logging.ERROR)
|
46
|
+
|
47
|
+
level = logging.DEBUG if args.debug else logging.INFO
|
48
|
+
format_string = (
|
49
|
+
"[%(asctime)s] %(levelname)s: %(name)s: %(message)s"
|
50
|
+
if args.debug
|
51
|
+
else "%(message)s"
|
52
|
+
)
|
53
|
+
|
54
|
+
logging.basicConfig(
|
55
|
+
level=level,
|
56
|
+
format=format_string,
|
57
|
+
stream=sys.stdout,
|
58
|
+
datefmt="%Y-%m-%d %H:%M:%S",
|
59
|
+
)
|
66
60
|
|
67
61
|
|
68
62
|
def build_parser() -> argparse.ArgumentParser:
|
@@ -136,17 +130,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
136
130
|
)
|
137
131
|
|
138
132
|
subparsers = parser.add_subparsers(help="sub-command help")
|
139
|
-
fotolab.
|
140
|
-
fotolab.auto.build_subparser(subparsers)
|
141
|
-
fotolab.border.build_subparser(subparsers)
|
142
|
-
fotolab.contrast.build_subparser(subparsers)
|
143
|
-
fotolab.info.build_subparser(subparsers)
|
144
|
-
fotolab.resize.build_subparser(subparsers)
|
145
|
-
fotolab.rotate.build_subparser(subparsers)
|
146
|
-
fotolab.montage.build_subparser(subparsers)
|
147
|
-
fotolab.sharpen.build_subparser(subparsers)
|
148
|
-
fotolab.watermark.build_subparser(subparsers)
|
149
|
-
fotolab.env.build_subparser(subparsers)
|
133
|
+
fotolab.subcommands.build_subparser(subparsers)
|
150
134
|
|
151
135
|
return parser
|
152
136
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright (C) 2024 Kian-Meng Ang
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify it under
|
4
|
+
# the terms of the GNU Affero General Public License as published by the Free
|
5
|
+
# Software Foundation, either version 3 of the License, or (at your option) any
|
6
|
+
# later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
9
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
10
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
11
|
+
# details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Affero General Public License
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
"""Common utils for subcommand."""
|
17
|
+
|
18
|
+
import importlib
|
19
|
+
import pkgutil
|
20
|
+
|
21
|
+
|
22
|
+
def build_subparser(subparsers):
|
23
|
+
"""Build subparser for each subcommands."""
|
24
|
+
iter_namespace = pkgutil.iter_modules(__path__, __name__ + ".")
|
25
|
+
|
26
|
+
subcommands = {
|
27
|
+
name: importlib.import_module(name)
|
28
|
+
for finder, name, ispkg in iter_namespace
|
29
|
+
}
|
30
|
+
|
31
|
+
for subcommand in subcommands.values():
|
32
|
+
subcommand.build_subparser(subparsers)
|
@@ -18,10 +18,10 @@
|
|
18
18
|
import argparse
|
19
19
|
import logging
|
20
20
|
|
21
|
-
import fotolab.contrast
|
22
|
-
import fotolab.resize
|
23
|
-
import fotolab.sharpen
|
24
|
-
import fotolab.watermark
|
21
|
+
import fotolab.subcommands.contrast
|
22
|
+
import fotolab.subcommands.resize
|
23
|
+
import fotolab.subcommands.sharpen
|
24
|
+
import fotolab.subcommands.watermark
|
25
25
|
|
26
26
|
log = logging.getLogger(__name__)
|
27
27
|
|
@@ -77,7 +77,7 @@ def run(args: argparse.Namespace) -> None:
|
|
77
77
|
log.debug(args)
|
78
78
|
log.debug(combined_args)
|
79
79
|
|
80
|
-
fotolab.resize.run(combined_args)
|
81
|
-
fotolab.contrast.run(combined_args)
|
82
|
-
fotolab.sharpen.run(combined_args)
|
83
|
-
fotolab.watermark.run(combined_args)
|
80
|
+
fotolab.subcommands.resize.run(combined_args)
|
81
|
+
fotolab.subcommands.contrast.run(combined_args)
|
82
|
+
fotolab.subcommands.sharpen.run(combined_args)
|
83
|
+
fotolab.subcommands.watermark.run(combined_args)
|
@@ -44,9 +44,9 @@ def run(_args: argparse.Namespace) -> None:
|
|
44
44
|
None
|
45
45
|
"""
|
46
46
|
sys_version = sys.version.replace("\n", "")
|
47
|
-
|
47
|
+
env = [
|
48
48
|
f"fotolab: {__version__}",
|
49
49
|
f"python: {sys_version}",
|
50
50
|
f"platform: {platform.platform()}",
|
51
|
-
|
52
|
-
)
|
51
|
+
]
|
52
|
+
print(*env, sep="\n")
|
@@ -54,6 +54,14 @@ def build_subparser(subparsers) -> None:
|
|
54
54
|
help="show the camera maker details",
|
55
55
|
)
|
56
56
|
|
57
|
+
info_parser.add_argument(
|
58
|
+
"--datetime",
|
59
|
+
default=False,
|
60
|
+
action="store_true",
|
61
|
+
dest="datetime",
|
62
|
+
help="show the datetime",
|
63
|
+
)
|
64
|
+
|
57
65
|
|
58
66
|
def run(args: argparse.Namespace) -> None:
|
59
67
|
"""Run info subcommand.
|
@@ -65,10 +73,20 @@ def run(args: argparse.Namespace) -> None:
|
|
65
73
|
None
|
66
74
|
"""
|
67
75
|
log.debug(args)
|
76
|
+
|
77
|
+
info = []
|
78
|
+
image = Image.open(args.image_filename)
|
79
|
+
|
68
80
|
if args.camera:
|
69
|
-
|
81
|
+
info.append(camera_metadata(image))
|
82
|
+
|
83
|
+
if args.datetime:
|
84
|
+
info.append(datetime(image))
|
85
|
+
|
86
|
+
if info:
|
87
|
+
print("\n".join(info))
|
70
88
|
else:
|
71
|
-
exif_tags = extract_exif_tags(
|
89
|
+
exif_tags = extract_exif_tags(image)
|
72
90
|
if exif_tags:
|
73
91
|
tag_name_width = max(map(len, exif_tags))
|
74
92
|
for tag_name, tag_value in exif_tags.items():
|
@@ -77,9 +95,9 @@ def run(args: argparse.Namespace) -> None:
|
|
77
95
|
print("No metadata found!")
|
78
96
|
|
79
97
|
|
80
|
-
def extract_exif_tags(
|
98
|
+
def extract_exif_tags(image: Image.Image, sort: bool = False) -> dict:
|
81
99
|
"""Extract Exif metadata from image."""
|
82
|
-
image
|
100
|
+
print(type(image))
|
83
101
|
exif = image._getexif()
|
84
102
|
log.debug(exif)
|
85
103
|
|
@@ -96,8 +114,14 @@ def extract_exif_tags(image_filename: str, sort: bool = False) -> dict:
|
|
96
114
|
return filtered_info
|
97
115
|
|
98
116
|
|
99
|
-
def
|
117
|
+
def datetime(image: Image.Image):
|
118
|
+
"""Extract datetime metadata."""
|
119
|
+
exif_tags = extract_exif_tags(image)
|
120
|
+
return exif_tags["DateTime"]
|
121
|
+
|
122
|
+
|
123
|
+
def camera_metadata(image: Image.Image):
|
100
124
|
"""Extract camera and model metadata."""
|
101
|
-
exif_tags = extract_exif_tags(
|
125
|
+
exif_tags = extract_exif_tags(image)
|
102
126
|
metadata = f'{exif_tags["Make"]} {exif_tags["Model"]}'
|
103
127
|
return metadata.strip()
|
@@ -40,6 +40,21 @@ def build_subparser(subparsers) -> None:
|
|
40
40
|
metavar="IMAGE_FILENAMES",
|
41
41
|
)
|
42
42
|
|
43
|
+
rotate_parser.add_argument(
|
44
|
+
"-r",
|
45
|
+
"--rotation",
|
46
|
+
type=int,
|
47
|
+
default=0,
|
48
|
+
help="Rotation angle in degrees (default: '%(default)s')",
|
49
|
+
)
|
50
|
+
|
51
|
+
rotate_parser.add_argument(
|
52
|
+
"-cw",
|
53
|
+
"--clockwise",
|
54
|
+
action="store_true",
|
55
|
+
help="Rotate clockwise (default: '%(default)s)",
|
56
|
+
)
|
57
|
+
|
43
58
|
|
44
59
|
def run(args: argparse.Namespace) -> None:
|
45
60
|
"""Run rotate subcommand.
|
@@ -52,10 +67,14 @@ def run(args: argparse.Namespace) -> None:
|
|
52
67
|
"""
|
53
68
|
log.debug(args)
|
54
69
|
|
70
|
+
rotation = args.rotation
|
71
|
+
if args.clockwise:
|
72
|
+
rotation = -rotation
|
73
|
+
|
55
74
|
for image_filename in args.image_filenames:
|
56
75
|
original_image = Image.open(image_filename)
|
57
76
|
rotated_image = original_image.rotate(
|
58
|
-
|
77
|
+
rotation,
|
59
78
|
expand=True,
|
60
79
|
)
|
61
80
|
save_image(args, rotated_image, image_filename, "rotate")
|
@@ -19,10 +19,10 @@ import argparse
|
|
19
19
|
import logging
|
20
20
|
import math
|
21
21
|
|
22
|
-
from PIL import Image, ImageColor, ImageDraw, ImageFont
|
22
|
+
from PIL import Image, ImageColor, ImageDraw, ImageFont, ImageSequence
|
23
23
|
|
24
24
|
from fotolab import save_image
|
25
|
-
from fotolab.info import
|
25
|
+
from fotolab.subcommands.info import camera_metadata
|
26
26
|
|
27
27
|
log = logging.getLogger(__name__)
|
28
28
|
|
@@ -139,7 +139,7 @@ def build_subparser(subparsers) -> None:
|
|
139
139
|
"-l",
|
140
140
|
"--lowercase",
|
141
141
|
default=True,
|
142
|
-
action=
|
142
|
+
action=argparse.BooleanOptionalAction,
|
143
143
|
dest="lowercase",
|
144
144
|
help="lowercase the watermark text",
|
145
145
|
)
|
@@ -157,13 +157,72 @@ def run(args: argparse.Namespace) -> None:
|
|
157
157
|
log.debug(args)
|
158
158
|
|
159
159
|
for image_filename in args.image_filenames:
|
160
|
-
|
161
|
-
|
160
|
+
image = Image.open(image_filename)
|
161
|
+
if image.format == "GIF":
|
162
|
+
watermark_gif_image(image, args)
|
163
|
+
else:
|
164
|
+
watermarked_image = watermark_non_gif_image(image, args)
|
165
|
+
save_image(args, watermarked_image, image_filename, "watermark")
|
166
|
+
|
167
|
+
|
168
|
+
def watermark_gif_image(original_image: Image.Image, args: argparse.Namespace):
|
169
|
+
"""Watermark the image."""
|
170
|
+
watermarked_image = original_image.copy()
|
171
|
+
|
172
|
+
frames = []
|
173
|
+
|
174
|
+
for frame in ImageSequence.Iterator(original_image):
|
175
|
+
frame = frame.convert("RGBA")
|
176
|
+
draw = ImageDraw.Draw(frame)
|
177
|
+
|
178
|
+
font = ImageFont.load_default(calc_font_size(original_image, args))
|
179
|
+
log.debug("default font: %s", " ".join(font.getname()))
|
180
|
+
|
181
|
+
text = args.text
|
182
|
+
if args.camera and camera_metadata(original_image):
|
183
|
+
text = camera_metadata(original_image)
|
184
|
+
|
185
|
+
if args.lowercase:
|
186
|
+
text = text.lower()
|
162
187
|
|
188
|
+
(left, top, right, bottom) = draw.textbbox(
|
189
|
+
xy=(0, 0), text=text, font=font
|
190
|
+
)
|
191
|
+
text_width = right - left
|
192
|
+
text_height = bottom - top
|
193
|
+
(position_x, position_y) = calc_position(
|
194
|
+
watermarked_image,
|
195
|
+
text_width,
|
196
|
+
text_height,
|
197
|
+
args.position,
|
198
|
+
calc_padding(original_image, args),
|
199
|
+
)
|
200
|
+
|
201
|
+
draw.text(
|
202
|
+
(position_x, position_y),
|
203
|
+
text,
|
204
|
+
font=font,
|
205
|
+
fill=(*ImageColor.getrgb(args.font_color), 128),
|
206
|
+
stroke_width=calc_font_outline_width(original_image, args),
|
207
|
+
stroke_fill=(*ImageColor.getrgb(args.outline_color), 128),
|
208
|
+
)
|
209
|
+
frames.append(frame)
|
210
|
+
|
211
|
+
frames[0].save(
|
212
|
+
"foo.gif",
|
213
|
+
format="GIF",
|
214
|
+
append_images=frames[1:],
|
215
|
+
save_all=True,
|
216
|
+
duration=original_image.info.get("duration", 100),
|
217
|
+
loop=original_image.info.get("loop", 0),
|
218
|
+
disposal=original_image.info.get("disposal", 2),
|
219
|
+
)
|
163
220
|
|
164
|
-
|
221
|
+
|
222
|
+
def watermark_non_gif_image(
|
223
|
+
original_image: Image.Image, args: argparse.Namespace
|
224
|
+
):
|
165
225
|
"""Watermark the image."""
|
166
|
-
original_image = Image.open(image_filename)
|
167
226
|
watermarked_image = original_image.copy()
|
168
227
|
|
169
228
|
draw = ImageDraw.Draw(watermarked_image)
|
@@ -172,8 +231,8 @@ def watermark_image(image_filename, args):
|
|
172
231
|
log.debug("default font: %s", " ".join(font.getname()))
|
173
232
|
|
174
233
|
text = args.text
|
175
|
-
if args.camera and camera_metadata(
|
176
|
-
text = camera_metadata(
|
234
|
+
if args.camera and camera_metadata(original_image):
|
235
|
+
text = camera_metadata(original_image)
|
177
236
|
|
178
237
|
if args.lowercase:
|
179
238
|
text = text.lower()
|
@@ -200,13 +259,6 @@ def watermark_image(image_filename, args):
|
|
200
259
|
return watermarked_image
|
201
260
|
|
202
261
|
|
203
|
-
def camera_metadata(image_filename):
|
204
|
-
"""Extract camera and model metadata."""
|
205
|
-
exif_tags = extract_exif_tags(image_filename)
|
206
|
-
metadata = f'{exif_tags["Make"]} {exif_tags["Model"]}'
|
207
|
-
return metadata.strip()
|
208
|
-
|
209
|
-
|
210
262
|
def calc_font_size(image, args) -> int:
|
211
263
|
"""Calculate the font size based on the width of the image."""
|
212
264
|
width, _height = image.size
|
@@ -244,19 +296,14 @@ def calc_padding(image, args) -> int:
|
|
244
296
|
|
245
297
|
def calc_position(image, text_width, text_height, position, padding) -> tuple:
|
246
298
|
"""Calculate the boundary coordinates of the watermark text."""
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
elif position == "bottom-right":
|
259
|
-
position_x = image.width - text_width - padding
|
260
|
-
position_y = image.height - text_height - padding
|
261
|
-
|
262
|
-
return (position_x, position_y)
|
299
|
+
positions = {
|
300
|
+
"top-left": (padding, padding),
|
301
|
+
"top-right": (image.width - text_width - padding, padding),
|
302
|
+
"bottom-left": (padding, image.height - text_height - padding),
|
303
|
+
"bottom-right": (
|
304
|
+
image.width - text_width - padding,
|
305
|
+
image.height - text_height - padding,
|
306
|
+
),
|
307
|
+
}
|
308
|
+
|
309
|
+
return positions.get(position, (0, 0))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fotolab
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.24.0
|
4
4
|
Summary: A console program that manipulate images.
|
5
5
|
Keywords: photography,photo
|
6
6
|
Author-email: Kian-Meng Ang <kianmeng@cpan.org>
|
@@ -61,7 +61,7 @@ fotolab -h
|
|
61
61
|
|
62
62
|
```console
|
63
63
|
usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-v] [-d] [-V]
|
64
|
-
{animate,auto,border,contrast,info,resize,rotate,
|
64
|
+
{animate,auto,border,contrast,env,info,montage,resize,rotate,sharpen,watermark} ...
|
65
65
|
|
66
66
|
A console program to manipulate photos.
|
67
67
|
|
@@ -70,19 +70,19 @@ changelog: https://github.com/kianmeng/fotolab/blob/master/CHANGELOG.md
|
|
70
70
|
issues: https://github.com/kianmeng/fotolab/issues
|
71
71
|
|
72
72
|
positional arguments:
|
73
|
-
{animate,auto,border,contrast,info,resize,rotate,
|
73
|
+
{animate,auto,border,contrast,env,info,montage,resize,rotate,sharpen,watermark}
|
74
74
|
sub-command help
|
75
75
|
animate animate an image
|
76
76
|
auto auto adjust (resize, contrast, and watermark) a photo
|
77
77
|
border add border to image
|
78
78
|
contrast contrast an image
|
79
|
+
env print environment information for bug reporting
|
79
80
|
info info an image
|
81
|
+
montage montage a list of image
|
80
82
|
resize resize an image
|
81
83
|
rotate rotate an image
|
82
|
-
montage montage a list of image
|
83
84
|
sharpen sharpen an image
|
84
85
|
watermark watermark an image
|
85
|
-
env print environment information for bug reporting
|
86
86
|
|
87
87
|
options:
|
88
88
|
-h, --help show this help message and exit
|
@@ -206,7 +206,7 @@ fotolab info -h
|
|
206
206
|
<!--help-info !-->
|
207
207
|
|
208
208
|
```console
|
209
|
-
usage: fotolab info [-h] [-s] IMAGE_FILENAME
|
209
|
+
usage: fotolab info [-h] [-s] [--camera] [--datetime] IMAGE_FILENAME
|
210
210
|
|
211
211
|
positional arguments:
|
212
212
|
IMAGE_FILENAME set the image filename
|
@@ -214,6 +214,8 @@ positional arguments:
|
|
214
214
|
options:
|
215
215
|
-h, --help show this help message and exit
|
216
216
|
-s, --sort show image info by sorted field name
|
217
|
+
--camera show the camera maker details
|
218
|
+
--datetime show the datetime
|
217
219
|
```
|
218
220
|
|
219
221
|
<!--help-info !-->
|
@@ -227,13 +229,17 @@ fotolab rotate -h
|
|
227
229
|
<!--help-rotate !-->
|
228
230
|
|
229
231
|
```console
|
230
|
-
usage: fotolab rotate [-h]
|
232
|
+
usage: fotolab rotate [-h] [-r ROTATION] [-cw]
|
233
|
+
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
231
234
|
|
232
235
|
positional arguments:
|
233
|
-
IMAGE_FILENAMES
|
236
|
+
IMAGE_FILENAMES set the image filenames
|
234
237
|
|
235
238
|
options:
|
236
|
-
-h, --help
|
239
|
+
-h, --help show this help message and exit
|
240
|
+
-r, --rotation ROTATION
|
241
|
+
Rotation angle in degrees (default: '0')
|
242
|
+
-cw, --clockwise Rotate clockwise (default: 'False)
|
237
243
|
```
|
238
244
|
|
239
245
|
<!--help-rotate !-->
|
@@ -326,7 +332,7 @@ usage: fotolab watermark [-h] [-t WATERMARK_TEXT]
|
|
326
332
|
[-p {top-left,top-right,bottom-left,bottom-right}]
|
327
333
|
[-pd PADDING] [-fs FONT_SIZE] [-fc FONT_COLOR]
|
328
334
|
[-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR] [--camera]
|
329
|
-
[-l]
|
335
|
+
[-l | --lowercase | --no-lowercase]
|
330
336
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
331
337
|
|
332
338
|
positional arguments:
|
@@ -354,7 +360,8 @@ options:
|
|
354
360
|
set the outline color of the watermark text (default:
|
355
361
|
'black')
|
356
362
|
--camera use camera metadata as watermark
|
357
|
-
-l, --lowercase
|
363
|
+
-l, --lowercase, --no-lowercase
|
364
|
+
lowercase the watermark text
|
358
365
|
```
|
359
366
|
|
360
367
|
<!--help-watermark !-->
|
@@ -0,0 +1,20 @@
|
|
1
|
+
fotolab/__init__.py,sha256=xMgr0qY4XC9waGeCumA3xk1SjuwsIC0tuMY3k_u0suU,2061
|
2
|
+
fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
|
3
|
+
fotolab/cli.py,sha256=vUS7eVcwEy2CWn4g5wTujLXS_GAzug9Np7j8-sM6GHU,4321
|
4
|
+
fotolab/subcommands/__init__.py,sha256=5ncuu_LxuWphjNohm32Z_lD0FmJPWrAynBzeza0lyCU,1124
|
5
|
+
fotolab/subcommands/animate.py,sha256=ejimhTozo9DN7BbqqcV4x8zLnanZRKq1pxBBFeOdr6Q,2967
|
6
|
+
fotolab/subcommands/auto.py,sha256=ljvC0Z88Dva18YHyn3auAjlvVHqGrxsky-HGXwaIMZo,2391
|
7
|
+
fotolab/subcommands/border.py,sha256=5ch2d7LVPhB2OFuuXSW5ci6Cn967CPDQu0qSfaO7uMg,3591
|
8
|
+
fotolab/subcommands/contrast.py,sha256=l7Bs5p8W8ypN9Cg3fFHnU-A20UwMKtjTiPk6D0PRwpM,2095
|
9
|
+
fotolab/subcommands/env.py,sha256=6vQDQ1sunJl2XBaSAHpLZUOiKiHy4STO45CMjXJd_Ow,1466
|
10
|
+
fotolab/subcommands/info.py,sha256=vDzomRfHOKCNk9TON5CX9UB_km6GYBJT_nkDcwtARVA,3330
|
11
|
+
fotolab/subcommands/montage.py,sha256=lUVY-zDSH7mwH-s34_XefdNp7CoDJHkwpbTUGiyJGgs,2037
|
12
|
+
fotolab/subcommands/resize.py,sha256=2bH1Kgoe_DqU8ozJ1E_oA6a9JPtuwIlo5a4sq_4Yles,5018
|
13
|
+
fotolab/subcommands/rotate.py,sha256=27Xrc8iV9n8WI6tOE-vBBMUeSYu2CtZAh-PGcF7JL-k,2144
|
14
|
+
fotolab/subcommands/sharpen.py,sha256=wUPtJdtB6mCRmcHrA0CoEVO0O0ROBJWhejTvUeL67QU,2655
|
15
|
+
fotolab/subcommands/watermark.py,sha256=5vsMDeJZhLT5qmftJQXY4jK2gtPQsbTYKXA6Ye2MqmA,8900
|
16
|
+
fotolab-0.24.0.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
|
17
|
+
fotolab-0.24.0.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
|
18
|
+
fotolab-0.24.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
19
|
+
fotolab-0.24.0.dist-info/METADATA,sha256=VH-jJMrow1yoLw1XXO4eVgl1putj9tJuLFd93Tg9MSE,10975
|
20
|
+
fotolab-0.24.0.dist-info/RECORD,,
|
fotolab-0.21.1.dist-info/RECORD
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
fotolab/__init__.py,sha256=fZZb0I229_RXcxunCTP3flULzE0p48prsOWsvTqLkyM,2061
|
2
|
-
fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
|
3
|
-
fotolab/animate.py,sha256=ejimhTozo9DN7BbqqcV4x8zLnanZRKq1pxBBFeOdr6Q,2967
|
4
|
-
fotolab/auto.py,sha256=l_-Kf5V5Anvwz1QV1ET-42YsDWEeHf_okHkXWOycWAI,2295
|
5
|
-
fotolab/border.py,sha256=5ch2d7LVPhB2OFuuXSW5ci6Cn967CPDQu0qSfaO7uMg,3591
|
6
|
-
fotolab/cli.py,sha256=FBFSeMNqcOiJ6MuAcy0qUvc9cscdFUG946HlWZXBPtY,4984
|
7
|
-
fotolab/contrast.py,sha256=l7Bs5p8W8ypN9Cg3fFHnU-A20UwMKtjTiPk6D0PRwpM,2095
|
8
|
-
fotolab/env.py,sha256=fzUoRWgYEiYJIWYEiiSLEb7dH_xVUOnhMpQgc1yjrTY,1457
|
9
|
-
fotolab/info.py,sha256=lY9n6HDnlDyRVDTRqYwzxm5xgPSyh0P8N3ybnnNtNtw,2892
|
10
|
-
fotolab/montage.py,sha256=lUVY-zDSH7mwH-s34_XefdNp7CoDJHkwpbTUGiyJGgs,2037
|
11
|
-
fotolab/resize.py,sha256=2bH1Kgoe_DqU8ozJ1E_oA6a9JPtuwIlo5a4sq_4Yles,5018
|
12
|
-
fotolab/rotate.py,sha256=l_vQgf0IcI8AR1TSVsk4PrMZtJ3j_wpU77rKiGJ-KTA,1715
|
13
|
-
fotolab/sharpen.py,sha256=wUPtJdtB6mCRmcHrA0CoEVO0O0ROBJWhejTvUeL67QU,2655
|
14
|
-
fotolab/watermark.py,sha256=-YzxABVT5KJM1GgYLP3Z8X9YPfQzncOA9YnRJgNN6nA,7457
|
15
|
-
fotolab-0.21.1.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
|
16
|
-
fotolab-0.21.1.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
|
17
|
-
fotolab-0.21.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
18
|
-
fotolab-0.21.1.dist-info/METADATA,sha256=hH4mutSmdcXzZmt204mH0EdmgErcY18WK8KR9wtjw5o,10600
|
19
|
-
fotolab-0.21.1.dist-info/RECORD,,
|
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
|