fotolab 0.31.1__py3-none-any.whl → 0.31.4__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
@@ -20,11 +20,12 @@ import logging
20
20
  import os
21
21
  import subprocess
22
22
  import sys
23
+ from importlib import metadata
23
24
  from pathlib import Path
24
25
 
25
26
  from PIL import Image
26
27
 
27
- __version__ = "0.31.1"
28
+ __version__ = metadata.version("fotolab")
28
29
 
29
30
  log = logging.getLogger(__name__)
30
31
 
@@ -24,8 +24,7 @@ def build_subparser(subparsers):
24
24
  iter_namespace = pkgutil.iter_modules(__path__, __name__ + ".")
25
25
 
26
26
  subcommands = {
27
- name: importlib.import_module(name)
28
- for finder, name, ispkg in iter_namespace
27
+ name: importlib.import_module(name) for finder, name, ispkg in iter_namespace
29
28
  }
30
29
 
31
30
  for subcommand in subcommands.values():
@@ -123,10 +123,7 @@ def build_subparser(subparsers) -> None:
123
123
  type=int,
124
124
  default=4,
125
125
  choices=range(0, 7),
126
- help=(
127
- "set WEBP encoding method "
128
- "(0=fast, 6=slow/best, default: '%(default)s')"
129
- ),
126
+ help=("set WEBP encoding method (0=fast, 6=slow/best, default: '%(default)s')"),
130
127
  metavar="METHOD",
131
128
  )
132
129
 
@@ -77,10 +77,7 @@ def build_subparser(subparsers: argparse._SubParsersAction) -> None:
77
77
  dest="width_right",
78
78
  type=int,
79
79
  default=0,
80
- help=(
81
- "set the width of right border in pixels"
82
- " (default: '%(default)s')"
83
- ),
80
+ help=("set the width of right border in pixels (default: '%(default)s')"),
84
81
  metavar="WIDTH",
85
82
  )
86
83
 
@@ -90,10 +87,7 @@ def build_subparser(subparsers: argparse._SubParsersAction) -> None:
90
87
  dest="width_bottom",
91
88
  type=int,
92
89
  default=0,
93
- help=(
94
- "set the width of bottom border in pixels"
95
- " (default: '%(default)s')"
96
- ),
90
+ help=("set the width of bottom border in pixels (default: '%(default)s')"),
97
91
  metavar="WIDTH",
98
92
  )
99
93
 
@@ -31,9 +31,7 @@ def _validate_cutoff(value: str) -> float:
31
31
  try:
32
32
  f_value = float(value)
33
33
  except ValueError as e:
34
- raise argparse.ArgumentTypeError(
35
- f"invalid float value: '{value}'"
36
- ) from e
34
+ raise argparse.ArgumentTypeError(f"invalid float value: '{value}'") from e
37
35
  if not 0 <= f_value <= 50:
