fotolab 0.16.17__tar.gz → 0.18.1__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 (42) hide show
  1. {fotolab-0.16.17 → fotolab-0.18.1}/.pre-commit-config.yaml +1 -1
  2. fotolab-0.18.1/.python-version +5 -0
  3. {fotolab-0.16.17 → fotolab-0.18.1}/CHANGELOG.md +23 -0
  4. {fotolab-0.16.17 → fotolab-0.18.1}/PKG-INFO +5 -3
  5. {fotolab-0.16.17 → fotolab-0.18.1}/Pipfile.lock +37 -37
  6. {fotolab-0.16.17 → fotolab-0.18.1}/README.md +4 -2
  7. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/__init__.py +1 -1
  8. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/auto.py +2 -0
  9. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/cli.py +2 -3
  10. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/env.py +1 -3
  11. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/info.py +25 -4
  12. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/watermark.py +35 -3
  13. {fotolab-0.16.17 → fotolab-0.18.1}/noxfile.py +1 -6
  14. fotolab-0.16.17/.python-version +0 -5
  15. {fotolab-0.16.17 → fotolab-0.18.1}/.coveragerc +0 -0
  16. {fotolab-0.16.17 → fotolab-0.18.1}/.gitignore +0 -0
  17. {fotolab-0.16.17 → fotolab-0.18.1}/CONTRIBUTING.md +0 -0
  18. {fotolab-0.16.17 → fotolab-0.18.1}/LICENSE.md +0 -0
  19. {fotolab-0.16.17 → fotolab-0.18.1}/Pipfile +0 -0
  20. {fotolab-0.16.17 → fotolab-0.18.1}/docs/Makefile +0 -0
  21. {fotolab-0.16.17 → fotolab-0.18.1}/docs/make.bat +0 -0
  22. {fotolab-0.16.17 → fotolab-0.18.1}/docs/source/CHANGELOG.md +0 -0
  23. {fotolab-0.16.17 → fotolab-0.18.1}/docs/source/CONTRIBUTING.md +0 -0
  24. {fotolab-0.16.17 → fotolab-0.18.1}/docs/source/LICENSE.md +0 -0
  25. {fotolab-0.16.17 → fotolab-0.18.1}/docs/source/README.md +0 -0
  26. {fotolab-0.16.17 → fotolab-0.18.1}/docs/source/_static/logo.jpg +0 -0
  27. {fotolab-0.16.17 → fotolab-0.18.1}/docs/source/conf.py +0 -0
  28. {fotolab-0.16.17 → fotolab-0.18.1}/docs/source/index.rst +0 -0
  29. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/__main__.py +0 -0
  30. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/animate.py +0 -0
  31. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/border.py +0 -0
  32. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/contrast.py +0 -0
  33. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/montage.py +0 -0
  34. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/resize.py +0 -0
  35. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/rotate.py +0 -0
  36. {fotolab-0.16.17 → fotolab-0.18.1}/fotolab/sharpen.py +0 -0
  37. {fotolab-0.16.17 → fotolab-0.18.1}/pyproject.toml +0 -0
  38. {fotolab-0.16.17 → fotolab-0.18.1}/tests/__init__.py +0 -0
  39. {fotolab-0.16.17 → fotolab-0.18.1}/tests/conftest.py +0 -0
  40. {fotolab-0.16.17 → fotolab-0.18.1}/tests/test_env.py +0 -0
  41. {fotolab-0.16.17 → fotolab-0.18.1}/tests/test_help_flag.py +0 -0
  42. {fotolab-0.16.17 → fotolab-0.18.1}/tests/test_quiet_flag.py +0 -0
@@ -15,7 +15,7 @@ repos:
15
15
  - id: trailing-whitespace
16
16
 
17
17
  - repo: https://github.com/abravalheri/validate-pyproject
18
- rev: v0.19
18
+ rev: v0.20.2
19
19
  hooks:
20
20
  - id: validate-pyproject
21
21
  name: validate-pyproject
