fotolab 0.9.0__py2.py3-none-any.whl → 0.10.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
@@ -19,12 +19,42 @@ import logging
19
19
  import os
20
20
  import subprocess
21
21
  import sys
22
+ from pathlib import Path
22
23
 
23
- __version__ = "0.9.0"
24
+ __version__ = "0.10.0"
24
25
 
25
26
  log = logging.getLogger(__name__)
26
27
 
27
28
 
29
+ def save_image(args, new_image, subcommand):
30
+ """Save image after image operation.
31
+
32
+ Args:
33
+ args (argparse.Namespace): Config from command line arguments
34
+ new_image(PIL.Image.Image): Modified image
35
+ subcommand(str): Subcommand used to call this function
36
+
37
+ Returns:
38
+ None
39
+ """
40
+ image_file = Path(args.image_filename)
41
+
42
+ if args.overwrite:
43
+ new_filename = image_file.with_name(image_file.name)
44
+ else:
45
+ new_filename = Path(
46
+ args.output_dir,
47
+ image_file.with_name(f"{subcommand}_{image_file.name}"),
48
+ )
49
+ new_filename.parent.mkdir(parents=True, exist_ok=True)
50
+
51
+ log.info("%s image: %s", subcommand, new_filename)
52
+ new_image.save(new_filename)
53
+
54
+ if args.open:
55
+ _open_image(new_filename)
56
+
57
+
28
58
  def _open_image(filename):
29
59
  """Open generated image using default program."""
30
60
  if sys.platform == "linux":
fotolab/auto.py CHANGED
@@ -68,6 +68,7 @@ def run(args: argparse.Namespace) -> None:
68
68
  }
69
69
  combined_args = argparse.Namespace(**vars(args), **extra_args)
70
70
  combined_args.overwrite = True
71
+ combined_args.open = False
71
72
  log.debug(args)
72
73
  log.debug(combined_args)
73
74
 
fotolab/border.py CHANGED
@@ -17,10 +17,11 @@
17
17
 
18
18
  import argparse
19
19
  import logging
20
- from pathlib import Path
21
20
 
22
21
  from PIL import Image, ImageColor, ImageOps
23
22
 
23
+ from fotolab import save_image
24
+
24
25
  log = logging.getLogger(__name__)
25
26
 
26
27
 
@@ -110,8 +111,6 @@ def run(args: argparse.Namespace) -> None:
110
111
  """
111
112
  log.debug(args)
112
113
 
113
- image_file = Path(args.image_filename)
114
-
115
114
  original_image = Image.open(args.image_filename)
116
115
 
117
116
  if (
@@ -135,13 +134,4 @@ def run(args: argparse.Namespace) -> None:
135
134
  fill=ImageColor.getrgb(args.color),
136
135
  )
137
136
 
138
- if args.overwrite:
139
- new_filename = image_file.with_name(image_file.name)
140
- else:
141
- new_filename = Path(
142
- args.output_dir, image_file.with_name(f"border_{image_file.name}")
143
- )
144
- new_filename.parent.mkdir(parents=True, exist_ok=True)
145
-
146
- log.info("creating image: %s", new_filename)
147
- bordered_image.save(new_filename)
137
+ save_image(args, bordered_image, "border")
fotolab/cli.py CHANGED
@@ -29,6 +29,7 @@ import fotolab.auto
29
29
  import fotolab.border
30
30
  import fotolab.contrast
31
31
  import fotolab.env
32
+ import fotolab.info
32
33
  import fotolab.resize
33
34
  import fotolab.sharpen
34
35
  import fotolab.watermark
@@ -122,6 +123,7 @@ def build_parser() -> argparse.ArgumentParser:
122
123
  fotolab.auto.build_subparser(subparsers)
123
124
  fotolab.border.build_subparser(subparsers)
124
125
  fotolab.contrast.build_subparser(subparsers)
126
+ fotolab.info.build_subparser(subparsers)
125
127
  fotolab.resize.build_subparser(subparsers)
126
128
  fotolab.sharpen.build_subparser(subparsers)
127
129
  fotolab.watermark.build_subparser(subparsers)
fotolab/contrast.py CHANGED
@@ -17,10 +17,11 @@
17
17
 
18
18
  import argparse
19
19
  import logging
20
- from pathlib import Path
21
20
 
22
21
  from PIL import Image, ImageOps
23
22
 
23
+ from fotolab import save_image
24
+
24
25
  log = logging.getLogger(__name__)
25
26
 
26
27
 
@@ -66,19 +67,7 @@ def run(args: argparse.Namespace) -> None:
66
67
  """