38
36
  raise argparse.ArgumentTypeError(
39
37
  f"cutoff value {f_value} must be between 0 and 50"
@@ -43,9 +41,7 @@ def _validate_cutoff(value: str) -> float:
43
41
 
44
42
  def build_subparser(subparsers: argparse._SubParsersAction) -> None:
45
43
  """Build the subparser."""
46
- contrast_parser = subparsers.add_parser(
47
- "contrast", help="contrast an image."
48
- )
44
+ contrast_parser = subparsers.add_parser("contrast", help="contrast an image.")
49
45
 
50
46
  contrast_parser.set_defaults(func=run)
51
47
 
@@ -103,8 +99,6 @@ def run(args: argparse.Namespace) -> None:
103
99
 
104
100
  for image_filename in args.image_filenames:
105
101
  original_image = Image.open(image_filename)
106
- contrast_image = ImageOps.autocontrast(
107
- original_image, cutoff=args.cutoff
108
- )
102
+ contrast_image = ImageOps.autocontrast(original_image, cutoff=args.cutoff)
109
103
 
110
104
  save_image(args, contrast_image, image_filename, "contrast")
@@ -37,9 +37,7 @@ class HalftoneCell(NamedTuple):
37
37
 
38
38
  def build_subparser(subparsers) -> None:
39
39
  """Build the subparser."""
40
- halftone_parser = subparsers.add_parser(
41
- "halftone", help="halftone an image"
42
- )
40
+ halftone_parser = subparsers.add_parser("halftone", help="halftone an image")
43
41
 
44
42
  halftone_parser.set_defaults(func=run)
45
43
 
@@ -156,9 +154,7 @@ def _draw_halftone_dot(
156
154
  else:
157
155
  # Calculate brightness (luminance) from the RGB color
158
156
  brightness = int(
159
- 0.299 * pixel_value[0]
160
- + 0.587 * pixel_value[1]
161
- + 0.114 * pixel_value[2]
157
+ 0.299 * pixel_value[0] + 0.587 * pixel_value[1] + 0.114 * pixel_value[2]
162
158
  )
163
159
  dot_fill = pixel_value # Use original color for color dots
164
160
 
@@ -107,9 +107,7 @@ def extract_exif_tags(image: Image.Image, sort: bool = False) -> dict:
107
107
  if exif:
108
108
  info = {ExifTags.TAGS.get(tag_id): exif.get(tag_id) for tag_id in exif}
109
109
 
110
- filtered_info = {
111
- key: value for key, value in info.items() if key is not None
112
- }
110
+ filtered_info = {key: value for key, value in info.items() if key is not None}
113
111
  if sort:
114
112
  filtered_info = dict(sorted(filtered_info.items()))
115
113
 
@@ -27,9 +27,7 @@ log = logging.getLogger(__name__)
27
27
 
28
28
  def build_subparser(subparsers) -> None:
29
29
  """Build the subparser."""
30
- montage_parser = subparsers.add_parser(
31
- "montage", help="montage a list of image"
32
- )
30
+ montage_parser = subparsers.add_parser("montage", help="montage a list of image")
33
31
 
34
32
  montage_parser.set_defaults(func=run)
35
33
 
@@ -59,10 +59,7 @@ def build_subparser(subparsers) -> None:
59
59
  "--canvas-color",
60
60
  default="black",
61
61
  dest="canvas_color",
62
- help=(
63
- "the color of the extended larger canvas"
64
- "(default: '%(default)s')"
65
- ),
62
+ help=("the color of the extended larger canvas(default: '%(default)s')"),
66
63
  )
67
64
 
68
65
  if "-c" in sys.argv or "--canvas" in sys.argv:
@@ -109,10 +109,7 @@ def build_subparser(subparsers: argparse._SubParsersAction) -> None:
109
109
  dest="outline_width",
110
110
  type=int,
111
111
  default=2,
112
- help=(
113
- "set the outline width of the watermark text "
114
- "(default: '%(default)s')"
115
- ),
112
+ help=("set the outline width of the watermark text (default: '%(default)s')"),
116
113
  metavar="OUTLINE_WIDTH",
117
114
  )
118
115
 
@@ -122,10 +119,7 @@ def build_subparser(subparsers: argparse._SubParsersAction) -> None:
122
119
  dest="outline_color",
123
120
  type=str,
124
121
  default="black",
125
- help=(
126
- "set the outline color of the watermark text "
127
- "(default: '%(default)s')"
128
- ),
122
+ help=("set the outline color of the watermark text (default: '%(default)s')"),
129
123
  metavar="OUTLINE_COLOR",
130
124
  )
131
125
 
@@ -203,9 +197,7 @@ def run(args: argparse.Namespace) -> None:
203
197
  if image.format == "GIF":
204
198
  watermark_gif_image(image, image_filename, args)
205
199
  else:
206
- watermarked_image: Image.Image = watermark_non_gif_image(
207
- image, args
208
- )
200
+ watermarked_image: Image.Image = watermark_non_gif_image(image, args)
209
201
  save_image(args, watermarked_image, image_filename, "watermark")
210
202
 
211
203
 
@@ -341,16 +333,12 @@ def calc_font_size(image: Image.Image, args: argparse.Namespace) -> int:
341
333
  return new_font_size
342
334
 
343
335
 
344
- def calc_font_outline_width(
345
- image: Image.Image, args: argparse.Namespace
346
- ) -> int:
336
+ def calc_font_outline_width(image: Image.Image, args: argparse.Namespace) -> int:
347
337
  """Calculate the font padding based on the width of the image."""