@@ -0,0 +1,5 @@
1
+ 3.8.20
2
+ 3.9.20
3
+ 3.10.15
4
+ 3.11.10
5
+ 3.12.7
@@ -7,6 +7,29 @@ and this project adheres to [0-based versioning](https://0ver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## v0.18.1 (2024-10-06)
11
+
12
+ - Bump deps and Python version in `pyenv`
13
+ - Use `prog` field in `argparse` when show program version
14
+ - Set watermark text default to lowercase
15
+
16
+ ## v0.18.0 (2024-09-29)
17
+
18
+ - Add `--camera` flag to `watermark` subcommand to use camera's metadata as text
19
+ - Add `--lowercase` flag to `watermark` subcommand to use lowercase the watermark text
20
+ - Bump deps and `pre-commit` hooks
21
+
22
+ ## v0.17.0 (2024-09-22)
23
+
24
+ - Bump Python versions for `pyenv`
25
+ - Filter out image with `None` info field name
26
+ - Show image info by sorted field name using `-s` or `--sort` flag
27
+
28
+ ## v0.16.18 (2024-09-15)
29
+
30
+ - Bump deps
31
+ - Refactor showing stacktrace based on raw args
32
+
10
33
  ## v0.16.17 (2024-09-08)
11
34
 
12
35
  - Add `posargs` to most sessions in `nox`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fotolab
3
- Version: 0.16.17
3
+ Version: 0.18.1
4
4
  Summary: A console program that manipulate images.
5
5
  Keywords: photography,photo
6
6
  Author-email: Kian-Meng Ang <kianmeng@cpan.org>
@@ -210,13 +210,14 @@ fotolab info -h
210
210
  <!--help-info !-->
211
211
 
212
212
  ```console
213
- usage: fotolab info [-h] IMAGE_FILENAME
213
+ usage: fotolab info [-h] [-s] IMAGE_FILENAME
214
214
 
215
215
  positional arguments:
216
216
  IMAGE_FILENAME set the image filename
217
217
 
218
218
  options:
219
219
  -h, --help show this help message and exit
220
+ -s, --sort show image info by sorted field name
220
221
  ```
221
222
 
222
223
  <!--help-info !-->
@@ -327,7 +328,7 @@ fotolab watermark -h
327
328
  usage: fotolab watermark [-h] [-t WATERMARK_TEXT]
328
329
  [-p {top-left,top-right,bottom-left,bottom-right}]
329
330
  [-pd PADDING] [-fs FONT_SIZE] [-fc FONT_COLOR]
330
- [-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR]
331
+ [-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR] [--camera]
331
332
  IMAGE_FILENAMES [IMAGE_FILENAMES ...]
332
333
 
333
334
  positional arguments:
@@ -354,6 +355,7 @@ options:
354
355
  -oc OUTLINE_COLOR, --outline-color OUTLINE_COLOR
355
356
  set the outline color of the watermark text (default:
356
357
  'black')
358
+ --camera use camera metadata as watermark
357
359
  ```
358
360
 
359
361
  <!--help-watermark !-->
@@ -372,11 +372,11 @@
372
372
  },
373
373
  "filelock": {
374
374
  "hashes": [
375
- "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb",
376
- "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"
375
+ "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0",
376
+ "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"
377
377
  ],
378
378
  "markers": "python_version >= '3.8'",
379
- "version": "==3.15.4"
379
+ "version": "==3.16.1"
380
380
  },
381
381
  "flake8": {
382
382
  "hashes": [
@@ -436,19 +436,19 @@
436
436
  },
437
437
  "identify": {
438
438
  "hashes": [
439
- "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf",
440
- "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"
439
+ "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0",
440
+ "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"
441
441
  ],
442
442
  "markers": "python_version >= '3.8'",
443
- "version": "==2.6.0"
443
+ "version": "==2.6.1"
444
444
  },
445
445
  "idna": {
446
446
  "hashes": [
447
- "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac",
448
- "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"
447
+ "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
448
+ "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
449
449
  ],
450
450
  "markers": "python_version >= '3.6'",
451
- "version": "==3.8"
451
+ "version": "==3.10"
452
452
  },
453
453
  "imagesize": {
454
454
  "hashes": [
@@ -460,12 +460,12 @@
460
460
  },
461
461
  "importlib-metadata": {
462
462
  "hashes": [
463
- "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1",
464
- "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"
463
+ "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b",
464
+ "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"
465
465
  ],
466
466
  "index": "pypi",
467
467
  "markers": "python_version >= '3.8'",
468
- "version": "==8.4.0"
468
+ "version": "==8.5.0"
469
469
  },
470
470
  "iniconfig": {
471
471
  "hashes": [
@@ -567,11 +567,11 @@
567
567
  },
568
568
  "mdit-py-plugins": {
569
569
  "hashes": [
570
- "sha256:1020dfe4e6bfc2c79fb49ae4e3f5b297f5ccd20f010187acc52af2921e27dc6a",
571
- "sha256:834b8ac23d1cd60cec703646ffd22ae97b7955a6d596eb1d304be1e251ae499c"
570
+ "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636",
571
+ "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"
572
572
  ],
573
573
  "markers": "python_version >= '3.8'",
574
- "version": "==0.4.1"
574
+ "version": "==0.4.2"
575
575
  },
576
576
  "mdurl": {
577
577
  "hashes": [
@@ -704,11 +704,11 @@
704
704
  },
705
705
  "platformdirs": {
706
706
  "hashes": [
707
- "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee",
708
- "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"
707
+ "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907",
708
+ "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"
709
709
  ],
710
710
  "markers": "python_version >= '3.8'",
711
- "version": "==4.2.2"
711
+ "version": "==4.3.6"
712
712
  },
713
713
  "pluggy": {
714
714
  "hashes": [
@@ -761,12 +761,12 @@
761
761
  },
762
762
  "pytest": {
763
763
  "hashes": [
764
- "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5",
765
- "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"
764
+ "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181",
765
+ "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"
766
766
  ],
767
767
  "index": "pypi",
768
768
  "markers": "python_version >= '3.8'",
769
- "version": "==8.3.2"
769
+ "version": "==8.3.3"
770
770
  },
771
771
  "pytest-cov": {
772
772
  "hashes": [
@@ -887,12 +887,12 @@
887
887
  },
888
888
  "sphinx-autodoc-typehints": {
889
889
  "hashes": [
890
- "sha256:8f8281654ddf5709875429b7120d367f4edee39a131e13d5806e4f779a81bf0f",
891
- "sha256:c9774d47e7d304cf975e073df49ebf19763dca94ac0295e7013b522b26cb18de"
890
+ "sha256:940de2951fd584d147e46772579fdc904f945c5f1ee1a78c614646abfbbef18b",
891
+ "sha256:e743512da58b67a06579a1462798a6907664ab77460758a43234adeac350afbf"
892
892
  ],
893
893
  "index": "pypi",
894
894
  "markers": "python_version >= '3.10'",
895
- "version": "==2.4.0"
895
+ "version": "==2.4.4"
896
896
  },
897
897
  "sphinx-copybutton": {
898
898
  "hashes": [
@@ -953,36 +953,36 @@
953
953
  },
954
954
  "tomli": {
955
955
  "hashes": [
956
- "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
957
- "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
956
+ "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38",
957
+ "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"
958
958
  ],
959
959
  "index": "pypi",
960
- "markers": "python_version >= '3.7'",
961
- "version": "==2.0.1"
960
+ "markers": "python_version >= '3.8'",
961
+ "version": "==2.0.2"
962
962
  },
963
963
  "urllib3": {
964
964
  "hashes": [
965
- "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472",
966
- "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"
965
+ "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac",
966
+ "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"
967
967
  ],
968
968
  "markers": "python_version >= '3.8'",
969
- "version": "==2.2.2"
969
+ "version": "==2.2.3"
970
970
  },
971
971
  "virtualenv": {
972
972
  "hashes": [
973
- "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a",
974
- "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"
973
+ "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48",
974
+ "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2"
975
975
  ],
976
976
  "markers": "python_version >= '3.7'",
977
- "version": "==20.26.3"
977
+ "version": "==20.26.6"
978
978
  },
979
979
  "zipp": {
980
980
  "hashes": [
981
- "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064",
982
- "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"
981
+ "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350",
982
+ "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"
983
983
  ],
984
984
  "markers": "python_version >= '3.8'",
985
- "version": "==3.20.1"
985
+ "version": "==3.20.2"
986
986
  }
987
987
  }
988
988
  }
@@ -188,13 +188,14 @@ fotolab info -h
188
188
  <!--help-info !-->
189
189
 
190
190
  ```console
191
- usage: fotolab info [-h] IMAGE_FILENAME
191
+ usage: fotolab info [-h] [-s] IMAGE_FILENAME
192
192
 
193
193
  positional arguments:
194
194
  IMAGE_FILENAME set the image filename
195
195
 
196
196
  options:
197
197
  -h, --help show this help message and exit
198
+ -s, --sort show image info by sorted field name
198
199
  ```
199
200
 
200
201
  <!--help-info !-->
@@ -305,7 +306,7 @@ fotolab watermark -h
305
306
  usage: fotolab watermark [-h] [-t WATERMARK_TEXT]
306
307
  [-p {top-left,top-right,bottom-left,bottom-right}]
307
308
  [-pd PADDING] [-fs FONT_SIZE] [-fc FONT_COLOR]
308
- [-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR]
309
+ [-ow OUTLINE_WIDTH] [-oc OUTLINE_COLOR] [--camera]
309
310
  IMAGE_FILENAMES [IMAGE_FILENAMES ...]
310
311
 
311
312
  positional arguments:
@@ -332,6 +333,7 @@ options:
332
333
  -oc OUTLINE_COLOR, --outline-color OUTLINE_COLOR
333
334
  set the outline color of the watermark text (default:
334
335
  'black')
336
+ --camera use camera metadata as watermark
335
337
  ```
336
338
 
337
339
  <!--help-watermark !-->
@@ -21,7 +21,7 @@ import subprocess
21
21
  import sys
22
22
  from pathlib import Path
23
23
 
24
- __version__ = "0.16.17"
24
+ __version__ = "0.18.1"
25
25
 
26
26
  log = logging.getLogger(__name__)
27
27
 
@@ -67,6 +67,8 @@ def run(args: argparse.Namespace) -> None:
67
67
  "outline_width": 2,
68
68
  "outline_color": "black",
69
69
  "padding": 15,
70
+ "camera": False,
71
+ "lowercase": False,
70
72
  }
