fotolab 0.9.1__py2.py3-none-any.whl → 0.14.0__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 CHANGED
@@ -21,34 +21,34 @@ import subprocess
21
21
  import sys
22
22
  from pathlib import Path
23
23
 
24
- __version__ = "0.9.1"
24
+ __version__ = "0.14.0"
25
25
 
26
26
  log = logging.getLogger(__name__)
27
27
 
28
28
 
29
- def save_image(args, new_image):
30
- """Run resize subcommand.
29
+ def save_image(args, new_image, output_filename, subcommand):
30
+ """Save image after image operation.
31
31
 
32
32
  Args:
33
33
  args (argparse.Namespace): Config from command line arguments
34
34
  new_image(PIL.Image.Image): Modified image
35
+ subcommand(str): Subcommand used to call this function
35
36
 
36
37
  Returns:
37
38
  None
38
39
  """
39
- action = args.func.__module__.split(".")[-1]
40
- image_file = Path(args.image_filename)
40
+ image_file = Path(output_filename)
41
41
 
42
42
  if args.overwrite:
43
43
  new_filename = image_file.with_name(image_file.name)
44
44
  else:
45
45
  new_filename = Path(
46
46
  args.output_dir,
47
- image_file.with_name(f"{action}_{image_file.name}"),
47
+ image_file.with_name(f"{subcommand}_{image_file.name}"),
48
48
  )
49
49
  new_filename.parent.mkdir(parents=True, exist_ok=True)
50
50
 
51
- log.info("%s image: %s", action, new_filename)
51
+ log.info("%s image: %s", subcommand, new_filename)
52
52
  new_image.save(new_filename)
53
53
 
54
54
  if args.open:
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/auto.py CHANGED
@@ -35,11 +35,12 @@ def build_subparser(subparsers) -> None:
35
35
  auto_parser.set_defaults(func=run)
36
36
 
37
37
  auto_parser.add_argument(
38
- dest="image_filename",
38
+ dest="image_filenames",
39
39
  help="set the image filename",
40
+ nargs="+",
40
41
  type=str,
41
42
  default=None,
42
- metavar="IMAGE_FILENAME",
43
+ metavar="IMAGE_FILENAMES",
43
44
  )
44
45
 
45
46
 
@@ -65,6 +66,7 @@ def run(args: argparse.Namespace) -> None:
65
66
  "font_color": "white",
66
67
  "outline_width": 2,
67
68
  "outline_color": "black",
69
+ "padding": 15,
68
70
  }
69
71
  combined_args = argparse.Namespace(**vars(args), **extra_args)
70
72
  combined_args.overwrite = True
fotolab/border.py CHANGED
@@ -32,11 +32,12 @@ def build_subparser(subparsers) -> None:
32
32
  border_parser.set_defaults(func=run)
33
33
 
34
34
  border_parser.add_argument(
35
- dest="image_filename",
36
- help="set the image filename",
35
+ dest="image_filenames",
36
+ help="set the image filenames",
37
+ nargs="+",
37
38
  type=str,
38
39
  default=None,
39
- metavar="IMAGE_FILENAME",
40
+ metavar="IMAGE_FILENAMES",
40
41
  )
41
42
 
42
43
  border_parser.add_argument(
@@ -111,27 +112,28 @@ def run(args: argparse.Namespace) -> None:
111
112
  """
112
113
  log.debug(args)
113
114
 