67
68
  log.debug(args)
68
69
 
69
- image_file = Path(args.image_filename)
70
-
71
70
  original_image = Image.open(args.image_filename)
72
71
  contrast_image = ImageOps.autocontrast(original_image, cutoff=args.cutoff)
73
72
 
74
- if args.overwrite:
75
- new_filename = image_file.with_name(image_file.name)
76
- else:
77
- new_filename = Path(
78
- args.output_dir,
79
- image_file.with_name(f"contrast_{image_file.name}"),
80
- )
81
- new_filename.parent.mkdir(parents=True, exist_ok=True)
82
-
83
- log.info("contrasting image: %s", new_filename)
84
- contrast_image.save(new_filename)
73
+ save_image(args, contrast_image, "contrast")
fotolab/env.py CHANGED
@@ -45,6 +45,8 @@ def run(args: argparse.Namespace) -> None:
45
45
  """
46
46
  log.debug(args)
47
47
 
48
+ sys_version = sys.version.replace("\n", "")
49
+
48
50
  print(f"fotolab: {__version__}")
49
- print(f"python: {sys.version}")
51
+ print(f"python: {sys_version}")
50
52
  print(f"platform: {platform.platform()}")
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/resize.py CHANGED
@@ -17,10 +17,11 @@
17
17
 
18
18
  import argparse
19
19
  import logging
20
- from pathlib import Path
21
20
 
22
21
  from PIL import Image
23
22
 
23
+ from fotolab import save_image
24
+
24
25
  log = logging.getLogger(__name__)
25
26
 
26
27
 
@@ -63,28 +64,17 @@ def run(args: argparse.Namespace) -> None:
63
64
  """Run resize subcommand.
64
65
 
65
66
  Args:
66
- config (argparse.Namespace): Config from command line arguments
67
+ args (argparse.Namespace): Config from command line arguments
67
68
 
68
69
  Returns:
69
70
  None
70
71
  """
71
72
  log.debug(args)
72
73
 
73
- image_file = Path(args.image_filename)
74
74
  original_image = Image.open(args.image_filename)
75
75
  resized_image = original_image.copy()
76
76
  resized_image = resized_image.resize(
77
77
  (args.width, args.height), Image.Resampling.LANCZOS
78
78
  )
79
79
 
80
- if args.overwrite:
81
- new_filename = image_file.with_name(image_file.name)
82
- else:
83
- new_filename = Path(
84
- args.output_dir,
85
- image_file.with_name(f"resize_{image_file.name}"),
86
- )
87
- new_filename.parent.mkdir(parents=True, exist_ok=True)
88
-
89
- log.info("resizing image: %s", new_filename)
90
- resized_image.save(new_filename)
80
+ save_image(args, resized_image, "resize")
fotolab/sharpen.py CHANGED
@@ -17,10 +17,11 @@
17
17
 
18
18
  import argparse
19
19
  import logging
20
- from pathlib import Path
21
20
 
22
21
  from PIL import Image, ImageFilter
23
22
 
23
+ from fotolab import save_image
24
+
24
25
  log = logging.getLogger(__name__)
25
26
 
26
27
 
@@ -86,22 +87,10 @@ def run(args: argparse.Namespace) -> None:
86
87
  """
87
88
  log.debug(args)
88
89
 
