fotolab 0.24.0__tar.gz → 0.25.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.
- {fotolab-0.24.0 → fotolab-0.25.1}/.pre-commit-config.yaml +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/CHANGELOG.md +12 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/PKG-INFO +4 -3
- {fotolab-0.24.0 → fotolab-0.25.1}/Pipfile.lock +72 -76
- {fotolab-0.24.0 → fotolab-0.25.1}/README.md +3 -2
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/__init__.py +2 -2
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/cli.py +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/__init__.py +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/animate.py +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/auto.py +2 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/border.py +20 -17
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/contrast.py +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/env.py +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/info.py +1 -2
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/montage.py +4 -4
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/resize.py +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/rotate.py +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/sharpen.py +40 -3
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/subcommands/watermark.py +1 -1
- {fotolab-0.24.0 → fotolab-0.25.1}/.coveragerc +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/.gitignore +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/.python-version +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/CONTRIBUTING.md +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/LICENSE.md +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/Pipfile +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/Makefile +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/make.bat +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/source/CHANGELOG.md +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/source/CONTRIBUTING.md +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/source/LICENSE.md +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/source/README.md +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/source/_static/logo.jpg +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/source/conf.py +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/docs/source/index.rst +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/fotolab/__main__.py +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/noxfile.py +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/pyproject.toml +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/tests/__init__.py +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/tests/conftest.py +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/tests/test_env.py +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/tests/test_help_flag.py +0 -0
- {fotolab-0.24.0 → fotolab-0.25.1}/tests/test_quiet_flag.py +0 -0
@@ -7,6 +7,18 @@ and this project adheres to [0-based versioning](https://0ver.org/).
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
## v0.25.1 (2025-01-13)
|
11
|
+
|
12
|
+
- Bump deps
|
13
|
+
- Fix incorrect subcommand when saving image with border
|
14
|
+
- Refactor calculate border
|
15
|
+
|
16
|
+
## v0.25.0 (2025-01-05)
|
17
|
+
|
18
|
+
- Add `--before-after` or `-ba` flag to `sharpen` command
|
19
|
+
- Bump `pre-commit` hook and deps
|
20
|
+
- Bump copyright years
|
21
|
+
|
10
22
|
## v0.24.0 (2024-12-29)
|
11
23
|
|
12
24
|
- Bump `pre-commit` hook
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fotolab
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.25.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>
|
@@ -300,7 +300,7 @@ fotolab sharpen -h
|
|
300
300
|
<!--help-sharpen !-->
|
301
301
|
|
302
302
|
```console
|
303
|
-
usage: fotolab sharpen [-h] [-r RADIUS] [-p PERCENT] [-t THRESHOLD]
|
303
|
+
usage: fotolab sharpen [-h] [-r RADIUS] [-p PERCENT] [-t THRESHOLD] [-ba]
|
304
304
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
305
305
|
|
306
306
|
positional arguments:
|
@@ -315,6 +315,7 @@ options:
|
|
315
315
|
-t, --threshold THRESHOLD
|
316
316
|
set the minimum brightness changed to be sharpened
|
317
317
|
(default: '3')
|
318
|
+
-ba, --before-after generate a GIF showing before and after changes
|
318
319
|
```
|
319
320
|
|
320
321
|
<!--help-sharpen !-->
|
@@ -385,7 +386,7 @@ options:
|
|
385
386
|
|
386
387
|
## Copyright and License
|
387
388
|
|
388
|
-
Copyright (C) 2024 Kian-Meng Ang
|
389
|
+
Copyright (C) 2024,2025 Kian-Meng Ang
|
389
390
|
|
390
391
|
This program is free software: you can redistribute it and/or modify it under
|
391
392
|
the terms of the GNU Affero General Public License as published by the Free
|
@@ -22,85 +22,81 @@
|
|
22
22
|
},
|
23
23
|
"pillow": {
|
24
24
|
"hashes": [
|
25
|
-
"sha256:
|
26
|
-
"sha256:
|
27
|
-
"sha256:
|
28
|
-
"sha256:
|
29
|
-
"sha256:
|
30
|
-
"sha256:
|
31
|
-
"sha256:
|
32
|
-
"sha256:
|
33
|
-
"sha256:
|
34
|
-
"sha256:
|
35
|
-
"sha256:
|
36
|
-
"sha256:
|
37
|
-
"sha256:
|
38
|
-
"sha256:
|
39
|
-
"sha256:
|
40
|
-
"sha256:
|
41
|
-
"sha256:
|
42
|
-
"sha256:
|
43
|
-
"sha256:
|
44
|
-
"sha256:
|
45
|
-
"sha256:
|
46
|
-
"sha256:
|
47
|
-
"sha256:
|
48
|
-
"sha256:
|
49
|
-
"sha256:
|
50
|
-
"sha256:
|
51
|
-
"sha256:
|
52
|
-
"sha256:
|
53
|
-
"sha256:
|
54
|
-
"sha256:
|
55
|
-
"sha256:
|
56
|
-
"sha256:
|
57
|
-
"sha256:
|
58
|
-
"sha256:
|
59
|
-
"sha256:
|
60
|
-
"sha256:
|
61
|
-
"sha256:
|
62
|
-
"sha256:
|
63
|
-
"sha256:
|
64
|
-
"sha256:
|
65
|
-
"sha256:
|
66
|
-
"sha256:
|
67
|
-
"sha256:
|
68
|
-
"sha256:
|
69
|
-
"sha256:
|
70
|
-
"sha256:
|
71
|
-
"sha256:
|
72
|
-
"sha256:
|
73
|
-
"sha256:
|
74
|
-
"sha256:
|
75
|
-
"sha256:
|
76
|
-
"sha256:
|
77
|
-
"sha256:
|
78
|
-
"sha256:
|
79
|
-
"sha256:
|
80
|
-
"sha256:
|
81
|
-
"sha256:
|
82
|
-
"sha256:
|
83
|
-
"sha256:
|
84
|
-
"sha256:
|
85
|
-
"sha256:
|
86
|
-
"sha256:
|
87
|
-
"sha256:
|
88
|
-
"sha256:
|
89
|
-
"sha256:
|
90
|
-
"sha256:
|
91
|
-
"sha256:
|
92
|
-
"sha256:
|
93
|
-
"sha256:
|
94
|
-
"sha256:
|
95
|
-
"sha256:
|
96
|
-
"sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798",
|
97
|
-
"sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb",
|
98
|
-
"sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2",
|
99
|
-
"sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"
|
25
|
+
"sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83",
|
26
|
+
"sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96",
|
27
|
+
"sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65",
|
28
|
+
"sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a",
|
29
|
+
"sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352",
|
30
|
+
"sha256:3362c6ca227e65c54bf71a5f88b3d4565ff1bcbc63ae72c34b07bbb1cc59a43f",
|
31
|
+
"sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20",
|
32
|
+
"sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c",
|
33
|
+
"sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114",
|
34
|
+
"sha256:3a5fe20a7b66e8135d7fd617b13272626a28278d0e578c98720d9ba4b2439d49",
|
35
|
+
"sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91",
|
36
|
+
"sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0",
|
37
|
+
"sha256:4db853948ce4e718f2fc775b75c37ba2efb6aaea41a1a5fc57f0af59eee774b2",
|
38
|
+
"sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5",
|
39
|
+
"sha256:54251ef02a2309b5eec99d151ebf5c9904b77976c8abdcbce7891ed22df53884",
|
40
|
+
"sha256:54ce1c9a16a9561b6d6d8cb30089ab1e5eb66918cb47d457bd996ef34182922e",
|
41
|
+
"sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c",
|
42
|
+
"sha256:5bb94705aea800051a743aa4874bb1397d4695fb0583ba5e425ee0328757f196",
|
43
|
+
"sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756",
|
44
|
+
"sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861",
|
45
|
+
"sha256:73ddde795ee9b06257dac5ad42fcb07f3b9b813f8c1f7f870f402f4dc54b5269",
|
46
|
+
"sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1",
|
47
|
+
"sha256:7d33d2fae0e8b170b6a6c57400e077412240f6f5bb2a342cf1ee512a787942bb",
|
48
|
+
"sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a",
|
49
|
+
"sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081",
|
50
|
+
"sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1",
|
51
|
+
"sha256:89dbdb3e6e9594d512780a5a1c42801879628b38e3efc7038094430844e271d8",
|
52
|
+
"sha256:8c730dc3a83e5ac137fbc92dfcfe1511ce3b2b5d7578315b63dbbb76f7f51d90",
|
53
|
+
"sha256:8e275ee4cb11c262bd108ab2081f750db2a1c0b8c12c1897f27b160c8bd57bbc",
|
54
|
+
"sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5",
|
55
|
+
"sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1",
|
56
|
+
"sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3",
|
57
|
+
"sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35",
|
58
|
+
"sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f",
|
59
|
+
"sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c",
|
60
|
+
"sha256:a07dba04c5e22824816b2615ad7a7484432d7f540e6fa86af60d2de57b0fcee2",
|
61
|
+
"sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2",
|
62
|
+
"sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf",
|
63
|
+
"sha256:a76da0a31da6fcae4210aa94fd779c65c75786bc9af06289cd1c184451ef7a65",
|
64
|
+
"sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b",
|
65
|
+
"sha256:a8d65b38173085f24bc07f8b6c505cbb7418009fa1a1fcb111b1f4961814a442",
|
66
|
+
"sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2",
|
67
|
+
"sha256:ab8a209b8485d3db694fa97a896d96dd6533d63c22829043fd9de627060beade",
|
68
|
+
"sha256:abc56501c3fd148d60659aae0af6ddc149660469082859fa7b066a298bde9482",
|
69
|
+
"sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe",
|
70
|
+
"sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc",
|
71
|
+
"sha256:b20be51b37a75cc54c2c55def3fa2c65bb94ba859dde241cd0a4fd302de5ae0a",
|
72
|
+
"sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec",
|
73
|
+
"sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3",
|
74
|
+
"sha256:b6123aa4a59d75f06e9dd3dac5bf8bc9aa383121bb3dd9a7a612e05eabc9961a",
|
75
|
+
"sha256:bd165131fd51697e22421d0e467997ad31621b74bfc0b75956608cb2906dda07",
|
76
|
+
"sha256:bf902d7413c82a1bfa08b06a070876132a5ae6b2388e2712aab3a7cbc02205c6",
|
77
|
+
"sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f",
|
78
|
+
"sha256:c1eec9d950b6fe688edee07138993e54ee4ae634c51443cfb7c1e7613322718e",
|
79
|
+
"sha256:c640e5a06869c75994624551f45e5506e4256562ead981cce820d5ab39ae2192",
|
80
|
+
"sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0",
|
81
|
+
"sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6",
|
82
|
+
"sha256:d3d8da4a631471dfaf94c10c85f5277b1f8e42ac42bade1ac67da4b4a7359b73",
|
83
|
+
"sha256:d44ff19eea13ae4acdaaab0179fa68c0c6f2f45d66a4d8ec1eda7d6cecbcc15f",
|
84
|
+
"sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6",
|
85
|
+
"sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547",
|
86
|
+
"sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9",
|
87
|
+
"sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457",
|
88
|
+
"sha256:e1abe69aca89514737465752b4bcaf8016de61b3be1397a8fc260ba33321b3a8",
|
89
|
+
"sha256:e267b0ed063341f3e60acd25c05200df4193e15a4a5807075cd71225a2386e26",
|
90
|
+
"sha256:e5449ca63da169a2e6068dd0e2fcc8d91f9558aba89ff6d02121ca8ab11e79e5",
|
91
|
+
"sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab",
|
92
|
+
"sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070",
|
93
|
+
"sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71",
|
94
|
+
"sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9",
|
95
|
+
"sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761"
|
100
96
|
],
|
101
97
|
"index": "pypi",
|
102
98
|
"markers": "python_version >= '3.9'",
|
103
|
-
"version": "==11.
|
99
|
+
"version": "==11.1.0"
|
104
100
|
}
|
105
101
|
},
|
106
102
|
"develop": {
|
@@ -277,7 +277,7 @@ fotolab sharpen -h
|
|
277
277
|
<!--help-sharpen !-->
|
278
278
|
|
279
279
|
```console
|
280
|
-
usage: fotolab sharpen [-h] [-r RADIUS] [-p PERCENT] [-t THRESHOLD]
|
280
|
+
usage: fotolab sharpen [-h] [-r RADIUS] [-p PERCENT] [-t THRESHOLD] [-ba]
|
281
281
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
282
282
|
|
283
283
|
positional arguments:
|
@@ -292,6 +292,7 @@ options:
|
|
292
292
|
-t, --threshold THRESHOLD
|
293
293
|
set the minimum brightness changed to be sharpened
|
294
294
|
(default: '3')
|
295
|
+
-ba, --before-after generate a GIF showing before and after changes
|
295
296
|
```
|
296
297
|
|
297
298
|
<!--help-sharpen !-->
|
@@ -362,7 +363,7 @@ options:
|
|
362
363
|
|
363
364
|
## Copyright and License
|
364
365
|
|
365
|
-
Copyright (C) 2024 Kian-Meng Ang
|
366
|
+
Copyright (C) 2024,2025 Kian-Meng Ang
|
366
367
|
|
367
368
|
This program is free software: you can redistribute it and/or modify it under
|
368
369
|
the terms of the GNU Affero General Public License as published by the Free
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2024 Kian-Meng Ang
|
1
|
+
# Copyright (C) 2024,2025 Kian-Meng Ang
|
2
2
|
#
|
3
3
|
# This program is free software: you can redistribute it and/or modify it under
|
4
4
|
# the terms of the GNU Affero General Public License as published by the Free
|
@@ -21,7 +21,7 @@ import subprocess
|
|
21
21
|
import sys
|
22
22
|
from pathlib import Path
|
23
23
|
|
24
|
-
__version__ = "0.
|
24
|
+
__version__ = "0.25.1"
|
25
25
|
|
26
26
|
log = logging.getLogger(__name__)
|
27
27
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2024 Kian-Meng Ang
|
1
|
+
# Copyright (C) 2024,2025 Kian-Meng Ang
|
2
2
|
#
|
3
3
|
# This program is free software: you can redistribute it and/or modify it under
|
4
4
|
# the terms of the GNU Affero General Public License as published by the Free
|
@@ -70,6 +70,7 @@ def run(args: argparse.Namespace) -> None:
|
|
70
70
|
"camera": False,
|
71
71
|
"canvas": False,
|
72
72
|
"lowercase": False,
|
73
|
+
"before_after": False,
|
73
74
|
}
|
74
75
|
combined_args = argparse.Namespace(**vars(args), **extra_args)
|
75
76
|
combined_args.overwrite = True
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2024 Kian-Meng Ang
|
1
|
+
# Copyright (C) 2024,2025 Kian-Meng Ang
|
2
2
|
#
|
3
3
|
# This program is free software: you can redistribute it and/or modify it under
|
4
4
|
# the terms of the GNU Affero General Public License as published by the Free
|
@@ -115,25 +115,28 @@ def run(args: argparse.Namespace) -> None:
|
|
115
115
|
for image_filename in args.image_filenames:
|
116
116
|
original_image = Image.open(image_filename)
|
117
117
|
|
118
|
-
|
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
|
-
|
118
|
+
border = get_border(args)
|
133
119
|
bordered_image = ImageOps.expand(
|
134
120
|
original_image,
|
135
121
|
border=border,
|
136
122
|
fill=ImageColor.getrgb(args.color),
|
137
123
|
)
|
138
124
|
|
139
|
-
save_image(args, bordered_image, image_filename, "
|
125
|
+
save_image(args, bordered_image, image_filename, "border")
|
126
|
+
|
127
|
+
|
128
|
+
def get_border(args: argparse.Namespace) -> tuple:
|
129
|
+
"""Calculate the border."""
|
130
|
+
if (
|
131
|
+
args.width_left
|
132
|
+
or args.width_top
|
133
|
+
or args.width_right
|
134
|
+
or args.width_bottom
|
135
|
+
):
|
136
|
+
return (
|
137
|
+
int(args.width_left),
|
138
|
+
int(args.width_top),
|
139
|
+
int(args.width_right),
|
140
|
+
int(args.width_bottom),
|
141
|
+
)
|
142
|
+
return args.width
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2024 Kian-Meng Ang
|
1
|
+
# Copyright (C) 2024,2025 Kian-Meng Ang
|
2
2
|
#
|
3
3
|
# This program is free software: you can redistribute it and/or modify it under
|
4
4
|
# the terms of the GNU Affero General Public License as published by the Free
|
@@ -97,7 +97,6 @@ def run(args: argparse.Namespace) -> None:
|
|
97
97
|
|
98
98
|
def extract_exif_tags(image: Image.Image, sort: bool = False) -> dict:
|
99
99
|
"""Extract Exif metadata from image."""
|
100
|
-
print(type(image))
|
101
100
|
exif = image._getexif()
|
102
101
|
log.debug(exif)
|
103
102
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2024 Kian-Meng Ang
|
1
|
+
# Copyright (C) 2024,2025 Kian-Meng Ang
|
2
2
|
#
|
3
3
|
# This program is free software: you can redistribute it and/or modify it under
|
4
4
|
# the terms of the GNU Affero General Public License as published by the Free
|
@@ -63,9 +63,9 @@ def run(args: argparse.Namespace) -> None:
|
|
63
63
|
montaged_image = Image.new("RGB", (total_width, total_height))
|
64
64
|
|
65
65
|
x_offset = 0
|
66
|
-
for
|
67
|
-
montaged_image.paste(
|
68
|
-
x_offset +=
|
66
|
+
for image in images:
|
67
|
+
montaged_image.paste(image, (x_offset, 0))
|
68
|
+
x_offset += image.width
|
69
69
|
|
70
70
|
output_image_filename = args.image_filenames[0].name
|
71
71
|
save_image(args, montaged_image, output_image_filename, "montage")
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2024 Kian-Meng Ang
|
1
|
+
# Copyright (C) 2024,2025 Kian-Meng Ang
|
2
2
|
#
|
3
3
|
# This program is free software: you can redistribute it and/or modify it under
|
4
4
|
# the terms of the GNU Affero General Public License as published by the Free
|
@@ -17,10 +17,11 @@
|
|
17
17
|
|
18
18
|
import argparse
|
19
19
|
import logging
|
20
|
+
from pathlib import Path
|
20
21
|
|
21
22
|
from PIL import Image, ImageFilter
|
22
23
|
|
23
|
-
from fotolab import save_image
|
24
|
+
from fotolab import _open_image, save_image
|
24
25
|
|
25
26
|
log = logging.getLogger(__name__)
|
26
27
|
|
@@ -76,6 +77,15 @@ def build_subparser(subparsers) -> None:
|
|
76
77
|
metavar="THRESHOLD",
|
77
78
|
)
|
78
79
|
|
80
|
+
sharpen_parser.add_argument(
|
81
|
+
"-ba",
|
82
|
+
"--before-after",
|
83
|
+
default=False,
|
84
|
+
action="store_true",
|
85
|
+
dest="before_after",
|
86
|
+
help="generate a GIF showing before and after changes",
|
87
|
+
)
|
88
|
+
|
79
89
|
|
80
90
|
def run(args: argparse.Namespace) -> None:
|
81
91
|
"""Run sharpen subcommand.
|
@@ -95,4 +105,31 @@ def run(args: argparse.Namespace) -> None:
|
|
95
105
|
args.radius, percent=args.percent, threshold=args.threshold
|
96
106
|
)
|
97
107
|
)
|
98
|
-
|
108
|
+
if args.before_after:
|
109
|
+
save_gif_image(args, image_filename, original_image, sharpen_image)
|
110
|
+
else:
|
111
|
+
save_image(args, sharpen_image, image_filename, "sharpen")
|
112
|
+
|
113
|
+
|
114
|
+
def save_gif_image(args, image_filename, original_image, sharpen_image):
|
115
|
+
"""Save the original and sharpen image."""
|
116
|
+
image_file = Path(image_filename)
|
117
|
+
new_filename = Path(
|
118
|
+
args.output_dir,
|
119
|
+
image_file.with_name(f"sharpen_gif_{image_file.stem}.gif"),
|
120
|
+
)
|
121
|
+
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
122
|
+
|
123
|
+
log.info("sharpen gif image: %s", new_filename)
|
124
|
+
original_image.save(
|
125
|
+
new_filename,
|
126
|
+
format="gif",
|
127
|
+
append_images=[sharpen_image],
|
128
|
+
save_all=True,
|
129
|
+
duration=2500,
|
130
|
+
loop=0,
|
131
|
+
optimize=True,
|
132
|
+
)
|
133
|
+
|
134
|
+
if args.open:
|
135
|
+
_open_image(new_filename)
|
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
|