348
338
  width, _height = image.size
349
339
  new_font_outline_width: int = args.outline_width
350
340
  if width > 600:
351
- new_font_outline_width = math.floor(
352
- FONT_OUTLINE_WIDTH_ASPECT_RATIO * width
353
- )
341
+ new_font_outline_width = math.floor(FONT_OUTLINE_WIDTH_ASPECT_RATIO * width)
354
342
 
355
343
  log.debug("new font outline width: %d", new_font_outline_width)
356
344
  return new_font_outline_width
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: fotolab
3
- Version: 0.31.1
3
+ Version: 0.31.4
4
4
  Summary: A console program that manipulate images.
5
5
  Keywords: photography,photo
6
6
  Author-email: Kian-Meng Ang <kianmeng@cpan.org>
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Programming Language :: Python
19
+ License-File: LICENSE.md
19
20
  Requires-Dist: pillow
20
21
  Project-URL: Changelog, https://github.com/kianmeng/fotolab/blob/master/CHANGELOG.md
21
22
  Project-URL: Issues, https://github.com/kianmeng/fotolab/issues
@@ -27,28 +28,22 @@ A console program to manipulate photos.
27
28
 
28
29
  ## Installation
29
30
 
30
- Stable version From PyPI using `pipx`:
31
+ Stable version From PyPI using `uv`:
31
32
 
32
33
  ```console
33
- pipx install fotolab
34
- ```
35
-
36
- Stable version From PyPI using `pip`:
37
-
38
- ```console
39
- python -m pip install fotolab
34
+ uv pip install fotolab
40
35
  ```
41
36
 
42
37
  Upgrade to latest stable version:
43
38
 
44
39
  ```console
45
- python3 -m pip install fotolab --upgrade
40
+ uv pip install fotolab --upgrade
46
41
  ```
47
42
 
48
43
  Latest development version from GitHub:
49
44
 
50
45
  ```console
51
- python -m pip install -e git+https://github.com/kianmeng/fotolab.git
46
+ uv pip install -e git+https://github.com/kianmeng/fotolab.git
52
47
  ```
53
48
 
54
49
  ## Usage
@@ -0,0 +1,21 @@
1
+ fotolab/__init__.py,sha256=7XrkZPbYLVCnsak061vye7L9hFC7zj7cP7XWdjunAk8,3137
2
+ fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
3
+ fotolab/cli.py,sha256=oFiQXmsu3wIsM_DpZnL4B94sAoB62L16Am-cjxGmosY,4406
4
+ fotolab/subcommands/__init__.py,sha256=zPNE3lTK3yNjBq2zP1GiL13R4ywO_zh5MRFp5aOFp_g,1121
5
+ fotolab/subcommands/animate.py,sha256=Bzp1Y708UZogcLFwZSoJBfLAxLNZ5c0PESp1xl03sQg,5512
6
+ fotolab/subcommands/auto.py,sha256=3Hl1cCdu65GcfwvwiMRAcex6c7zA-KqIY6AFnB6nI3w,2447
7
+ fotolab/subcommands/border.py,sha256=3mD6ebdPjGk39ldUq9766jEXCbszPlbyV48k13dmrSA,4621
8
+ fotolab/subcommands/contrast.py,sha256=k-NGncYgm7x821CP-NhDbyZGzW1FPxaDgJi00xd97kw,2969
9
+ fotolab/subcommands/env.py,sha256=QoxRvzZKgmoHTUxDV4QYhdChCpMWs5TbXFY_qIpIQpE,1469
10
+ fotolab/subcommands/halftone.py,sha256=4YpHkp3zSYp36qJVPinWBOAUhTJjc-aGxiaNd1IkhXA,6655
11
+ fotolab/subcommands/info.py,sha256=pT2NBZ-KBjBCJJRpC9HC04iZj3s6RhbLWTRG6vjsarg,3549
12
+ fotolab/subcommands/montage.py,sha256=6-3VFMOQm3KOhcGaDfzStTKvBB5GHrotFkHU9kxZe5E,2552
13
+ fotolab/subcommands/resize.py,sha256=h4t425Xf95lkh6Trp-qw_cu0bBgMgBSBvJvUIR4dqiE,5407
14
+ fotolab/subcommands/rotate.py,sha256=uBFjHyjiBSQLtrtH1p9myODIHUDr1gkL4PpU-6Y1Ofo,2575
15
+ fotolab/subcommands/sharpen.py,sha256=YNho2IPbc-lPvSy3Bsjehc2JOEy27LPqFSGRULs9MyY,3492
16
+ fotolab/subcommands/watermark.py,sha256=uVcFynGt2hkTNF5RnfdHhBxSoLmlA7o8-_I65pe_di0,11166
17
+ fotolab-0.31.4.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
18
+ fotolab-0.31.4.dist-info/licenses/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
19
+ fotolab-0.31.4.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
20
+ fotolab-0.31.4.dist-info/METADATA,sha256=gUG_1R0jrlUKYmjNF_HSQpLCOh71dnBwCzAF_KrFDos,13581
21
+ fotolab-0.31.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: flit 3.9.0
2
+ Generator: flit 3.12.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,21 +0,0 @@
1
- fotolab/__init__.py,sha256=KWNA2ZPAuWOJFMr7zE2Lqnp2yOIi8e7vNdeo9uanRsQ,3087
2
- fotolab/__main__.py,sha256=aboOURPs_snOXTEWYR0q8oq1UTY9e-NxCd1j33V0wHI,833
3
- fotolab/cli.py,sha256=oFiQXmsu3wIsM_DpZnL4B94sAoB62L16Am-cjxGmosY,4406
4
- fotolab/subcommands/__init__.py,sha256=l3DlIaJ3u3jGjnC1H1yV8LZ_nPqOLJ6gikD4BCaMAQ0,1129
5
- fotolab/subcommands/animate.py,sha256=_tfIJOcwft-OP1PluPThWMsO6RAunj5RbhxeRi8Gf9w,5549
6
- fotolab/subcommands/auto.py,sha256=3Hl1cCdu65GcfwvwiMRAcex6c7zA-KqIY6AFnB6nI3w,2447
7
- fotolab/subcommands/border.py,sha256=-RNAYVcVTVrySzkmu3bIf__FTzog1BFC1jXqozF7PVM,4695
8
- fotolab/subcommands/contrast.py,sha256=fcXmHnxDw74j5ZUDQ5cwWh0N4tpyqqvEjymnpITgrEk,3027
9
- fotolab/subcommands/env.py,sha256=QoxRvzZKgmoHTUxDV4QYhdChCpMWs5TbXFY_qIpIQpE,1469
10
- fotolab/subcommands/halftone.py,sha256=lt6RV0OuZkGs1LigTC1EcCCY42CocPFHWaJTDjJ5LFM,6693
11
- fotolab/subcommands/info.py,sha256=H3voMi67cKoHT2Mu4RUNQBPdb_MspetPjhOvy-YyNnE,3563
12
- fotolab/subcommands/montage.py,sha256=d_3EcyRSFS8fKkczlHO8IRP-mrKhQUtkQndjfd0MKsc,2566
13
- fotolab/subcommands/resize.py,sha256=UOb2rg_5ArRj0gxPTDOww_ix3tqJRC0W5b_S-Lt1G4w,5444
14
- fotolab/subcommands/rotate.py,sha256=uBFjHyjiBSQLtrtH1p9myODIHUDr1gkL4PpU-6Y1Ofo,2575
15
- fotolab/subcommands/sharpen.py,sha256=YNho2IPbc-lPvSy3Bsjehc2JOEy27LPqFSGRULs9MyY,3492
16
- fotolab/subcommands/watermark.py,sha256=wKv_8eREUZ20hNF2xKs1XZlcSNbB2kdG_kbBlaXhJ1I,11298
17
- fotolab-0.31.1.dist-info/entry_points.txt,sha256=mvw7AY_yZkIyjAxPtHNed9X99NZeLnMxEeAfEJUbrCM,44
18
- fotolab-0.31.1.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
19
- fotolab-0.31.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
20
- fotolab-0.31.1.dist-info/METADATA,sha256=UjjTDVhNEU_PHEGJE-Cc_Z2zNugHVnxycHU3lzpBLIM,13656
21
- fotolab-0.31.1.dist-info/RECORD,,