89
- image_file = Path(args.image_filename)
90
-
91
90
  original_image = Image.open(args.image_filename)
92
91
  sharpen_image = original_image.filter(
93
92
  ImageFilter.UnsharpMask(
94
93
  args.radius, percent=args.percent, threshold=args.threshold
95
94
  )
96
95
  )
97
-
98
- if args.overwrite:
99
- new_filename = image_file.with_name(image_file.name)
100
- else:
101
- new_filename = Path(
102
- args.output_dir, image_file.with_name(f"sharpen_{image_file.name}")
103
- )
104
- new_filename.parent.mkdir(parents=True, exist_ok=True)
105
-
106
- log.info("sharpening image: %s", new_filename)
107
- sharpen_image.save(new_filename)
96
+ save_image(args, sharpen_image, "sharpen")
fotolab/watermark.py CHANGED
@@ -17,10 +17,11 @@
17
17
 
18
18
  import argparse
19
19
  import logging
20
- from pathlib import Path
21
20
 
22
21
  from PIL import Image, ImageColor, ImageDraw, ImageFont
23
22
 
23
+ from fotolab import save_image
24
+
24
25
  log = logging.getLogger(__name__)
25
26
 
26
27
  POSITIONS = ["top-left", "top-right", "bottom-left", "bottom-right"]