114
- original_image = Image.open(args.image_filename)
115
-
116
- if (
117
- args.width_left
118
- or args.width_top
119
- or args.width_right
120
- or args.width_bottom
121
- ):
122
- border = (
123
- int(args.width_left),
124
- int(args.width_top),
125
- int(args.width_right),
126
- int(args.width_bottom),
115
+ for image_filename in args.image_filenames:
116
+ original_image = Image.open(image_filename)
117
+
118
+ if (
119
+ args.width_left
120
+ or args.width_top
121
+ or args.width_right
122
+ or args.width_bottom
123
+ ):
124
+ border = (
125
+ int(args.width_left),
126
+ int(args.width_top),
127
+ int(args.width_right),
128
+ int(args.width_bottom),
129
+ )
130
+ else:
131
+ border = args.width
132
+
133
+ bordered_image = ImageOps.expand(
134
+ original_image,
135
+ border=border,
136
+ fill=ImageColor.getrgb(args.color),
127
137
  )
128
- else:
129
- border = args.width
130
138
 
131
- bordered_image = ImageOps.expand(
132
- original_image,
133
- border=border,
134
- fill=ImageColor.getrgb(args.color),
135
- )
136
-
137
- save_image(args, bordered_image)
139
+ save_image(args, bordered_image, image_filename, "watermark")
fotolab/cli.py CHANGED
@@ -25,10 +25,13 @@ 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
31
32
  import fotolab.env
33
+ import fotolab.info
34
+ import fotolab.montage
32
35
  import fotolab.resize
33
36
  import fotolab.sharpen
34
37
  import fotolab.watermark
@@ -82,7 +85,7 @@ def build_parser() -> argparse.ArgumentParser:
82
85
  default=False,
83
86
  action="store_true",
84
87
  dest="open",
85
- help="open the image using default program (default: '%(default)s'",
88
+ help="open the image using default program (default: '%(default)s')",
86
89
  )
87
90
 
88
91
  parser.add_argument(
@@ -119,10 +122,13 @@ def build_parser() -> argparse.ArgumentParser:
119
122
  )
120
123
 
121
124
  subparsers = parser.add_subparsers(help="sub-command help")
125
+ fotolab.animate.build_subparser(subparsers)
122
126
  fotolab.auto.build_subparser(subparsers)
123
127
  fotolab.border.build_subparser(subparsers)
124
128
  fotolab.contrast.build_subparser(subparsers)
129
+ fotolab.info.build_subparser(subparsers)
125
130
  fotolab.resize.build_subparser(subparsers)
131
+ fotolab.montage.build_subparser(subparsers)
126
132
  fotolab.sharpen.build_subparser(subparsers)
127
133
  fotolab.watermark.build_subparser(subparsers)
128
134
  fotolab.env.build_subparser(subparsers)
fotolab/contrast.py CHANGED
@@ -34,11 +34,12 @@ def build_subparser(subparsers) -> None:
34
34
  contrast_parser.set_defaults(func=run)
35
35
 
36
36
  contrast_parser.add_argument(
37
- dest="image_filename",
37
+ dest="image_filenames",
38
38
  help="set the image filename",
39
+ nargs="+",
39
40
  type=str,
40
41
  default=None,
41
- metavar="IMAGE_FILENAME",
42
+ metavar="IMAGE_FILENAMES",
42
43
  )
43
44
 