71
73
  combined_args = argparse.Namespace(**vars(args), **extra_args)
72
74
  combined_args.overwrite = True
@@ -132,7 +132,7 @@ def build_parser() -> argparse.ArgumentParser:
132
132
  "-V",
133
133
  "--version",
134
134
  action="version",
135
- version=f"fotolab {__version__}",
135
+ version=f"%(prog)s {__version__}",
136
136
  )
137
137
 
138
138
  subparsers = parser.add_subparsers(help="sub-command help")
@@ -154,7 +154,6 @@ def build_parser() -> argparse.ArgumentParser:
154
154
  def main(args: Optional[Sequence[str]] = None) -> None:
155
155
  """Run the main program flow."""
156
156
  args = args or sys.argv[1:]
157
- parsed_args = argparse.Namespace(debug=True)
158
157
  log.debug(args)
159
158
 
160
159
  try:
@@ -175,7 +174,7 @@ def main(args: Optional[Sequence[str]] = None) -> None:
175
174
  log.error(
176
175
  "error: %s",
177
176
  getattr(error, "message", str(error)),
178
- exc_info=getattr(parsed_args, "debug", True),
177
+ exc_info=("-d" in args or "--debug" in args),
179
178
  )
180
179
 
181
180
  raise SystemExit(1) from None
@@ -34,7 +34,7 @@ def build_subparser(subparsers) -> None:
34
34
  env_parser.set_defaults(func=run)
35
35
 
36
36
 
37
- def run(args: argparse.Namespace) -> None:
37
+ def run(_args: argparse.Namespace) -> None:
38
38
  """Run env subcommand.
39
39
 
40
40
  Args:
@@ -43,8 +43,6 @@ def run(args: argparse.Namespace) -> None:
43
43
  Returns:
44
44
  None
45
45
  """
46
- log.debug(args)
47
-
48
46
  sys_version = sys.version.replace("\n", "")
49
47
  print(
50
48
  f"fotolab: {__version__}",
@@ -37,6 +37,15 @@ def build_subparser(subparsers) -> None:
37
37
  metavar="IMAGE_FILENAME",
38
38
  )
39
39
 
40
+ info_parser.add_argument(
41
+ "-s",
42
+ "--sort",
43
+ default=False,
44
+ action="store_true",
45
+ dest="sort",
46
+ help="show image info by sorted field name",
47
+ )
48
+
40
49
 
41
50
  def run(args: argparse.Namespace) -> None:
42
51
  """Run info subcommand.
@@ -49,10 +58,22 @@ def run(args: argparse.Namespace) -> None:
49
58
  """
50
59
  log.debug(args)
51
60
 
52
- image = Image.open(args.image_filename)
61
+ exif_tags = extract_exif_tags(args.image.filename)
62
+ tag_name_width = max(map(len, exif_tags))
63
+ for tag_name, tag_value in exif_tags.items():
64
+ print(f"{tag_name:<{tag_name_width}}: {tag_value}")
65
+
66
+
67
+ def extract_exif_tags(image_filename: str, sort: bool = False) -> dict:
68
+ """Extract Exif metadata from image."""
69
+ image = Image.open(image_filename)
53
70
  exif = image._getexif()
54
71
  info = {ExifTags.TAGS.get(tag_id): exif.get(tag_id) for tag_id in exif}
55
72
 
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}")
73
+ filtered_info = {
74
+ key: value for key, value in info.items() if key is not None
75
+ }
76
+ if sort:
77
+ filtered_info = dict(sorted(filtered_info.items()))
78
+
79
+ return filtered_info
@@ -22,6 +22,7 @@ import math
22
22
  from PIL import Image, ImageColor, ImageDraw, ImageFont
23
23
 
24
24
  from fotolab import save_image
25
+ from fotolab.info import extract_exif_tags
25
26
 
26
27
  log = logging.getLogger(__name__)
27
28
 
@@ -126,12 +127,29 @@ def build_subparser(subparsers) -> None:
126
127
  metavar="OUTLINE_COLOR",
127
128
  )
128
129
 
130
+ watermark_parser.add_argument(
131
+ "--camera",
132
+ default=False,
133
+ action="store_true",
134
+ dest="camera",
135
+ help="use camera metadata as watermark",
136
+ )
137
+
138
+ watermark_parser.add_argument(
139
+ "-l",
140
+ "--lowercase",
141
+ default=True,
142
+ action="store_true",
143
+ dest="lowercase",
144
+ help="lowercase the watermark text",
145
+ )
146
+
129
147
 
130
148
  def run(args: argparse.Namespace) -> None:
131
149
  """Run watermark subcommand.
132
150
 
133
151
  Args:
134
- config (argparse.Namespace): Config from command line arguments
152
+ args (argparse.Namespace): Config from command line arguments
135
153
 
136
154
  Returns:
137
155
  None
@@ -147,8 +165,15 @@ def run(args: argparse.Namespace) -> None:
147
165
  font = ImageFont.load_default(calc_font_size(original_image, args))
148
166
  log.debug("default font: %s", " ".join(font.getname()))
149
167
 
168
+ text = args.text
169
+ if args.camera and camera_metadata(image_filename):
170
+ text = camera_metadata(image_filename)
171
+
172
+ if args.lowercase:
173
+ text = text.lower()
174
+
150
175
  (left, top, right, bottom) = draw.textbbox(
151
- xy=(0, 0), text=args.text, font=font
176
+ xy=(0, 0), text=text, font=font
152
177
  )
153
178
  text_width = right - left
154
179
  text_height = bottom - top
@@ -162,7 +187,7 @@ def run(args: argparse.Namespace) -> None:
162
187
 
163
188
  draw.text(
164
189
  (position_x, position_y),
165
- args.text,
190
+ text,
166
191
  font=font,
167
192
  fill=(*ImageColor.getrgb(args.font_color), 128),
168
193
  stroke_width=calc_font_outline_width(original_image, args),
@@ -172,6 +197,13 @@ def run(args: argparse.Namespace) -> None:
172
197
  save_image(args, watermarked_image, image_filename, "watermark")
173
198
 
174
199
 
200
+ def camera_metadata(image_filename):
201
+ """Extract camera and model metadata."""
202
+ exif_tags = extract_exif_tags(image_filename)
203
+ metadata = f'{exif_tags["Make"]} {exif_tags["Model"]}'
204
+ return metadata.strip()
205
+
206
+
175
207
  def calc_font_size(image, args) -> int:
176
208
  """Calculate the font size based on the width of the image."""
177
209
  width, _height = image.size
@@ -152,12 +152,7 @@ def release(_session: nox.Session) -> None:
152
152
 
153
153
  def _pipenv_install(session: nox.Session) -> None:
154
154
  session.install("pipenv")
155
- session.run(
156
- "pipenv",
157
- "install",
158
- "--dev",
159
- env={"PIPENV_VERBOSITY": "-1"}
160
- )
155
+ session.run("pipenv", "install", "--dev", env={"PIPENV_VERBOSITY": "-1"})
161
156
 
162
157
 
163
158
  def _search_and_replace(file, search, replace) -> None:
@@ -1,5 +0,0 @@
1
- 3.8.19
2
- 3.9.19
3
- 3.10.14
4
- 3.11.9
5
- 3.12.5
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