fotolab 0.13.0__tar.gz → 0.14.0__tar.gz

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.
Files changed (40) hide show
  1. {fotolab-0.13.0 → fotolab-0.14.0}/.pre-commit-config.yaml +2 -2
  2. {fotolab-0.13.0 → fotolab-0.14.0}/CHANGELOG.md +10 -0
  3. {fotolab-0.13.0 → fotolab-0.14.0}/PKG-INFO +28 -3
  4. {fotolab-0.13.0 → fotolab-0.14.0}/Pipfile.lock +9 -9
  5. {fotolab-0.13.0 → fotolab-0.14.0}/README.md +27 -2
  6. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/__init__.py +1 -1
  7. fotolab-0.14.0/fotolab/animate.py +114 -0
  8. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/cli.py +2 -0
  9. {fotolab-0.13.0 → fotolab-0.14.0}/.coveragerc +0 -0
  10. {fotolab-0.13.0 → fotolab-0.14.0}/.gitignore +0 -0
  11. {fotolab-0.13.0 → fotolab-0.14.0}/.python-version +0 -0
  12. {fotolab-0.13.0 → fotolab-0.14.0}/CONTRIBUTING.md +0 -0
  13. {fotolab-0.13.0 → fotolab-0.14.0}/LICENSE.md +0 -0
  14. {fotolab-0.13.0 → fotolab-0.14.0}/Pipfile +0 -0
  15. {fotolab-0.13.0 → fotolab-0.14.0}/docs/Makefile +0 -0
  16. {fotolab-0.13.0 → fotolab-0.14.0}/docs/make.bat +0 -0
  17. {fotolab-0.13.0 → fotolab-0.14.0}/docs/source/CHANGELOG.md +0 -0
  18. {fotolab-0.13.0 → fotolab-0.14.0}/docs/source/CONTRIBUTING.md +0 -0
  19. {fotolab-0.13.0 → fotolab-0.14.0}/docs/source/LICENSE.md +0 -0
  20. {fotolab-0.13.0 → fotolab-0.14.0}/docs/source/README.md +0 -0
  21. {fotolab-0.13.0 → fotolab-0.14.0}/docs/source/_static/logo.jpg +0 -0
  22. {fotolab-0.13.0 → fotolab-0.14.0}/docs/source/conf.py +0 -0
  23. {fotolab-0.13.0 → fotolab-0.14.0}/docs/source/index.rst +0 -0
  24. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/__main__.py +0 -0
  25. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/auto.py +0 -0
  26. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/border.py +0 -0
  27. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/contrast.py +0 -0
  28. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/env.py +0 -0
  29. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/info.py +0 -0
  30. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/montage.py +0 -0
  31. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/resize.py +0 -0
  32. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/sharpen.py +0 -0
  33. {fotolab-0.13.0 → fotolab-0.14.0}/fotolab/watermark.py +0 -0
  34. {fotolab-0.13.0 → fotolab-0.14.0}/pyproject.toml +0 -0
  35. {fotolab-0.13.0 → fotolab-0.14.0}/tests/__init__.py +0 -0
  36. {fotolab-0.13.0 → fotolab-0.14.0}/tests/conftest.py +0 -0
  37. {fotolab-0.13.0 → fotolab-0.14.0}/tests/test_env.py +0 -0
  38. {fotolab-0.13.0 → fotolab-0.14.0}/tests/test_help_flag.py +0 -0
  39. {fotolab-0.13.0 → fotolab-0.14.0}/tests/test_quiet_flag.py +0 -0
  40. {fotolab-0.13.0 → fotolab-0.14.0}/tox.ini +0 -0
@@ -45,7 +45,7 @@ repos:
45
45
  - --py=312
46
46
 
47
47
  - repo: https://github.com/psf/black
48
- rev: 24.4.0
48
+ rev: 24.4.2
49
49
  hooks:
50
50
  - id: black
51
51
  language_version: python3.12
@@ -107,7 +107,7 @@ repos:
107
107
  - --disable=R0801,W0212
108
108
 
109
109
  - repo: https://github.com/pre-commit/mirrors-mypy
110
- rev: v1.9.0
110
+ rev: v1.10.0
111
111
  hooks:
112
112
  - id: mypy
113
113
  exclude: docs/
@@ -7,6 +7,16 @@ and this project adheres to [0-based versioning](https://0ver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## v0.14.0 (2024-04-28)
11
+
12
+ ### Added
13
+
14
+ - Add `animate` subcommand to create animated `gif` image
15
+
16
+ ### Changed
17
+
18
+ - Bump deps and `pre-commit` hooks
19
+
10
20
  ## v0.13.0 (2024-04-21)
11
21
 
12
22
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fotolab
3
- Version: 0.13.0
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>
@@ -57,8 +57,9 @@ fotolab -h
57
57
  ```
58
58
 
59
59
  ```console
60
+
60
61
  usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-d] [-V]