@@ -119,8 +120,6 @@ def run(args: argparse.Namespace) -> None:
119
120
  """
120
121
  log.debug(args)
121
122
 
122
- image_file = Path(args.image_filename)
123
-
124
123
  original_image = Image.open(args.image_filename)
125
124
  watermarked_image = original_image.copy()
126
125
 
@@ -146,17 +145,7 @@ def run(args: argparse.Namespace) -> None:
146
145
  stroke_fill=ImageColor.getrgb(args.outline_color),
147
146
  )
148
147
 
149
- if args.overwrite:
150
- new_filename = image_file.with_name(image_file.name)
151
- else:
152
- new_filename = Path(
153
- args.output_dir,
154
- image_file.with_name(f"watermark_{image_file.name}"),
155
- )
156
- new_filename.parent.mkdir(parents=True, exist_ok=True)
157
-
158
- log.info("watermarking image: %s", new_filename)
159
- watermarked_image.save(new_filename)
148
+ save_image(args, watermarked_image, "watermark")
160
149
 
161
150
 
162
151
  def calculate_position(image, text_width, text_height, position) -> tuple:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fotolab
3
- Version: 0.9.0
3
+ Version: 0.10.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>
@@ -57,9 +57,8 @@ fotolab -h
57
57
  ```
58
58
 
59
59
  ```console
60
-
61
60
  usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-d] [-V]
62
- {auto,border,contrast,resize,sharpen,watermark,env} ...
61
+ {auto,border,contrast,info,resize,sharpen,watermark,env} ...
63
62
 
64
63
  A console program to manipulate photos.
65
64
 
@@ -68,11 +67,12 @@ A console program to manipulate photos.
68
67
  issues: https://github.com/kianmeng/fotolab/issues
69
68
 
70
69
  positional arguments:
71
- {auto,border,contrast,resize,sharpen,watermark,env}
70
+ {auto,border,contrast,info,resize,sharpen,watermark,env}
72
71
  sub-command help
73
72
  auto auto adjust (resize, contrast, and watermark) a photo
74
73
  border add border to image
75
74
  contrast contrast an image
75
+ info info an image
76
76
  resize resize an image
77
77
  sharpen sharpen an image
78
78
  watermark watermark an image
@@ -135,6 +135,22 @@ optional arguments:
135
135
  -h, --help show this help message and exit
136
136
  ```
137
137
 
138
+ ### fotolab info
139
+
140
+ ```console
141
+ fotolab info -h
142
+ ```
143
+
144
+ ```console
145
+ usage: fotolab info [-h] IMAGE_FILENAME
146
+
147
+ positional arguments:
148
+ IMAGE_FILENAME set the image filename
149
+
150
+ optional arguments:
151
+ -h, --help show this help message and exit
152
+ ```
153
+
138
154
  ### fotolab sharpen
139
155
 
140
156
  ```console
@@ -0,0 +1,16 @@
1
+ fotolab/__init__.py,sha256=rLzpwtU7DbbHRYPQ4hQCyhQdg6OrvKeftKLf0PaytXo,2061
2
+ fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
3
+ fotolab/auto.py,sha256=k4DkHQp05m7UYUgHRrH9L1d0eSgOzrn2Cyk5BG27KyA,2173
4
+ fotolab/border.py,sha256=vujylADWHQsFwoCjoUa2yOIi8aJhTrVBgZsqyxDHKV0,3423
5
+ fotolab/cli.py,sha256=erXr3MXmMXQ9bDu9T6ZoOoRW0Yzt2z8anlSPJHkHtBk,4498
6
+ fotolab/contrast.py,sha256=82dpsFHW6kW7tR0kekFn1UoZAuAq3EXWQNOmrtRGw2g,1981
7
+ fotolab/env.py,sha256=NTTvfISWBBfIw5opWrUfg0BtkaAtdUtcISBAJC2gVUk,1449
8
+ fotolab/info.py,sha256=DawXTQJiQDBwy0Ml5Ysk8MvKga3ikp_aIw73AR3LdZo,1687
9
+ fotolab/resize.py,sha256=EkZYyWw9jHVmexIVbF3a9v5MYQEQxjVXlGGBMoB0IeQ,2138
10
+ fotolab/sharpen.py,sha256=DGeIq24JHpfftAF_h26cTMJVwSsxmnB9bL7lPkynuco,2546
11
+ fotolab/watermark.py,sha256=8qHkGzjw726pv8z8wY5dH70-7lnr9Zr-VXkZep3VSac,4661
12
+ fotolab-0.10.0.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
13
+ fotolab-0.10.0.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
14
+ fotolab-0.10.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
15
+ fotolab-0.10.0.dist-info/METADATA,sha256=SunRTn8v-nCy8Pw5N9qGLewPSyxyo9-t7On3RxCwHPI,6973
16
+ fotolab-0.10.0.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- fotolab/__init__.py,sha256=a0NCJBRDthqiPJOuVD1dvsVwDXvm-ruruL26QiEL6q8,1237
2
- fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
3
- fotolab/auto.py,sha256=q_d_lOZh410nvh9yGNS3k-jg5mB0zQrhOfxSmi-nShA,2142
4
- fotolab/border.py,sha256=QBA-rJ0phv_3ace20NW18PlhLIbYDjdGVJwX13vDKdI,3776
5
- fotolab/cli.py,sha256=4IEk0DRrCPIG0PB37f4zSyWUEbrZrLSKi5qJxb1M0Is,4433
6
- fotolab/contrast.py,sha256=dtQ39YBDmBhFlRS0jB8XqLsoNGEz96ZYfgg71MyeLFg,2350
7
- fotolab/env.py,sha256=XUwy3TAFFcTMvtXAT0tLJbo-ianBo_FPK2IQfvBOhic,1400
8
- fotolab/resize.py,sha256=ax4IacQR4vuGGxGI3B-ito6ldiT054QkaKympiv4y20,2505
9
- fotolab/sharpen.py,sha256=PP1xYXupOetQxQxXijzWiUlrKNlu80lfInG37VQhVYw,2902
10
- fotolab/watermark.py,sha256=X7u-HlOONfOhU8VRyvOgIvXYUu_q9IKHBMEkIf-oem4,5031
11
- fotolab-0.9.0.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
12
- fotolab-0.9.0.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
13
- fotolab-0.9.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
14
- fotolab-0.9.0.dist-info/METADATA,sha256=i_R7skWGswlLGC1_GbZWdXWkXTup2iGeQ17iaHRZ8vc,6688
15
- fotolab-0.9.0.dist-info/RECORD,,