fotolab 0.16.17__py2.py3-none-any.whl → 0.18.1__py2.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/auto.py +2 -0
- fotolab/cli.py +2 -3
- fotolab/env.py +1 -3
- fotolab/info.py +25 -4
- fotolab/watermark.py +35 -3
- {fotolab-0.16.17.dist-info → fotolab-0.18.1.dist-info}/METADATA +5 -3
- fotolab-0.18.1.dist-info/RECORD +19 -0
- fotolab-0.16.17.dist-info/RECORD +0 -19
- {fotolab-0.16.17.dist-info → fotolab-0.18.1.dist-info}/LICENSE.md +0 -0
- {fotolab-0.16.17.dist-info → fotolab-0.18.1.dist-info}/WHEEL +0 -0
- {fotolab-0.16.17.dist-info → fotolab-0.18.1.dist-info}/entry_points.txt +0 -0
fotolab/__init__.py
CHANGED
fotolab/auto.py
CHANGED
@@ -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
|
fotolab/cli.py
CHANGED
@@ -132,7 +132,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
132
132
|
"-V",
|
133
133
|
"--version",
|
134
134
|
action="version",
|
135
|
-
version=f"
|
135
|
+
version=f"%(prog)s {__version__}",
|
136
136
|
)
|
137
137
|
|
138
138
|
subparsers = parser.add_subparsers(help="sub-command help")
|
@@ -154,7 +154,6 @@ def build_parser() -> argparse.ArgumentParser:
|
|
154
154
|
def main(args: Optional[Sequence[str]] = None) -> None:
|
155
155
|
"""Run the main program flow."""
|
156
156
|
args = args or sys.argv[1:]
|
157
|
-
parsed_args = argparse.Namespace(debug=True)
|
158
157
|
log.debug(args)
|
159
158
|
|
160
159
|
try:
|
@@ -175,7 +174,7 @@ def main(args: Optional[Sequence[str]] = None) -> None:
|
|
175
174
|
log.error(
|
176
175
|
"error: %s",
|
177
176
|
getattr(error, "message", str(error)),
|
178
|
-
exc_info=
|
177
|
+
exc_info=("-d" in args or "--debug" in args),
|
179
178
|
)
|
180
179
|
|
181
180
|
raise SystemExit(1) from None
|
fotolab/env.py
CHANGED
@@ -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__}",
|
fotolab/info.py
CHANGED
@@ -37,6 +37,15 @@ def build_subparser(subparsers) -> None:
|
|
37
37
|
metavar="IMAGE_FILENAME",
|
38
38
|
)
|
39
39
|
|
40
|
+
info_parser.add_argument(
|
41
|
+
"-s",
|
42
|
+
"--sort",
|
43
|
+
default=False,
|
44
|
+
action="store_true",
|
45
|
+
dest="sort",
|
46
|
+
help="show image info by sorted field name",
|
47
|
+
)
|
48
|
+
|
40
49
|
|
41
50
|
def run(args: argparse.Namespace) -> None:
|
42
51
|
"""Run info subcommand.
|
@@ -49,10 +58,22 @@ def run(args: argparse.Namespace) -> None:
|
|
49
58
|
"""
|
50
59
|
log.debug(args)
|
51
60
|
|
52
|
-
|
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)
|
53
70
|
exif = image._getexif()
|
54
71
|
info = {ExifTags.TAGS.get(tag_id): exif.get(tag_id) for tag_id in exif}
|
55
72
|
|
56
|
-
|
57
|
-
|
58
|
-
|
73
|
+
filtered_info = {
|
74
|
+
key: value for key, value in info.items() if key is not None
|
75
|
+
}
|
76
|
+
if sort:
|
77
|
+
filtered_info = dict(sorted(filtered_info.items()))
|
78
|
+
|
79
|
+
return filtered_info
|
fotolab/watermark.py
CHANGED
@@ -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
|
@@ -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>
|
@@ -210,13 +210,14 @@ fotolab info -h
|
|
210
210
|
<!--help-info !-->
|
211
211
|
|
212
212
|
```console
|
213
|
-
usage: fotolab info [-h] IMAGE_FILENAME
|
213
|
+
usage: fotolab info [-h] [-s] IMAGE_FILENAME
|
214
214
|
|
215
215
|
positional arguments:
|
216
216
|
IMAGE_FILENAME set the image filename
|
217
217
|
|
218
218
|
options:
|
219
219
|
-h, --help show this help message and exit
|
220
|
+
-s, --sort show image info by sorted field name
|
220
221
|
```
|
221
222
|
|
222
223
|
<!--help-info !-->
|
@@ -327,7 +328,7 @@ fotolab watermark -h
|
|
327
328
|
usage: fotolab watermark [-h] [-t WATERMARK_TEXT]
|
328
329
|
[-p {top-left,top-right,bottom-left,bottom-right}]
|
329
330
|
[-pd PADDING] [-fs FONT_SIZE] [-fc FONT_COLOR]
|
330
|
-
[-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR]
|
331
|
+
[-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR] [--camera]
|
331
332
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
332
333
|
|
333
334
|
positional arguments:
|
@@ -354,6 +355,7 @@ options:
|
|
354
355
|
-oc OUTLINE_COLOR, --outline-color OUTLINE_COLOR
|
355
356
|
set the outline color of the watermark text (default:
|
356
357
|
'black')
|
358
|
+
--camera use camera metadata as watermark
|
357
359
|
```
|
358
360
|
|
359
361
|
<!--help-watermark !-->
|
@@ -0,0 +1,19 @@
|
|
1
|
+
fotolab/__init__.py,sha256=XvtFiEJ4C6qZB4LfH3agFbx98-wD8x7tEH50NSKU8iE,2061
|
2
|
+
fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
|
3
|
+
fotolab/animate.py,sha256=ejimhTozo9DN7BbqqcV4x8zLnanZRKq1pxBBFeOdr6Q,2967
|
4
|
+
fotolab/auto.py,sha256=SmEEbTXFiP1BiqaAFxPNTcGguVSUbAmLbSuWf_LgsBY,2270
|
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=kbKMIqdkK-Wn2lWLvnFL_Efc45K9KCaR_euTv9LIGzw,2256
|
10
|
+
fotolab/montage.py,sha256=lUVY-zDSH7mwH-s34_XefdNp7CoDJHkwpbTUGiyJGgs,2037
|
11
|
+
fotolab/resize.py,sha256=cvPfh4wUfydM23Do7VnP6Bx2EqMHKfYFYrpiNhyWzCU,3259
|
12
|
+
fotolab/rotate.py,sha256=l_vQgf0IcI8AR1TSVsk4PrMZtJ3j_wpU77rKiGJ-KTA,1715
|
13
|
+
fotolab/sharpen.py,sha256=wUPtJdtB6mCRmcHrA0CoEVO0O0ROBJWhejTvUeL67QU,2655
|
14
|
+
fotolab/watermark.py,sha256=WlZF6aV1iR6Bh6Y3pXLvCFyLkpo-IHyKbS4UlUcvhNU,7382
|
15
|
+
fotolab-0.18.1.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
|
16
|
+
fotolab-0.18.1.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
|
17
|
+
fotolab-0.18.1.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
|
18
|
+
fotolab-0.18.1.dist-info/METADATA,sha256=LdK1HE2kcKwjLyEeci6Rr5ax_0I-Buhvl1LrY6Z3LsY,10676
|
19
|
+
fotolab-0.18.1.dist-info/RECORD,,
|
fotolab-0.16.17.dist-info/RECORD
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
fotolab/__init__.py,sha256=qP6gvbqFk1sDJ5TBEb93V94RXlDx6CLNo3Td6D-12nQ,2062
|
2
|
-
fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
|
3
|
-
fotolab/animate.py,sha256=ejimhTozo9DN7BbqqcV4x8zLnanZRKq1pxBBFeOdr6Q,2967
|
4
|
-
fotolab/auto.py,sha256=1Toxe8pA_tq15g1-imMFuHf1L94Ac7EthPTu7E8SAzE,2217
|
5
|
-
fotolab/border.py,sha256=5ch2d7LVPhB2OFuuXSW5ci6Cn967CPDQu0qSfaO7uMg,3591
|
6
|
-
fotolab/cli.py,sha256=XENJqvvMxOTHVYfch8gZJhkzGxhex0LUAe75ISNNWPo,5032
|
7
|
-
fotolab/contrast.py,sha256=l7Bs5p8W8ypN9Cg3fFHnU-A20UwMKtjTiPk6D0PRwpM,2095
|
8
|
-
fotolab/env.py,sha256=u63uuy1LG9bXy5Q-x1JfPiQaGCGwTYy-GJmWtzSkeFc,1477
|
9
|
-
fotolab/info.py,sha256=DawXTQJiQDBwy0Ml5Ysk8MvKga3ikp_aIw73AR3LdZo,1687
|
10
|
-
fotolab/montage.py,sha256=lUVY-zDSH7mwH-s34_XefdNp7CoDJHkwpbTUGiyJGgs,2037
|
11
|
-
fotolab/resize.py,sha256=cvPfh4wUfydM23Do7VnP6Bx2EqMHKfYFYrpiNhyWzCU,3259
|
12
|
-
fotolab/rotate.py,sha256=l_vQgf0IcI8AR1TSVsk4PrMZtJ3j_wpU77rKiGJ-KTA,1715
|
13
|
-
fotolab/sharpen.py,sha256=wUPtJdtB6mCRmcHrA0CoEVO0O0ROBJWhejTvUeL67QU,2655
|
14
|
-
fotolab/watermark.py,sha256=JnCIB--WZ2COG1BNrFY14GaWznz7BqBlwOVz4uW8H3Q,6546
|
15
|
-
fotolab-0.16.17.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
|
16
|
-
fotolab-0.16.17.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
|
17
|
-
fotolab-0.16.17.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
|
18
|
-
fotolab-0.16.17.dist-info/METADATA,sha256=f8SorvhIK70fPa4tyenLO4Nr6RN44gRtfu8wHQJaXk8,10549
|
19
|
-
fotolab-0.16.17.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|