61
- {auto,border,contrast,info,resize,montage,sharpen,watermark,env}
62
+ {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
62
63
  ...
63
64
 
64
65
  A console program to manipulate photos.
@@ -68,8 +69,9 @@ 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,info,resize,montage,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
@@ -91,6 +93,29 @@ optional arguments:
91
93
  -V, --version show program's version number and exit
92
94
  ```
93
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
+
94
119
  ### fotolab auto
95
120
 
96
121
  ```console
@@ -261,11 +261,11 @@
261
261
  },
262
262
  "identify": {
263
263
  "hashes": [
264
- "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791",
265
- "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"
264
+ "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa",
265
+ "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"
266
266
  ],
267
267
  "markers": "python_version >= '3.8'",
268
- "version": "==2.5.35"
268
+ "version": "==2.5.36"
269
269
  },
270
270
  "importlib-metadata": {
271
271
  "hashes": [
@@ -394,11 +394,11 @@
394
394
  },
395
395
  "pluggy": {
396
396
  "hashes": [
397
- "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981",
398
- "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"
397
+ "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1",
398
+ "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"
399
399
  ],
400
400
  "markers": "python_version >= '3.8'",
401
- "version": "==1.4.0"
401
+ "version": "==1.5.0"
402
402
  },
403
403
  "pre-commit": {
404
404
  "hashes": [
@@ -860,12 +860,12 @@
860
860
  },
861
861
  "myst-parser": {
862
862
  "hashes": [
863
- "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14",
864
- "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead"
863
+ "sha256:0b4ae0b33a45800a748260cb40348c37089a8a456c35120609240bd1b32f9255",
864
+ "sha256:8ee926557b8e4c2940a1e62c5720e1667cfaf8480b94b1b9c77dc38e31d104aa"
865
865
  ],
866
866
  "index": "pypi",
867
867
  "markers": "python_version >= '3.8'",
868
- "version": "==2.0.0"
868
+ "version": "==3.0.0"
869
869
  },
870
870
  "packaging": {
871
871
  "hashes": [
@@ -35,8 +35,9 @@ fotolab -h
35
35
  ```
36
36
 
37
37
  ```console
38
+
38
39
  usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-d] [-V]
39
- {auto,border,contrast,info,resize,montage,sharpen,watermark,env}
40
+ {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
40
41
  ...
41
42
 
42
43
  A console program to manipulate photos.
@@ -46,8 +47,9 @@ A console program to manipulate photos.
46
47
  issues: https://github.com/kianmeng/fotolab/issues
47
48
 
48
49
  positional arguments:
49
- {auto,border,contrast,info,resize,montage,sharpen,watermark,env}
50
+ {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
50
51
  sub-command help
52
+ animate animate an image
51
53
  auto auto adjust (resize, contrast, and watermark) a photo
52
54
  border add border to image
53
55
  contrast contrast an image
@@ -69,6 +71,29 @@ optional arguments:
69
71
  -V, --version show program's version number and exit
70
72
  ```
71
73
 
74
+ ### fotolab animate
75
+
76
+ ```console
77
+ fotolab animate -h
78
+ ```
79
+
80
+ ```console
81
+
82
+ usage: fotolab animate [-h] [-f FORMAT] [-d DURATION] [-l LOOP]
83
+ IMAGE_FILENAMES [IMAGE_FILENAMES ...]
84
+
85
+ positional arguments:
86
+ IMAGE_FILENAMES set the image filenames
87
+
88
+ optional arguments:
89
+ -h, --help show this help message and exit
90
+ -f FORMAT, --format FORMAT
91
+ set the image format (default: 'gif')
92
+ -d DURATION, --duration DURATION
93
+ set the duration in milliseconds (default: '2500')
94
+ -l LOOP, --loop LOOP set the loop cycle (default: '0')
95
+ ```
96
+
72
97
  ### fotolab auto
73
98
 
74
99
  ```console
@@ -21,7 +21,7 @@ import subprocess
21
21
  import sys
22
22
  from pathlib import Path
23
23
 
24
- __version__ = "0.13.0"
24
+ __version__ = "0.14.0"
25
25
 
26
26
  log = logging.getLogger(__name__)
27
27
 
@@ -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)
@@ -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
@@ -121,6 +122,7 @@ def build_parser() -> argparse.ArgumentParser:
121
122
  )
122
123
 
123
124
  subparsers = parser.add_subparsers(help="sub-command help")
125
+ fotolab.animate.build_subparser(subparsers)
124
126
  fotolab.auto.build_subparser(subparsers)
125
127
  fotolab.border.build_subparser(subparsers)
126
128
  fotolab.contrast.build_subparser(subparsers)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes