fotolab 0.13.0__py2.py3-none-any.whl → 0.16.3__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 +3 -3
- fotolab/animate.py +114 -0
- fotolab/cli.py +16 -0
- fotolab/resize.py +39 -5
- fotolab/rotate.py +61 -0
- fotolab/sharpen.py +3 -3
- fotolab/watermark.py +46 -7
- {fotolab-0.13.0.dist-info → fotolab-0.16.3.dist-info}/METADATA +46 -6
- fotolab-0.16.3.dist-info/RECORD +19 -0
- fotolab-0.13.0.dist-info/RECORD +0 -17
- {fotolab-0.13.0.dist-info → fotolab-0.16.3.dist-info}/LICENSE.md +0 -0
- {fotolab-0.13.0.dist-info → fotolab-0.16.3.dist-info}/WHEEL +0 -0
- {fotolab-0.13.0.dist-info → fotolab-0.16.3.dist-info}/entry_points.txt +0 -0
fotolab/__init__.py
CHANGED
@@ -21,7 +21,7 @@ import subprocess
|
|
21
21
|
import sys
|
22
22
|
from pathlib import Path
|
23
23
|
|
24
|
-
__version__ = "0.
|
24
|
+
__version__ = "0.16.3"
|
25
25
|
|
26
26
|
log = logging.getLogger(__name__)
|
27
27
|
|
@@ -48,7 +48,7 @@ def save_image(args, new_image, output_filename, subcommand):
|
|
48
48
|
)
|
49
49
|
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
50
50
|
|
51
|
-
log.info("%s image: %s", subcommand, new_filename)
|
51
|
+
log.info("%s image: %s", subcommand, new_filename.resolve())
|
52
52
|
new_image.save(new_filename)
|
53
53
|
|
54
54
|
if args.open:
|
@@ -64,4 +64,4 @@ def _open_image(filename):
|
|
64
64
|
elif sys.platform == "windows":
|
65
65
|
os.startfile(filename)
|
66
66
|
|
67
|
-
log.info("open image: %s
|
67
|
+
log.info("open image: %s", filename.resolve())
|
fotolab/animate.py
ADDED
@@ -0,0 +1,114 @@
|
|
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
|
+
"""Animate subcommand."""
|
17
|
+
|
18
|
+
import argparse
|
19
|
+
import logging
|
20
|
+
from pathlib import Path
|
21
|
+
|
22
|
+
from PIL import Image
|
23
|
+
|
24
|
+
from fotolab import _open_image
|
25
|
+
|
26
|
+
log = logging.getLogger(__name__)
|
27
|
+
|
28
|
+
|
29
|
+
def build_subparser(subparsers) -> None:
|
30
|
+
"""Build the subparser."""
|
31
|
+
animate_parser = subparsers.add_parser("animate", help="animate an image")
|
32
|
+
|
33
|
+
animate_parser.set_defaults(func=run)
|
34
|
+
|
35
|
+
animate_parser.add_argument(
|
36
|
+
dest="image_filenames",
|
37
|
+
help="set the image filenames",
|
38
|
+
nargs="+",
|
39
|
+
type=str,
|
40
|
+
default=None,
|
41
|
+
metavar="IMAGE_FILENAMES",
|
42
|
+
)
|
43
|
+
|
44
|
+
animate_parser.add_argument(
|
45
|
+
"-f",
|
46
|
+
"--format",
|
47
|
+
dest="format",
|
48
|
+
type=str,
|
49
|
+
choices=["gif", "webp"],
|
50
|
+
default="gif",
|
51
|
+
help="set the image format (default: '%(default)s')",
|
52
|
+
metavar="FORMAT",
|
53
|
+
)
|
54
|
+
|
55
|
+
animate_parser.add_argument(
|
56
|
+
"-d",
|
57
|
+
"--duration",
|
58
|
+
dest="duration",
|
59
|
+
type=int,
|
60
|
+
default=2500,
|
61
|
+
help="set the duration in milliseconds (default: '%(default)s')",
|
62
|
+
metavar="DURATION",
|
63
|
+
)
|
64
|
+
|
65
|
+
animate_parser.add_argument(
|
66
|
+
"-l",
|
67
|
+
"--loop",
|
68
|
+
dest="loop",
|
69
|
+
type=int,
|
70
|
+
default=0,
|
71
|
+
help="set the loop cycle (default: '%(default)s')",
|
72
|
+
metavar="LOOP",
|
73
|
+
)
|
74
|
+
|
75
|
+
|
76
|
+
def run(args: argparse.Namespace) -> None:
|
77
|
+
"""Run animate subcommand.
|
78
|
+
|
79
|
+
Args:
|
80
|
+
config (argparse.Namespace): Config from command line arguments
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
None
|
84
|
+
"""
|
85
|
+
log.debug(args)
|
86
|
+
|
87
|
+
first_image = args.image_filenames[0]
|
88
|
+
animated_image = Image.open(first_image)
|
89
|
+
|
90
|
+
append_images = []
|
91
|
+
for image_filename in args.image_filenames[1:]:
|
92
|
+
append_images.append(Image.open(image_filename))
|
93
|
+
|
94
|
+
image_file = Path(first_image)
|
95
|
+
new_filename = Path(
|
96
|
+
args.output_dir,
|
97
|
+
image_file.with_name(f"animate_{image_file.stem}.{args.format}"),
|
98
|
+
)
|
99
|
+
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
100
|
+
|
101
|
+
log.info("animate image: %s", new_filename)
|
102
|
+
|
103
|
+
animated_image.save(
|
104
|
+
new_filename,
|
105
|
+
format=args.format,
|
106
|
+
append_images=append_images,
|
107
|
+
save_all=True,
|
108
|
+
duration=args.duration,
|
109
|
+
loop=args.loop,
|
110
|
+
optimize=True,
|
111
|
+
)
|
112
|
+
|
113
|
+
if args.open:
|
114
|
+
_open_image(new_filename)
|
fotolab/cli.py
CHANGED
@@ -25,6 +25,7 @@ import logging
|
|
25
25
|
import sys
|
26
26
|
from typing import Dict, Optional, Sequence
|
27
27
|
|
28
|
+
import fotolab.animate
|
28
29
|
import fotolab.auto
|
29
30
|
import fotolab.border
|
30
31
|
import fotolab.contrast
|
@@ -32,6 +33,7 @@ import fotolab.env
|
|
32
33
|
import fotolab.info
|
33
34
|
import fotolab.montage
|
34
35
|
import fotolab.resize
|
36
|
+
import fotolab.rotate
|
35
37
|
import fotolab.sharpen
|
36
38
|
import fotolab.watermark
|
37
39
|
from fotolab import __version__
|
@@ -41,6 +43,9 @@ log = logging.getLogger(__name__)
|
|
41
43
|
|
42
44
|
def setup_logging(args: argparse.Namespace) -> None:
|
43
45
|
"""Set up logging by level."""
|
46
|
+
if args.verbose == 0:
|
47
|
+
logging.getLogger("PIL").setLevel(logging.ERROR)
|
48
|
+
|
44
49
|
if args.quiet:
|
45
50
|
logging.disable(logging.NOTSET)
|
46
51
|
else:
|
@@ -104,6 +109,15 @@ def build_parser() -> argparse.ArgumentParser:
|
|
104
109
|
help="suppress all logging",
|
105
110
|
)
|
106
111
|
|
112
|
+
parser.add_argument(
|
113
|
+
"-v",
|
114
|
+
"--verbose",
|
115
|
+
default=0,
|
116
|
+
action="count",
|
117
|
+
dest="verbose",
|
118
|
+
help="show verbosity of debugging log, use -vv, -vvv for more details",
|
119
|
+
)
|
120
|
+
|
107
121
|
parser.add_argument(
|
108
122
|
"-d",
|
109
123
|
"--debug",
|
@@ -121,11 +135,13 @@ def build_parser() -> argparse.ArgumentParser:
|
|
121
135
|
)
|
122
136
|
|
123
137
|
subparsers = parser.add_subparsers(help="sub-command help")
|
138
|
+
fotolab.animate.build_subparser(subparsers)
|
124
139
|
fotolab.auto.build_subparser(subparsers)
|
125
140
|
fotolab.border.build_subparser(subparsers)
|
126
141
|
fotolab.contrast.build_subparser(subparsers)
|
127
142
|
fotolab.info.build_subparser(subparsers)
|
128
143
|
fotolab.resize.build_subparser(subparsers)
|
144
|
+
fotolab.rotate.build_subparser(subparsers)
|
129
145
|
fotolab.montage.build_subparser(subparsers)
|
130
146
|
fotolab.sharpen.build_subparser(subparsers)
|
131
147
|
fotolab.watermark.build_subparser(subparsers)
|
fotolab/resize.py
CHANGED
@@ -17,6 +17,7 @@
|
|
17
17
|
|
18
18
|
import argparse
|
19
19
|
import logging
|
20
|
+
import math
|
20
21
|
|
21
22
|
from PIL import Image
|
22
23
|
|
@@ -24,6 +25,9 @@ from fotolab import save_image
|
|
24
25
|
|
25
26
|
log = logging.getLogger(__name__)
|
26
27
|
|
28
|
+
DEFAULT_WIDTH = 600
|
29
|
+
DEFAULT_HEIGHT = 277
|
30
|
+
|
27
31
|
|
28
32
|
def build_subparser(subparsers) -> None:
|
29
33
|
"""Build the subparser."""
|
@@ -40,23 +44,25 @@ def build_subparser(subparsers) -> None:
|
|
40
44
|
metavar="IMAGE_FILENAMES",
|
41
45
|
)
|
42
46
|
|
43
|
-
resize_parser.
|
47
|
+
group = resize_parser.add_mutually_exclusive_group(required=False)
|
48
|
+
|
49
|
+
group.add_argument(
|
44
50
|
"-wh",
|
45
51
|
"--width",
|
46
52
|
dest="width",
|
47
53
|
help="set the width of the image (default: '%(default)s')",
|
48
54
|
type=int,
|
49
|
-
default=
|
55
|
+
default=DEFAULT_WIDTH,
|
50
56
|
metavar="WIDTH",
|
51
57
|
)
|
52
58
|
|
53
|
-
|
59
|
+
group.add_argument(
|
54
60
|
"-ht",
|
55
61
|
"--height",
|
56
62
|
dest="height",
|
57
63
|
help="set the height of the image (default: '%(default)s')",
|
58
64
|
type=int,
|
59
|
-
default=
|
65
|
+
default=DEFAULT_HEIGHT,
|
60
66
|
metavar="HEIGHT",
|
61
67
|
)
|
62
68
|
|
@@ -74,9 +80,37 @@ def run(args: argparse.Namespace) -> None:
|
|
74
80
|
|
75
81
|
for image_filename in args.image_filenames:
|
76
82
|
original_image = Image.open(image_filename)
|
83
|
+
|
84
|
+
new_width, new_height = _calc_new_image_dimension(original_image, args)
|
77
85
|
resized_image = original_image.copy()
|
78
86
|
resized_image = resized_image.resize(
|
79
|
-
(
|
87
|
+
(new_width, new_height), Image.Resampling.LANCZOS
|
80
88
|
)
|
81
89
|
|
82
90
|
save_image(args, resized_image, image_filename, "resize")
|
91
|
+
|
92
|
+
|
93
|
+
def _calc_new_image_dimension(image, args) -> tuple:
|
94
|
+
new_width = args.width
|
95
|
+
new_height = args.height
|
96
|
+
|
97
|
+
old_width, old_height = image.size
|
98
|
+
log.debug("old image dimension: %d x %d", old_width, old_height)
|
99
|
+
|
100
|
+
if args.width != DEFAULT_WIDTH:
|
101
|
+
aspect_ratio = old_height / old_width
|
102
|
+
log.debug("aspect ratio: %f", aspect_ratio)
|
103
|
+
|
104
|
+
new_height = math.ceil(args.width * aspect_ratio)
|
105
|
+
log.debug("new height: %d", new_height)
|
106
|
+
|
107
|
+
if args.height != DEFAULT_HEIGHT:
|
108
|
+
aspect_ratio = old_width / old_height
|
109
|
+
log.debug("aspect ratio: %f", aspect_ratio)
|
110
|
+
|
111
|
+
new_width = math.floor(args.height * aspect_ratio)
|
112
|
+
log.debug("new width: %d", new_width)
|
113
|
+
|
114
|
+
log.debug("new image dimension: %d x %d", new_width, new_height)
|
115
|
+
|
116
|
+
return (new_width, new_height)
|
fotolab/rotate.py
ADDED
@@ -0,0 +1,61 @@
|
|
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
|
+
"""Rotate subcommand."""
|
17
|
+
|
18
|
+
import argparse
|
19
|
+
import logging
|
20
|
+
|
21
|
+
from PIL import Image
|
22
|
+
|
23
|
+
from fotolab import save_image
|
24
|
+
|
25
|
+
log = logging.getLogger(__name__)
|
26
|
+
|
27
|
+
|
28
|
+
def build_subparser(subparsers) -> None:
|
29
|
+
"""Build the subparser."""
|
30
|
+
rotate_parser = subparsers.add_parser("rotate", help="rotate an image")
|
31
|
+
|
32
|
+
rotate_parser.set_defaults(func=run)
|
33
|
+
|
34
|
+
rotate_parser.add_argument(
|
35
|
+
dest="image_filenames",
|
36
|
+
help="set the image filenames",
|
37
|
+
nargs="+",
|
38
|
+
type=str,
|
39
|
+
default=None,
|
40
|
+
metavar="IMAGE_FILENAMES",
|
41
|
+
)
|
42
|
+
|
43
|
+
|
44
|
+
def run(args: argparse.Namespace) -> None:
|
45
|
+
"""Run rotate subcommand.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
config (argparse.Namespace): Config from command line arguments
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
None
|
52
|
+
"""
|
53
|
+
log.debug(args)
|
54
|
+
|
55
|
+
for image_filename in args.image_filenames:
|
56
|
+
original_image = Image.open(image_filename)
|
57
|
+
rotated_image = original_image.rotate(
|
58
|
+
180,
|
59
|
+
expand=True,
|
60
|
+
)
|
61
|
+
save_image(args, rotated_image, image_filename, "rotate")
|
fotolab/sharpen.py
CHANGED
@@ -44,7 +44,7 @@ def build_subparser(subparsers) -> None:
|
|
44
44
|
"-r",
|
45
45
|
"--radius",
|
46
46
|
dest="radius",
|
47
|
-
type=
|
47
|
+
type=int,
|
48
48
|
default=1,
|
49
49
|
help="set the radius or size of edges (default: '%(default)s')",
|
50
50
|
metavar="RADIUS",
|
@@ -54,7 +54,7 @@ def build_subparser(subparsers) -> None:
|
|
54
54
|
"-p",
|
55
55
|
"--percent",
|
56
56
|
dest="percent",
|
57
|
-
type=
|
57
|
+
type=int,
|
58
58
|
default=100,
|
59
59
|
help=(
|
60
60
|
"set the amount of overall strength of sharpening effect "
|
@@ -67,7 +67,7 @@ def build_subparser(subparsers) -> None:
|
|
67
67
|
"-t",
|
68
68
|
"--threshold",
|
69
69
|
dest="threshold",
|
70
|
-
type=
|
70
|
+
type=int,
|
71
71
|
default=3,
|
72
72
|
help=(
|
73
73
|
"set the minimum brightness changed to be sharpened "
|
fotolab/watermark.py
CHANGED
@@ -17,6 +17,7 @@
|
|
17
17
|
|
18
18
|
import argparse
|
19
19
|
import logging
|
20
|
+
import math
|
20
21
|
|
21
22
|
from PIL import Image, ImageColor, ImageDraw, ImageFont
|
22
23
|
|
@@ -24,6 +25,9 @@ from fotolab import save_image
|
|
24
25
|
|
25
26
|
log = logging.getLogger(__name__)
|
26
27
|
|
28
|
+
FONT_SIZE_ASPECT_RATIO = 12 / 600
|
29
|
+
FONT_PADDING_ASPECT_RATIO = 15 / 600
|
30
|
+
FONT_OUTLINE_WIDTH_ASPECT_RATIO = 2 / 600
|
27
31
|
POSITIONS = ["top-left", "top-right", "bottom-left", "bottom-right"]
|
28
32
|
|
29
33
|
|
@@ -140,19 +144,21 @@ def run(args: argparse.Namespace) -> None:
|
|
140
144
|
|
141
145
|
draw = ImageDraw.Draw(watermarked_image)
|
142
146
|
|
143
|
-
font = ImageFont.truetype(
|
147
|
+
font = ImageFont.truetype(
|
148
|
+
"arial.ttf", calc_font_size(original_image, args)
|
149
|
+
)
|
144
150
|
|
145
151
|
(left, top, right, bottom) = draw.textbbox(
|
146
152
|
xy=(0, 0), text=args.text, font=font
|
147
153
|
)
|
148
154
|
text_width = right - left
|
149
155
|
text_height = bottom - top
|
150
|
-
(position_x, position_y) =
|
156
|
+
(position_x, position_y) = calc_position(
|
151
157
|
watermarked_image,
|
152
158
|
text_width,
|
153
159
|
text_height,
|
154
160
|
args.position,
|
155
|
-
args
|
161
|
+
calc_padding(original_image, args),
|
156
162
|
)
|
157
163
|
|
158
164
|
draw.text(
|
@@ -160,16 +166,49 @@ def run(args: argparse.Namespace) -> None:
|
|
160
166
|
args.text,
|
161
167
|
font=font,
|
162
168
|
fill=(*ImageColor.getrgb(args.font_color), 128),
|
163
|
-
stroke_width=args
|
169
|
+
stroke_width=calc_font_outline_width(original_image, args),
|
164
170
|
stroke_fill=(*ImageColor.getrgb(args.outline_color), 128),
|
165
171
|
)
|
166
172
|
|
167
173
|
save_image(args, watermarked_image, image_filename, "watermark")
|
168
174
|
|
169
175
|
|
170
|
-
def
|
171
|
-
|
172
|
-
|
176
|
+
def calc_font_size(image, args) -> int:
|
177
|
+
"""Calculate the font size based on the width of the image."""
|
178
|
+
width, _height = image.size
|
179
|
+
new_font_size = args.font_size
|
180
|
+
if width > 600:
|
181
|
+
new_font_size = math.floor(FONT_SIZE_ASPECT_RATIO * width)
|
182
|
+
|
183
|
+
log.debug("new font size: %d", new_font_size)
|
184
|
+
return new_font_size
|
185
|
+
|
186
|
+
|
187
|
+
def calc_font_outline_width(image, args) -> int:
|
188
|
+
"""Calculate the font padding based on the width of the image."""
|
189
|
+
width, _height = image.size
|
190
|
+
new_font_outline_width = args.outline_width
|
191
|
+
if width > 600:
|
192
|
+
new_font_outline_width = math.floor(
|
193
|
+
FONT_OUTLINE_WIDTH_ASPECT_RATIO * width
|
194
|
+
)
|
195
|
+
|
196
|
+
log.debug("new font outline width: %d", new_font_outline_width)
|
197
|
+
return new_font_outline_width
|
198
|
+
|
199
|
+
|
200
|
+
def calc_padding(image, args) -> int:
|
201
|
+
"""Calculate the font padding based on the width of the image."""
|
202
|
+
width, _height = image.size
|
203
|
+
new_padding = args.padding
|
204
|
+
if width > 600:
|
205
|
+
new_padding = math.floor(FONT_PADDING_ASPECT_RATIO * width)
|
206
|
+
|
207
|
+
log.debug("new padding: %d", new_padding)
|
208
|
+
return new_padding
|
209
|
+
|
210
|
+
|
211
|
+
def calc_position(image, text_width, text_height, position, padding) -> tuple:
|
173
212
|
"""Calculate the boundary coordinates of the watermark text."""
|
174
213
|
if position == "top-left":
|
175
214
|
position_x = 0 + padding
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fotolab
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.16.3
|
4
4
|
Summary: A console program that manipulate images.
|
5
5
|
Keywords: photography,photo
|
6
6
|
Author-email: Kian-Meng Ang <kianmeng@cpan.org>
|
@@ -57,8 +57,8 @@ fotolab -h
|
|
57
57
|
```
|
58
58
|
|
59
59
|
```console
|
60
|
-
usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-d] [-V]
|
61
|
-
{auto,border,contrast,info,resize,montage,sharpen,watermark,env}
|
60
|
+
usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-v] [-d] [-V]
|
61
|
+
{animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
|
62
62
|
...
|
63
63
|
|
64
64
|
A console program to manipulate photos.
|
@@ -68,13 +68,15 @@ A console program to manipulate photos.
|
|
68
68
|
issues: https://github.com/kianmeng/fotolab/issues
|
69
69
|
|
70
70
|
positional arguments:
|
71
|
-
{auto,border,contrast,info,resize,montage,sharpen,watermark,env}
|
71
|
+
{animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
|
72
72
|
sub-command help
|
73
|
+
animate animate an image
|
73
74
|
auto auto adjust (resize, contrast, and watermark) a photo
|
74
75
|
border add border to image
|
75
76
|
contrast contrast an image
|
76
77
|
info info an image
|
77
78
|
resize resize an image
|
79
|
+
rotate rotate an image
|
78
80
|
montage montage a list of image
|
79
81
|
sharpen sharpen an image
|
80
82
|
watermark watermark an image
|
@@ -87,10 +89,33 @@ optional arguments:
|
|
87
89
|
-od OUTPUT_DIR, --output-dir OUTPUT_DIR
|
88
90
|
set default output folder (default: 'output')
|
89
91
|
-q, --quiet suppress all logging
|
92
|
+
-v, --verbose show verbosity of debugging log, use -vv, -vvv for more details
|
90
93
|
-d, --debug show debugging log and stacktrace
|
91
94
|
-V, --version show program's version number and exit
|
92
95
|
```
|
93
96
|
|
97
|
+
### fotolab animate
|
98
|
+
|
99
|
+
```console
|
100
|
+
fotolab animate -h
|
101
|
+
```
|
102
|
+
|
103
|
+
```console
|
104
|
+
usage: fotolab animate [-h] [-f FORMAT] [-d DURATION] [-l LOOP]
|
105
|
+
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
106
|
+
|
107
|
+
positional arguments:
|
108
|
+
IMAGE_FILENAMES set the image filenames
|
109
|
+
|
110
|
+
optional arguments:
|
111
|
+
-h, --help show this help message and exit
|
112
|
+
-f FORMAT, --format FORMAT
|
113
|
+
set the image format (default: 'gif')
|
114
|
+
-d DURATION, --duration DURATION
|
115
|
+
set the duration in milliseconds (default: '2500')
|
116
|
+
-l LOOP, --loop LOOP set the loop cycle (default: '0')
|
117
|
+
```
|
118
|
+
|
94
119
|
### fotolab auto
|
95
120
|
|
96
121
|
```console
|
@@ -172,6 +197,22 @@ optional arguments:
|
|
172
197
|
-h, --help show this help message and exit
|
173
198
|
```
|
174
199
|
|
200
|
+
### fotolab rotate
|
201
|
+
|
202
|
+
```console
|
203
|
+
fotolab rotate -h
|
204
|
+
```
|
205
|
+
|
206
|
+
```console
|
207
|
+
usage: fotolab rotate [-h] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
208
|
+
|
209
|
+
positional arguments:
|
210
|
+
IMAGE_FILENAMES set the image filenames
|
211
|
+
|
212
|
+
optional arguments:
|
213
|
+
-h, --help show this help message and exit
|
214
|
+
```
|
215
|
+
|
175
216
|
### fotolab montage
|
176
217
|
|
177
218
|
```console
|
@@ -179,7 +220,6 @@ fotolab montage -h
|
|
179
220
|
```
|
180
221
|
|
181
222
|
```console
|
182
|
-
|
183
223
|
usage: fotolab montage [-h] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
184
224
|
|
185
225
|
positional arguments:
|
@@ -196,7 +236,7 @@ fotolab resize -h
|
|
196
236
|
```
|
197
237
|
|
198
238
|
```console
|
199
|
-
usage: fotolab resize [-h] [-wh WIDTH
|
239
|
+
usage: fotolab resize [-h] [-wh WIDTH | -ht HEIGHT]
|
200
240
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
201
241
|
|
202
242
|
positional arguments:
|
@@ -0,0 +1,19 @@
|
|
1
|
+
fotolab/__init__.py,sha256=_g6Bhn9-dug7d9e9oOkmCaQzvI5-B9_kCpKESDGmcJ8,2061
|
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=YudfGpAdd7FlNk9GOoJvPuBOURRBqc-lzQz3cxlCH20,5008
|
7
|
+
fotolab/contrast.py,sha256=l7Bs5p8W8ypN9Cg3fFHnU-A20UwMKtjTiPk6D0PRwpM,2095
|
8
|
+
fotolab/env.py,sha256=NTTvfISWBBfIw5opWrUfg0BtkaAtdUtcISBAJC2gVUk,1449
|
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=3yHqtrh6WtFcGArgrpKAL6849Y2R1Fk-g3FeKdejrz0,6513
|
15
|
+
fotolab-0.16.3.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
|
16
|
+
fotolab-0.16.3.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
|
17
|
+
fotolab-0.16.3.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
|
18
|
+
fotolab-0.16.3.dist-info/METADATA,sha256=Df4Afp009m7123lBt6H4rBQ3bvBstFPi7N3uPH2BeA8,10153
|
19
|
+
fotolab-0.16.3.dist-info/RECORD,,
|
fotolab-0.13.0.dist-info/RECORD
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
fotolab/__init__.py,sha256=Z3guoQD823MHOmrtHNE9W0RnI6neYdRWNCv7QTxQb6s,2074
|
2
|
-
fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
|
3
|
-
fotolab/auto.py,sha256=1Toxe8pA_tq15g1-imMFuHf1L94Ac7EthPTu7E8SAzE,2217
|
4
|
-
fotolab/border.py,sha256=5ch2d7LVPhB2OFuuXSW5ci6Cn967CPDQu0qSfaO7uMg,3591
|
5
|
-
fotolab/cli.py,sha256=KoSDb752mewrtKE5wDs9icXF2McBVOKoEB98KYAV-jQ,4570
|
6
|
-
fotolab/contrast.py,sha256=l7Bs5p8W8ypN9Cg3fFHnU-A20UwMKtjTiPk6D0PRwpM,2095
|
7
|
-
fotolab/env.py,sha256=NTTvfISWBBfIw5opWrUfg0BtkaAtdUtcISBAJC2gVUk,1449
|
8
|
-
fotolab/info.py,sha256=DawXTQJiQDBwy0Ml5Ysk8MvKga3ikp_aIw73AR3LdZo,1687
|
9
|
-
fotolab/montage.py,sha256=lUVY-zDSH7mwH-s34_XefdNp7CoDJHkwpbTUGiyJGgs,2037
|
10
|
-
fotolab/resize.py,sha256=y3JT2IZUOeWf4gjORtaJ_ZseklO2jG6XvR-d6EdhS0k,2242
|
11
|
-
fotolab/sharpen.py,sha256=DsbIe4VU0Ty5oVzKnU70p9dMfhKr1i_UAQDimzAGX-Y,2655
|
12
|
-
fotolab/watermark.py,sha256=6LeK5g6W7Gq5kpLinwqBCwFGCtp0Uz_hrqBE3BD_CEU,5210
|
13
|
-
fotolab-0.13.0.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
|
14
|
-
fotolab-0.13.0.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
|
15
|
-
fotolab-0.13.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
|
16
|
-
fotolab-0.13.0.dist-info/METADATA,sha256=v1RC94R2HI1BVbz7dyA3nAVuGso-OsRmDZQvrHnCfuU,9085
|
17
|
-
fotolab-0.13.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|