44
45
  contrast_parser.add_argument(
@@ -67,7 +68,10 @@ def run(args: argparse.Namespace) -> None:
67
68
  """
68
69
  log.debug(args)
69
70
 
70
- original_image = Image.open(args.image_filename)
71
- contrast_image = ImageOps.autocontrast(original_image, cutoff=args.cutoff)
71
+ for image_filename in args.image_filenames:
72
+ original_image = Image.open(image_filename)
73
+ contrast_image = ImageOps.autocontrast(
74
+ original_image, cutoff=args.cutoff
75
+ )
72
76
 
73
- save_image(args, contrast_image)
77
+ save_image(args, contrast_image, image_filename, "contrast")
fotolab/info.py ADDED
@@ -0,0 +1,58 @@
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
+ """Info subcommand."""
17
+
18
+ import argparse
19
+ import logging
20
+
21
+ from PIL import ExifTags, Image
22
+
23
+ log = logging.getLogger(__name__)
24
+
25
+
26
+ def build_subparser(subparsers) -> None:
27
+ """Build the subparser."""
28
+ info_parser = subparsers.add_parser("info", help="info an image")
29
+
30
+ info_parser.set_defaults(func=run)
31
+
32
+ info_parser.add_argument(
33
+ dest="image_filename",
34
+ help="set the image filename",
35
+ type=str,
36
+ default=None,
37
+ metavar="IMAGE_FILENAME",
38
+ )
39
+
40
+
41
+ def run(args: argparse.Namespace) -> None:
42
+ """Run info subcommand.
43
+
44
+ Args:
45
+ config (argparse.Namespace): Config from command line arguments
46
+
47
+ Returns:
48
+ None
49
+ """
50
+ log.debug(args)
51
+
52
+ image = Image.open(args.image_filename)
53
+ exif = image._getexif()
54
+ info = {ExifTags.TAGS.get(tag_id): exif.get(tag_id) for tag_id in exif}
55
+
56
+ tag_name_width = max(map(len, info))
57
+ for tag_name, tag_value in info.items():
58
+ print(f"{tag_name:<{tag_name_width}}: {tag_value}")
fotolab/montage.py ADDED
@@ -0,0 +1,71 @@
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
+ """Montage 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
+ montage_parser = subparsers.add_parser(
31
+ "montage", help="montage a list of image"
32
+ )
33
+
34
+ montage_parser.set_defaults(func=run)
35
+
36
+ montage_parser.add_argument(
37
+ dest="image_filenames",
38
+ help="set the image filenames",
39
+ nargs="+",
40
+ type=argparse.FileType("r"),
41
+ default=None,
42
+ metavar="IMAGE_FILENAMES",
43
+ )
44
+
45
+
46
+ def run(args: argparse.Namespace) -> None:
47
+ """Run montage subcommand.
48
+
49
+ Args:
50
+ config (argparse.Namespace): Config from command line arguments
51
+
52
+ Returns:
53
+ None
54
+ """
55
+ log.debug(args)
56
+ images = []
57
+ for image_filename in args.image_filenames:
58
+ images.append(Image.open(image_filename.name))
59
+
60
+ total_width = sum(img.width for img in images)
61
+ total_height = max(img.height for img in images)
62
+
63
+ montaged_image = Image.new("RGB", (total_width, total_height))
64
+
65
+ x_offset = 0
66
+ for img in images:
67
+ montaged_image.paste(img, (x_offset, 0))
68
+ x_offset += img.width
69
+
70
+ output_image_filename = args.image_filenames[0].name
71
+ save_image(args, montaged_image, output_image_filename, "montage")
fotolab/resize.py CHANGED
@@ -32,11 +32,12 @@ def build_subparser(subparsers) -> None:
32
32
  resize_parser.set_defaults(func=run)
33
33
 
34
34
  resize_parser.add_argument(
35
- dest="image_filename",
35
+ dest="image_filenames",
36
36
  help="set the image filename",
37
+ nargs="+",
37
38
  type=str,
38
39
  default=None,
39
- metavar="IMAGE_FILENAME",
40
+ metavar="IMAGE_FILENAMES",
40
41
  )
41
42
 
42
43
  resize_parser.add_argument(
@@ -71,10 +72,11 @@ def run(args: argparse.Namespace) -> None:
71
72
  """
72
73
  log.debug(args)
73
74
 
74
- original_image = Image.open(args.image_filename)
75
- resized_image = original_image.copy()
76
- resized_image = resized_image.resize(
77
- (args.width, args.height), Image.Resampling.LANCZOS
78
- )
75
+ for image_filename in args.image_filenames:
76
+ original_image = Image.open(image_filename)
77
+ resized_image = original_image.copy()
78
+ resized_image = resized_image.resize(
79
+ (args.width, args.height), Image.Resampling.LANCZOS
80
+ )
79
81
 
80
- save_image(args, resized_image)
82
+ save_image(args, resized_image, image_filename, "resize")
fotolab/sharpen.py CHANGED
@@ -32,11 +32,12 @@ def build_subparser(subparsers) -> None:
32
32
  sharpen_parser.set_defaults(func=run)
33
33
 
34
34
  sharpen_parser.add_argument(
35
- dest="image_filename",
36
- help="set the image filename",
35
+ dest="image_filenames",
36
+ help="set the image filenames",
37
+ nargs="+",
37
38
  type=str,
38
39
  default=None,
39
- metavar="IMAGE_FILENAME",
40
+ metavar="IMAGE_FILENAMES",
40
41
  )
41
42
 
42
43
  sharpen_parser.add_argument(
@@ -87,10 +88,11 @@ def run(args: argparse.Namespace) -> None:
87
88
  """
88
89
  log.debug(args)
89
90
 
90
- original_image = Image.open(args.image_filename)
91
- sharpen_image = original_image.filter(
92
- ImageFilter.UnsharpMask(
93
- args.radius, percent=args.percent, threshold=args.threshold
91
+ for image_filename in args.image_filenames:
92
+ original_image = Image.open(image_filename)
93
+ sharpen_image = original_image.filter(
94
+ ImageFilter.UnsharpMask(
95
+ args.radius, percent=args.percent, threshold=args.threshold
96
+ )
94
97
  )
95
- )
96
- save_image(args, sharpen_image)
98
+ save_image(args, sharpen_image, image_filename, "sharpen")
fotolab/watermark.py CHANGED
@@ -36,11 +36,12 @@ def build_subparser(subparsers) -> None:
36
36
  watermark_parser.set_defaults(func=run)
37
37
 
38
38
  watermark_parser.add_argument(
39
- dest="image_filename",
40
- help="set the image filename",
39
+ dest="image_filenames",
40
+ help="set the image filenames",
41
+ nargs="+",
41
42
  type=str,
42
43
  default=None,
43
- metavar="IMAGE_FILENAME",
44
+ metavar="IMAGE_FILENAMES",
44
45
  )
45
46
 
46
47
  watermark_parser.add_argument(
@@ -62,6 +63,19 @@ def build_subparser(subparsers) -> None:
62
63
  default="bottom-left",
63
64
  )
64
65
 
66
+ watermark_parser.add_argument(
67
+ "-pd",
68
+ "--padding",
69
+ dest="padding",
70
+ type=int,
71
+ default=15,
72
+ help=(
73
+ "set the padding of the watermark text relative to the image "
74
+ "(default: '%(default)s')"
75
+ ),
76
+ metavar="PADDING",
77
+ )
78
+
65
79
  watermark_parser.add_argument(
66
80
  "-fs",
67
81
  "--font-size",
@@ -120,37 +134,43 @@ def run(args: argparse.Namespace) -> None:
120
134
  """
121
135
  log.debug(args)
122
136
 
123
- original_image = Image.open(args.image_filename)
124
- watermarked_image = original_image.copy()
125
-
126
- draw = ImageDraw.Draw(watermarked_image)
127
-
128
- font = ImageFont.truetype("arial.ttf", args.font_size)
129
-
130
- (left, top, right, bottom) = draw.textbbox(
131
- xy=(0, 0), text=args.text, font=font
132
- )
133
- text_width = right - left
134
- text_height = bottom - top
135
- (position_x, position_y) = calculate_position(
136
- watermarked_image, text_width, text_height, args.position
137
- )
138
-
139
- draw.text(
140
- (position_x, position_y),
141
- args.text,
142
- font=font,
143
- fill=ImageColor.getrgb(args.font_color),
144
- stroke_width=args.outline_width,
145
- stroke_fill=ImageColor.getrgb(args.outline_color),
146
- )
147
-
148
- save_image(args, watermarked_image)
149
-
150
-
151
- def calculate_position(image, text_width, text_height, position) -> tuple:
137
+ for image_filename in args.image_filenames:
138
+ original_image = Image.open(image_filename)
139
+ watermarked_image = original_image.copy()
140
+
141
+ draw = ImageDraw.Draw(watermarked_image)
142
+
143
+ font = ImageFont.truetype("arial.ttf", args.font_size)
144
+
145
+ (left, top, right, bottom) = draw.textbbox(
146
+ xy=(0, 0), text=args.text, font=font
147
+ )
148
+ text_width = right - left
149
+ text_height = bottom - top
150
+ (position_x, position_y) = calculate_position(
151
+ watermarked_image,
152
+ text_width,
153
+ text_height,
154
+ args.position,
155
+ args.padding,
156
+ )
157
+
158
+ draw.text(
159
+ (position_x, position_y),
160
+ args.text,
161
+ font=font,
162
+ fill=(*ImageColor.getrgb(args.font_color), 128),
163
+ stroke_width=args.outline_width,
164
+ stroke_fill=(*ImageColor.getrgb(args.outline_color), 128),
165
+ )
166
+
167
+ save_image(args, watermarked_image, image_filename, "watermark")
168
+
169
+
170
+ def calculate_position(
171
+ image, text_width, text_height, position, padding
172
+ ) -> tuple:
152
173
  """Calculate the boundary coordinates of the watermark text."""
153
- padding = 10
154
174
  if position == "top-left":
155
175
  position_x = 0 + padding
156
176
  position_y = 0 + padding
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fotolab
3
- Version: 0.9.1
3
+ Version: 0.14.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>
@@ -59,7 +59,8 @@ fotolab -h
59
59
  ```console
60
60
 
61
61
  usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-d] [-V]
62
- {auto,border,contrast,resize,sharpen,watermark,env} ...
62
+ {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
63
+ ...
63
64
 
64
65
  A console program to manipulate photos.
65
66
 
@@ -68,12 +69,15 @@ A console program to manipulate photos.
68
69
  issues: https://github.com/kianmeng/fotolab/issues
69
70
 
70
71
  positional arguments:
71
- {auto,border,contrast,resize,sharpen,watermark,env}
72
+ {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
72
73
  sub-command help
74
+ animate animate an image
73
75
  auto auto adjust (resize, contrast, and watermark) a photo
74
76
  border add border to image
75
77
  contrast contrast an image
78
+ info info an image
76
79
  resize resize an image
80
+ montage montage a list of image
77
81
  sharpen sharpen an image
78
82
  watermark watermark an image
79
83
  env print environment information for bug reporting
@@ -81,7 +85,7 @@ positional arguments:
81
85
  optional arguments:
82
86
  -h, --help show this help message and exit
83
87
  -o, --overwrite overwrite existing image
84
- -op, --open open the image using default program (default: 'False'
88
+ -op, --open open the image using default program (default: 'False')
85
89
  -od OUTPUT_DIR, --output-dir OUTPUT_DIR
86
90
  set default output folder (default: 'output')
87
91
  -q, --quiet suppress all logging
@@ -89,6 +93,45 @@ optional arguments:
89
93
  -V, --version show program's version number and exit
90
94
  ```
91
95
 
96
+ ### fotolab animate
97
+
98
+ ```console
99
+ fotolab animate -h
100
+ ```
101
+
102
+ ```console
103
+
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
+
119
+ ### fotolab auto
120
+
121
+ ```console
122
+ fotolab auto -h
123
+ ```
124
+
125
+ ```console
126
+ usage: fotolab auto [-h] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
127
+
128
+ positional arguments:
129
+ IMAGE_FILENAMES set the image filename
130
+
131
+ optional arguments:
132
+ -h, --help show this help message and exit
133
+ ```
134
+
92
135
  ### fotolab border
93
136
 
94
137
  ```console
@@ -98,12 +141,12 @@ fotolab border -h
98
141
  ```console
99
142
  usage: fotolab border [-h] [-c COLOR] [-w WIDTH] [-wt WIDTH] [-wr WIDTH]
100
143
  [-wb WIDTH] [-wl WIDTH]
101
- IMAGE_FILENAME
144
+ IMAGE_FILENAMES [IMAGE_FILENAMES ...]
102
145
 
103
146
  positional arguments:
104
- IMAGE_FILENAME set the image filename
147
+ IMAGE_FILENAMES set the image filenames
105
148
 
106
- options:
149
+ optional arguments:
107
150
  -h, --help show this help message and exit
108
151
  -c COLOR, --color COLOR
109
152
  set the color of border (default: 'black')
@@ -126,7 +169,26 @@ fotolab contrast -h
126
169
  ```
127
170
 
128
171
  ```console
129
- usage: fotolab contrast [-h] IMAGE_FILENAME
172
+ usage: fotolab contrast [-h] [-c CUTOFF] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
173
+
174
+ positional arguments:
175
+ IMAGE_FILENAMES set the image filename
176
+
177
+ optional arguments:
178
+ -h, --help show this help message and exit
179
+ -c CUTOFF, --cutoff CUTOFF
180
+ set the percentage of lightest or darkest pixels to
181
+ discard from histogram (default: '1')
182
+ ```
183
+
184
+ ### fotolab info
185
+
186
+ ```console
187
+ fotolab info -h
188
+ ```
189
+
190
+ ```console
191
+ usage: fotolab info [-h] IMAGE_FILENAME
130
192
 
131
193
  positional arguments:
132
194
  IMAGE_FILENAME set the image filename
@@ -135,6 +197,44 @@ optional arguments:
135
197
  -h, --help show this help message and exit
136
198
  ```
137
199
 
200
+ ### fotolab montage
201
+
202
+ ```console
203
+ fotolab montage -h
204
+ ```
205
+
206
+ ```console
207
+
208
+ usage: fotolab montage [-h] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
209
+
210
+ positional arguments:
211
+ IMAGE_FILENAMES set the image filenames
212
+
213
+ optional arguments:
214
+ -h, --help show this help message and exit
215
+ ```
216
+
217
+ ### fotolab resize
218
+
219
+ ```console
220
+ fotolab resize -h
221
+ ```
222
+
223
+ ```console
224
+ usage: fotolab resize [-h] [-wh WIDTH] [-ht HEIGHT]
225
+ IMAGE_FILENAMES [IMAGE_FILENAMES ...]
226
+
227
+ positional arguments:
228
+ IMAGE_FILENAMES set the image filename
229
+
230
+ optional arguments:
231
+ -h, --help show this help message and exit
232
+ -wh WIDTH, --width WIDTH
233
+ set the width of the image (default: '600')
234
+ -ht HEIGHT, --height HEIGHT
235
+ set the height of the image (default: '277')
236
+ ```
237
+
138
238
  ### fotolab sharpen
139
239
 
140
240
  ```console
@@ -142,13 +242,22 @@ fotolab sharpen -h
142
242
  ```
143
243
 
144
244
  ```console
145
- usage: fotolab sharpen [-h] IMAGE_FILENAME
245
+ usage: fotolab sharpen [-h] [-r RADIUS] [-p PERCENT] [-t THRESHOLD]
246
+ IMAGE_FILENAMES [IMAGE_FILENAMES ...]
146
247
 
147
248
  positional arguments:
148
- IMAGE_FILENAME set the image filename
249
+ IMAGE_FILENAMES set the image filenames
149
250
 
150
- options:
151
- -h, --help show this help message and exit
251
+ optional arguments:
252
+ -h, --help show this help message and exit
253
+ -r RADIUS, --radius RADIUS
254
+ set the radius or size of edges (default: '1')
255
+ -p PERCENT, --percent PERCENT
256
+ set the amount of overall strength of sharpening
257
+ effect (default: '100')
258
+ -t THRESHOLD, --threshold THRESHOLD
259
+ set the minimum brightness changed to be sharpened
260
+ (default: '3')
152
261
  ```
153
262
 
154
263
  ### fotolab watermark
@@ -160,20 +269,23 @@ fotolab watermark -h
160
269
  ```console
161
270
  usage: fotolab watermark [-h] [-t WATERMARK_TEXT]
162
271
  [-p {top-left,top-right,bottom-left,bottom-right}]
163
- [-fs FONT_SIZE] [-fc FONT_COLOR] [-ow OUTLINE_WIDTH]
164
- [-oc OUTLINE_COLOR]
165
- IMAGE_FILENAME
272
+ [-pd PADDING] [-fs FONT_SIZE] [-fc FONT_COLOR]
273
+ [-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR]
274
+ IMAGE_FILENAMES [IMAGE_FILENAMES ...]
166
275
 
167
276
  positional arguments:
168
- IMAGE_FILENAME set the image filename
277
+ IMAGE_FILENAMES set the image filenames
169
278
 
170
- options:
279
+ optional arguments:
171
280
  -h, --help show this help message and exit
172
281
  -t WATERMARK_TEXT, --text WATERMARK_TEXT
173
282
  set the watermark text (default: 'kianmeng.org')
174
283
  -p {top-left,top-right,bottom-left,bottom-right}, --position {top-left,top-right,bottom-left,bottom-right}
175
284
  set position of the watermark text (default: 'bottom-
176
285
  left')
286
+ -pd PADDING, --padding PADDING
287
+ set the padding of the watermark text relative to the
288
+ image (default: '15')
177
289
  -fs FONT_SIZE, --font-size FONT_SIZE
178
290
  set the font size of watermark text (default: '12')
179
291
  -fc FONT_COLOR, --font-color FONT_COLOR
@@ -0,0 +1,18 @@
1
+ fotolab/__init__.py,sha256=cpDAMSgpSA1exqkB5BGL2OrPVQfTzxV8nOTS5iP0rUE,2074
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=ZbXkftGAIrlcOgWju6KIeCBA8-EDVop2mkRN5f1Sa34,4641
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=y3JT2IZUOeWf4gjORtaJ_ZseklO2jG6XvR-d6EdhS0k,2242
12
+ fotolab/sharpen.py,sha256=DsbIe4VU0Ty5oVzKnU70p9dMfhKr1i_UAQDimzAGX-Y,2655
13
+ fotolab/watermark.py,sha256=6LeK5g6W7Gq5kpLinwqBCwFGCtp0Uz_hrqBE3BD_CEU,5210
14
+ fotolab-0.14.0.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
15
+ fotolab-0.14.0.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
16
+ fotolab-0.14.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
17
+ fotolab-0.14.0.dist-info/METADATA,sha256=jHoSNuIcWosz5li1NRXRTHRxpIFX3sjPv11jFAi7kMQ,9744
18
+ fotolab-0.14.0.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- fotolab/__init__.py,sha256=3N1D57pcYWYmpOUqPIomNqEWg4qVTyVQP6AUvKRNGOg,2015
2
- fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
3
- fotolab/auto.py,sha256=k4DkHQp05m7UYUgHRrH9L1d0eSgOzrn2Cyk5BG27KyA,2173
4
- fotolab/border.py,sha256=-XNa118OpiXwCXptSCl1HdxTJ2SSnv62HSg6xfBChaY,3413
5
- fotolab/cli.py,sha256=4IEk0DRrCPIG0PB37f4zSyWUEbrZrLSKi5qJxb1M0Is,4433
6
- fotolab/contrast.py,sha256=chIjzw2h7TA_u63Y_ZNS_0otxtyXgHmHaCDOMUayS_A,1969
7
- fotolab/env.py,sha256=NTTvfISWBBfIw5opWrUfg0BtkaAtdUtcISBAJC2gVUk,1449
8
- fotolab/resize.py,sha256=6314jLmhwb_ktd6uKEToaNHW0ZOyPW2IiELosBsIcXs,2128
9
- fotolab/sharpen.py,sha256=5lLWZ2JOM-jfsqr6Lt9tlijZH1oz4KlvBytTL0-QLQI,2535
10
- fotolab/watermark.py,sha256=Hn3nUhQo3iFhvtlsLjGjFMGG8rqKFNGOYQBcwRS250M,4648
11
- fotolab-0.9.1.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
12
- fotolab-0.9.1.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
13
- fotolab-0.9.1.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
14
- fotolab-0.9.1.dist-info/METADATA,sha256=ukyF71SeL7LHXiYzH90aXgo6xzA94Q3aQ_iZjZDRr7s,6688
15
- fotolab-0.9.1.dist-info/RECORD,,