format-img 0.1.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.
- format_img-0.1.0/.gitignore +10 -0
- format_img-0.1.0/LICENSE +21 -0
- format_img-0.1.0/PKG-INFO +108 -0
- format_img-0.1.0/README.md +98 -0
- format_img-0.1.0/pyproject.toml +21 -0
- format_img-0.1.0/scripts/update-datetime.ps1 +53 -0
- format_img-0.1.0/src/format_img/__init__.py +1 -0
- format_img-0.1.0/src/format_img/format_img.py +84 -0
- format_img-0.1.0/src/format_img/modify_exif.py +93 -0
- format_img-0.1.0/src/format_img/my_utility.py +75 -0
- format_img-0.1.0/uv.lock +48 -0
format_img-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 Martin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: format-img
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A python tool to format images based on EXIF information and edit EXIF data.
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Requires-Dist: exif>=1.3.5
|
|
8
|
+
Requires-Dist: exifread>=2.3.2
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# 图片名称格式化工具
|
|
12
|
+
## 根据 EXIF 信息来格式化图片名字,方便管理
|
|
13
|
+
|
|
14
|
+
## 环境与安装
|
|
15
|
+
|
|
16
|
+
本工具使用 `uv` 管理依赖和运行环境。
|
|
17
|
+
|
|
18
|
+
### 安装依赖并同步环境:
|
|
19
|
+
```bash
|
|
20
|
+
uv sync
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 用法
|
|
26
|
+
|
|
27
|
+
### 1. format-img
|
|
28
|
+
|
|
29
|
+
格式化当前目录下的图片文件名。
|
|
30
|
+
|
|
31
|
+
#### 基本用法
|
|
32
|
+
```bash
|
|
33
|
+
uv run format-img [-f format] [-s suffixs] [-h]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- `-f` 文件名的格式,默认值为 `%Y%m%d%H%M%S`。支持的占位符列表见下表。
|
|
37
|
+
- `-s` 要格式化文件名的后缀名列表(以逗号分隔,不区分大小写),默认值为 `jpg,png,jpeg,heic`。例如 `-s "jpg,png"`。
|
|
38
|
+
- `-h` 获取帮助信息。
|
|
39
|
+
|
|
40
|
+
#### 支持的格式占位符:
|
|
41
|
+
|
|
42
|
+
| 格式 | 含义 |
|
|
43
|
+
|---|---|
|
|
44
|
+
| %a | 本地(locale)简化星期名称 |
|
|
45
|
+
| %A | 本地完整星期名称 |
|
|
46
|
+
| %b | 本地简化月份名称 |
|
|
47
|
+
| %B | 本地完整月份名称 |
|
|
48
|
+
| %c | 本地相应的日期和时间表示 |
|
|
49
|
+
| %d | 一个月中的第几天(01 - 31) |
|
|
50
|
+
| %H | 一天中的第几个小时(24小时制,00 - 23) |
|
|
51
|
+
| %I | 第几个小时(12小时制,01 - 12) |
|
|
52
|
+
| %j | 一年中的第几天(001 - 366) |
|
|
53
|
+
| %m | 月份(01 - 12) |
|
|
54
|
+
| %M | 分钟数(00 - 59) |
|
|
55
|
+
| %p | 本地am或者pm的相应符 |
|
|
56
|
+
| %S | 秒(01 - 61) |
|
|
57
|
+
| %U | 一年中的星期数(00 - 53,星期天为一个星期的开始) |
|
|
58
|
+
| %w | 一个星期中的第几天(0 - 6,0是星期天) |
|
|
59
|
+
| %W | 和 %U 基本相同,不同的是以星期一为一个星期的开始 |
|
|
60
|
+
| %x | 本地相应日期 |
|
|
61
|
+
| %X | 本地相应时间 |
|
|
62
|
+
| %y | 去掉世纪的年份(00 - 99) |
|
|
63
|
+
| %Y | 完整的年份 |
|
|
64
|
+
| %Z | 时区的名字 |
|
|
65
|
+
| %% | '%' 字符 |
|
|
66
|
+
|
|
67
|
+
#### 示例
|
|
68
|
+
把当前目录下的 `jpg` 和 `png` 文件的名称格式化成 `2017-10-01 10:17:01` 的形式:
|
|
69
|
+
```bash
|
|
70
|
+
uv run format-img -s "jpg,png" -f "%Y-%m-%d %H:%M:%S"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### 2. modify-exif
|
|
76
|
+
|
|
77
|
+
用于读取/修改图片的 EXIF 信息。
|
|
78
|
+
|
|
79
|
+
#### 基本用法
|
|
80
|
+
```bash
|
|
81
|
+
# 读取属性详情
|
|
82
|
+
uv run modify-exif -f file -r property [-s]
|
|
83
|
+
|
|
84
|
+
# 读取拍摄时间与数字化时间(only output value if -s is set)
|
|
85
|
+
uv run modify-exif -f file -rt [-s]
|
|
86
|
+
|
|
87
|
+
# 写入指定属性
|
|
88
|
+
uv run modify-exif -f file -w property -v value
|
|
89
|
+
|
|
90
|
+
# 写入拍摄时间与数字化时间
|
|
91
|
+
uv run modify-exif -f file -wt -v value
|
|
92
|
+
|
|
93
|
+
# 查看帮助
|
|
94
|
+
uv run modify-exif -h
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
具体示例可以参考 `scripts/update-datetime.ps1`,用于批量修改目标文件夹里面 `yyyyMMddHHmmss` 这样命名规则图片的 EXIF 时间信息。
|
|
98
|
+
|
|
99
|
+
## 注意事项
|
|
100
|
+
|
|
101
|
+
**跨路径调用**:如果要在其他路径(即不是项目根目录)下调用本工具,建议使用 `--project` 参数指定项目路径,例如:
|
|
102
|
+
|
|
103
|
+
```powershell
|
|
104
|
+
uv --project D:\Development\format-img run format-img
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
使用 `--project` 可以确保 `uv` 能够找到该项目的环境与依赖,同时**不会**改变当前的工作路径(cwd),从而正确地对你当前所在的命令行路径下的图片进行格式化操作。
|
|
108
|
+
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# 图片名称格式化工具
|
|
2
|
+
## 根据 EXIF 信息来格式化图片名字,方便管理
|
|
3
|
+
|
|
4
|
+
## 环境与安装
|
|
5
|
+
|
|
6
|
+
本工具使用 `uv` 管理依赖和运行环境。
|
|
7
|
+
|
|
8
|
+
### 安装依赖并同步环境:
|
|
9
|
+
```bash
|
|
10
|
+
uv sync
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 用法
|
|
16
|
+
|
|
17
|
+
### 1. format-img
|
|
18
|
+
|
|
19
|
+
格式化当前目录下的图片文件名。
|
|
20
|
+
|
|
21
|
+
#### 基本用法
|
|
22
|
+
```bash
|
|
23
|
+
uv run format-img [-f format] [-s suffixs] [-h]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- `-f` 文件名的格式,默认值为 `%Y%m%d%H%M%S`。支持的占位符列表见下表。
|
|
27
|
+
- `-s` 要格式化文件名的后缀名列表(以逗号分隔,不区分大小写),默认值为 `jpg,png,jpeg,heic`。例如 `-s "jpg,png"`。
|
|
28
|
+
- `-h` 获取帮助信息。
|
|
29
|
+
|
|
30
|
+
#### 支持的格式占位符:
|
|
31
|
+
|
|
32
|
+
| 格式 | 含义 |
|
|
33
|
+
|---|---|
|
|
34
|
+
| %a | 本地(locale)简化星期名称 |
|
|
35
|
+
| %A | 本地完整星期名称 |
|
|
36
|
+
| %b | 本地简化月份名称 |
|
|
37
|
+
| %B | 本地完整月份名称 |
|
|
38
|
+
| %c | 本地相应的日期和时间表示 |
|
|
39
|
+
| %d | 一个月中的第几天(01 - 31) |
|
|
40
|
+
| %H | 一天中的第几个小时(24小时制,00 - 23) |
|
|
41
|
+
| %I | 第几个小时(12小时制,01 - 12) |
|
|
42
|
+
| %j | 一年中的第几天(001 - 366) |
|
|
43
|
+
| %m | 月份(01 - 12) |
|
|
44
|
+
| %M | 分钟数(00 - 59) |
|
|
45
|
+
| %p | 本地am或者pm的相应符 |
|
|
46
|
+
| %S | 秒(01 - 61) |
|
|
47
|
+
| %U | 一年中的星期数(00 - 53,星期天为一个星期的开始) |
|
|
48
|
+
| %w | 一个星期中的第几天(0 - 6,0是星期天) |
|
|
49
|
+
| %W | 和 %U 基本相同,不同的是以星期一为一个星期的开始 |
|
|
50
|
+
| %x | 本地相应日期 |
|
|
51
|
+
| %X | 本地相应时间 |
|
|
52
|
+
| %y | 去掉世纪的年份(00 - 99) |
|
|
53
|
+
| %Y | 完整的年份 |
|
|
54
|
+
| %Z | 时区的名字 |
|
|
55
|
+
| %% | '%' 字符 |
|
|
56
|
+
|
|
57
|
+
#### 示例
|
|
58
|
+
把当前目录下的 `jpg` 和 `png` 文件的名称格式化成 `2017-10-01 10:17:01` 的形式:
|
|
59
|
+
```bash
|
|
60
|
+
uv run format-img -s "jpg,png" -f "%Y-%m-%d %H:%M:%S"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### 2. modify-exif
|
|
66
|
+
|
|
67
|
+
用于读取/修改图片的 EXIF 信息。
|
|
68
|
+
|
|
69
|
+
#### 基本用法
|
|
70
|
+
```bash
|
|
71
|
+
# 读取属性详情
|
|
72
|
+
uv run modify-exif -f file -r property [-s]
|
|
73
|
+
|
|
74
|
+
# 读取拍摄时间与数字化时间(only output value if -s is set)
|
|
75
|
+
uv run modify-exif -f file -rt [-s]
|
|
76
|
+
|
|
77
|
+
# 写入指定属性
|
|
78
|
+
uv run modify-exif -f file -w property -v value
|
|
79
|
+
|
|
80
|
+
# 写入拍摄时间与数字化时间
|
|
81
|
+
uv run modify-exif -f file -wt -v value
|
|
82
|
+
|
|
83
|
+
# 查看帮助
|
|
84
|
+
uv run modify-exif -h
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
具体示例可以参考 `scripts/update-datetime.ps1`,用于批量修改目标文件夹里面 `yyyyMMddHHmmss` 这样命名规则图片的 EXIF 时间信息。
|
|
88
|
+
|
|
89
|
+
## 注意事项
|
|
90
|
+
|
|
91
|
+
**跨路径调用**:如果要在其他路径(即不是项目根目录)下调用本工具,建议使用 `--project` 参数指定项目路径,例如:
|
|
92
|
+
|
|
93
|
+
```powershell
|
|
94
|
+
uv --project D:\Development\format-img run format-img
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
使用 `--project` 可以确保 `uv` 能够找到该项目的环境与依赖,同时**不会**改变当前的工作路径(cwd),从而正确地对你当前所在的命令行路径下的图片进行格式化操作。
|
|
98
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "format-img"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A python tool to format images based on EXIF information and edit EXIF data."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.8"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"exif>=1.3.5",
|
|
9
|
+
"exifread>=2.3.2",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[project.scripts]
|
|
13
|
+
format-img = "format_img.format_img:main"
|
|
14
|
+
modify-exif = "format_img.modify_exif:main"
|
|
15
|
+
|
|
16
|
+
[build-system]
|
|
17
|
+
requires = ["hatchling"]
|
|
18
|
+
build-backend = "hatchling.build"
|
|
19
|
+
|
|
20
|
+
[tool.hatch.build.targets.wheel]
|
|
21
|
+
packages = ["src/format_img"]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.DESCRIPTION
|
|
3
|
+
增加某个路径下的图片拍摄时间信息,文件名必须是 yyyyMMddHHmmss 这样的形式
|
|
4
|
+
.PARAMETER Folder
|
|
5
|
+
要查找的路径,默认是当前路径
|
|
6
|
+
.PARAMETER Suffix
|
|
7
|
+
要查找的文件后缀名,默认是 jpg
|
|
8
|
+
.PARAMETER Recurse
|
|
9
|
+
是否递归查找,默认不递归
|
|
10
|
+
#>
|
|
11
|
+
|
|
12
|
+
# Parameter
|
|
13
|
+
[CmdletBinding()]
|
|
14
|
+
param (
|
|
15
|
+
[Parameter(Position = 0)]
|
|
16
|
+
[string]$Folder = ".",
|
|
17
|
+
[Parameter(Position = 1)]
|
|
18
|
+
[string]$Suffix = "jpg",
|
|
19
|
+
[Parameter()]
|
|
20
|
+
[switch]$Recurse
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
$ProjectDir = (Resolve-Path "$PSScriptRoot\..").Path
|
|
24
|
+
|
|
25
|
+
<#
|
|
26
|
+
.DESCRIPTION
|
|
27
|
+
传入 yyyyMMddHHmmss 形式的文件名返回 yyyy:MM:dd HH:mm:ss 这样的字符串
|
|
28
|
+
#>
|
|
29
|
+
function formatDatetime {
|
|
30
|
+
|
|
31
|
+
param (
|
|
32
|
+
[Parameter(Mandatory)]
|
|
33
|
+
[string]$fileName
|
|
34
|
+
)
|
|
35
|
+
return $($fileName.substring(0, 4) + ":" + $fileName.substring(4, 2) + ":" + $fileName.substring(6, 2) + " " + $fileName.substring(8, 2) + ":" + $fileName.substring(10, 2) + ":" + $fileName.substring(12, 2))
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if ($Recurse) {
|
|
40
|
+
$files = Get-ChildItem -LiteralPath $Folder -Recurse -Filter "*.${Suffix}"
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
$files = Get-ChildItem -LiteralPath $Folder -Filter "*.${Suffix}"
|
|
44
|
+
}
|
|
45
|
+
foreach ( $f in $files) {
|
|
46
|
+
$v = $(uv run --project "$ProjectDir" modify-exif -f $f.FullName -rt -s)
|
|
47
|
+
if ($v.count -eq 0) {
|
|
48
|
+
$dateTime = $(formatDatetime $f.Name)
|
|
49
|
+
uv run --project "$ProjectDir" modify-exif -f $f.FullName -wt -v $dateTime
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# format_img package
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
格式化图片名称
|
|
3
|
+
"""
|
|
4
|
+
import sys
|
|
5
|
+
import getopt
|
|
6
|
+
import exifread
|
|
7
|
+
import time
|
|
8
|
+
import os
|
|
9
|
+
from .my_utility import get_imgs, get_suffixes, get_format, get_file_suffix
|
|
10
|
+
|
|
11
|
+
HELP = """
|
|
12
|
+
format-img
|
|
13
|
+
[-f format] default is '%Y%m%d%H%M%S'
|
|
14
|
+
[-s suffixs] default is 'jpg,png,jpeg,heic'
|
|
15
|
+
-h help
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def main():
|
|
20
|
+
"""主入口函数"""
|
|
21
|
+
fmt = ''
|
|
22
|
+
suffixes = []
|
|
23
|
+
try:
|
|
24
|
+
options, args = getopt.getopt(sys.argv[1:], 'hs:f:')
|
|
25
|
+
for option, value in options:
|
|
26
|
+
if option == '-f':
|
|
27
|
+
fmt = value
|
|
28
|
+
elif option == '-s':
|
|
29
|
+
suffixes = value.split(',')
|
|
30
|
+
elif option == '-h':
|
|
31
|
+
print(HELP)
|
|
32
|
+
sys.exit(0)
|
|
33
|
+
except Exception as e:
|
|
34
|
+
sys.stderr.write(f"Error parsing options: {e}\n")
|
|
35
|
+
sys.exit(1)
|
|
36
|
+
|
|
37
|
+
if not fmt:
|
|
38
|
+
fmt = get_format()
|
|
39
|
+
if not suffixes:
|
|
40
|
+
suffixes = get_suffixes()
|
|
41
|
+
|
|
42
|
+
ok_cnt = 0
|
|
43
|
+
ng_cnt = 0
|
|
44
|
+
|
|
45
|
+
for img in get_imgs(suffixes):
|
|
46
|
+
# 遍历出图片的EXIF时间或者文件创建时间并且按照格式重新命名文件
|
|
47
|
+
try:
|
|
48
|
+
with open(img, 'rb') as f_img:
|
|
49
|
+
tags = exifread.process_file(f_img, stop_tag='EXIF DateTimeOriginal')
|
|
50
|
+
except Exception as e:
|
|
51
|
+
sys.stderr.write(f"Failed to read EXIF from {img}: {e}\n")
|
|
52
|
+
ng_cnt += 1
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
if 'EXIF DateTimeOriginal' in tags:
|
|
56
|
+
try:
|
|
57
|
+
img_time = time.strptime(str(tags['EXIF DateTimeOriginal']), "%Y:%m:%d %H:%M:%S")
|
|
58
|
+
except ValueError:
|
|
59
|
+
img_time = time.localtime(os.path.getmtime(img))
|
|
60
|
+
else:
|
|
61
|
+
img_time = time.localtime(os.path.getmtime(img))
|
|
62
|
+
|
|
63
|
+
# 重命名文件
|
|
64
|
+
i = 0
|
|
65
|
+
img_suffix = get_file_suffix(img)
|
|
66
|
+
img_new_name = time.strftime(fmt, img_time) + "." + img_suffix
|
|
67
|
+
while os.path.exists(img_new_name):
|
|
68
|
+
i += 1
|
|
69
|
+
img_new_name = time.strftime(fmt, img_time) + "_" + str(i) + "." + img_suffix
|
|
70
|
+
try:
|
|
71
|
+
os.rename(img, img_new_name)
|
|
72
|
+
print("%-25s\t→\t%-25s\tsuccess" % (img, img_new_name))
|
|
73
|
+
ok_cnt += 1
|
|
74
|
+
except Exception as e:
|
|
75
|
+
print("%-25s\t→\t%-25s\tfailed" % (img, img_new_name))
|
|
76
|
+
sys.stderr.write(f"Error: {e}\n")
|
|
77
|
+
ng_cnt += 1
|
|
78
|
+
|
|
79
|
+
# 输出统计信息
|
|
80
|
+
print("\nProcess completed\nSuccess: %d\nFailed: %d" % (ok_cnt, ng_cnt))
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
if __name__ == '__main__':
|
|
84
|
+
main()
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
编辑图片的EXIF信息
|
|
3
|
+
"""
|
|
4
|
+
import sys
|
|
5
|
+
import getopt
|
|
6
|
+
from .my_utility import get_file_exif, set_file_exif
|
|
7
|
+
|
|
8
|
+
HELP = """
|
|
9
|
+
modify-exif
|
|
10
|
+
-f file -r property [-s] read property, only output value if s is set
|
|
11
|
+
-f file -rt [-s] read datetime_original and datetime_digitized, only output value if s is set
|
|
12
|
+
-f file -w property -v value write property
|
|
13
|
+
-f file -wt -v value write datetime_original and datetime_digitized
|
|
14
|
+
-h help
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def read_property(filename, property_name, simple_out=False):
|
|
19
|
+
"""读取属性并打印详情"""
|
|
20
|
+
value = get_file_exif(filename, property_name)
|
|
21
|
+
if simple_out:
|
|
22
|
+
if value != "":
|
|
23
|
+
print(value)
|
|
24
|
+
else:
|
|
25
|
+
print(f"read {property_name} from {filename}")
|
|
26
|
+
print(f"value is {value}")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def write_property(filename, property_name, value):
|
|
30
|
+
"""写入属性并打印详情"""
|
|
31
|
+
print(f"write '{property_name}={value}' to {filename}")
|
|
32
|
+
set_file_exif(filename, property_name, value)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main():
|
|
36
|
+
"""主入口函数"""
|
|
37
|
+
process_file = ""
|
|
38
|
+
process_mode = ""
|
|
39
|
+
process_property = ""
|
|
40
|
+
process_value = ""
|
|
41
|
+
simple_out = False
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
options, args = getopt.getopt(sys.argv[1:], 'hf:r:w::v:s')
|
|
45
|
+
for option, value in options:
|
|
46
|
+
if option == '-f':
|
|
47
|
+
process_file = value
|
|
48
|
+
elif option == '-r':
|
|
49
|
+
process_mode = "r"
|
|
50
|
+
process_property = value
|
|
51
|
+
elif option == '-w':
|
|
52
|
+
process_mode = "w"
|
|
53
|
+
process_property = value
|
|
54
|
+
elif option == '-v':
|
|
55
|
+
process_value = value
|
|
56
|
+
elif option == '-s':
|
|
57
|
+
simple_out = True
|
|
58
|
+
elif option == '-h':
|
|
59
|
+
print(HELP)
|
|
60
|
+
sys.exit(0)
|
|
61
|
+
|
|
62
|
+
if process_file == "":
|
|
63
|
+
raise Exception("file is empty")
|
|
64
|
+
if process_mode == "":
|
|
65
|
+
raise Exception("r or w flag is necessary")
|
|
66
|
+
if process_property == "":
|
|
67
|
+
raise Exception("property is necessary")
|
|
68
|
+
if process_mode == "w" and process_value == "":
|
|
69
|
+
raise Exception("value is necessary")
|
|
70
|
+
except Exception as e:
|
|
71
|
+
sys.stderr.write("".join(e.args) + "\n")
|
|
72
|
+
sys.exit(1)
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
if process_mode == 'r':
|
|
76
|
+
if process_property == "t":
|
|
77
|
+
read_property(process_file, "datetime_original", simple_out)
|
|
78
|
+
read_property(process_file, "datetime_digitized", simple_out)
|
|
79
|
+
else:
|
|
80
|
+
read_property(process_file, process_property, simple_out)
|
|
81
|
+
else:
|
|
82
|
+
if process_property == "t":
|
|
83
|
+
write_property(process_file, "datetime_original", process_value)
|
|
84
|
+
write_property(process_file, "datetime_digitized", process_value)
|
|
85
|
+
else:
|
|
86
|
+
write_property(process_file, process_property, process_value)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
sys.stderr.write("".join(e.args) + "\n")
|
|
89
|
+
sys.exit(1)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == '__main__':
|
|
93
|
+
main()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""
|
|
2
|
+
自定义工具集
|
|
3
|
+
"""
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
from exif import Image, DATETIME_STR_FORMAT
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_imgs(suffixs=None):
|
|
11
|
+
"""获取指定后缀的图片文件名"""
|
|
12
|
+
if suffixs is None:
|
|
13
|
+
suffixs = get_suffixes()
|
|
14
|
+
|
|
15
|
+
# 构造匹配表达式
|
|
16
|
+
img_pattern = '$|.*\\.'.join(suffixs)
|
|
17
|
+
if img_pattern != "":
|
|
18
|
+
img_pattern += '$'
|
|
19
|
+
img_pattern = '.*\\.' + img_pattern
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
dirs = os.listdir('.')
|
|
23
|
+
except Exception:
|
|
24
|
+
dirs = []
|
|
25
|
+
|
|
26
|
+
imgs = []
|
|
27
|
+
for img in dirs:
|
|
28
|
+
if re.match(img_pattern, img, re.I):
|
|
29
|
+
imgs.append(img)
|
|
30
|
+
return imgs
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_suffixes():
|
|
34
|
+
"""获取默认的文件后缀"""
|
|
35
|
+
return ['jpg', 'png', 'jpeg', 'heic']
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_format():
|
|
39
|
+
"""获取默认的命名格式"""
|
|
40
|
+
return '%Y%m%d%H%M%S'
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_file_suffix(filename=''):
|
|
44
|
+
"""获取文件后缀"""
|
|
45
|
+
if filename != '':
|
|
46
|
+
tmp = filename.split('.')
|
|
47
|
+
if len(tmp) > 0:
|
|
48
|
+
return tmp.pop()
|
|
49
|
+
return ''
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_file_exif(filename='', property=''):
|
|
53
|
+
"""获取指定文件的EXIF信息,默认获取所有信息"""
|
|
54
|
+
image = Image(filename)
|
|
55
|
+
if not image.has_exif:
|
|
56
|
+
return ""
|
|
57
|
+
if property == "":
|
|
58
|
+
return image.list_all()
|
|
59
|
+
else:
|
|
60
|
+
return image.get(property, "")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def set_file_exif(filename='', property='datetime_original', value=''):
|
|
64
|
+
"""设定指定文件的EXIF信息,默认设置datetime_original为当前时间"""
|
|
65
|
+
image = Image(filename)
|
|
66
|
+
if value == '':
|
|
67
|
+
value = datetime.now().strftime(DATETIME_STR_FORMAT)
|
|
68
|
+
image.set(property, value)
|
|
69
|
+
with open(filename, 'wb') as f:
|
|
70
|
+
f.write(image.get_file())
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
if __name__ == '__main__':
|
|
74
|
+
# 模块测试
|
|
75
|
+
pass
|
format_img-0.1.0/uv.lock
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.8"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "exif"
|
|
7
|
+
version = "1.6.1"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
dependencies = [
|
|
10
|
+
{ name = "plum-py" },
|
|
11
|
+
]
|
|
12
|
+
sdist = { url = "https://files.pythonhosted.org/packages/52/21/34c46fbda54648afdcc66f0eec0ac91675361017abcdcdd23bd88fa74cc5/exif-1.6.1.tar.gz", hash = "sha256:763599b89b9b67495713060a703f32d1874abf8f0628c9d77711c2c06a5f44c8", size = 24052, upload-time = "2024-12-10T04:38:35.812Z" }
|
|
13
|
+
wheels = [
|
|
14
|
+
{ url = "https://files.pythonhosted.org/packages/67/07/a47a78be02b0a2d273358312f3e2eecc4981d4604f8a6e6b8ef27c1e9c2d/exif-1.6.1-py3-none-any.whl", hash = "sha256:2879830e2d8f0e5f1503110736bceb83a1e9c2121b32c23208c04284be5afbec", size = 30461, upload-time = "2024-12-10T04:38:33.547Z" },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "exifread"
|
|
19
|
+
version = "3.5.1"
|
|
20
|
+
source = { registry = "https://pypi.org/simple" }
|
|
21
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e2/4e/d8fce8810d819db47f5b159e75223511c5ccd7ad07c2feca64cf7fab2477/exifread-3.5.1.tar.gz", hash = "sha256:9f998f80d3062741c976dfc4fd033424bc40932937994e4d2181eb70c4b6aedd", size = 56552, upload-time = "2025-08-23T21:59:18.123Z" }
|
|
22
|
+
wheels = [
|
|
23
|
+
{ url = "https://files.pythonhosted.org/packages/e2/a3/20e34a55c7b225110d3822d07c3cab9e8653d9c179e36783f2ed632a96a7/exifread-3.5.1-py3-none-any.whl", hash = "sha256:e5426ce2857423ad401e575ea9d159dc97449dc041fb6e61b35109caea72c311", size = 59742, upload-time = "2025-08-23T21:59:16.633Z" },
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[[package]]
|
|
27
|
+
name = "format-img"
|
|
28
|
+
version = "0.1.0"
|
|
29
|
+
source = { editable = "." }
|
|
30
|
+
dependencies = [
|
|
31
|
+
{ name = "exif" },
|
|
32
|
+
{ name = "exifread" },
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[package.metadata]
|
|
36
|
+
requires-dist = [
|
|
37
|
+
{ name = "exif", specifier = ">=1.3.5" },
|
|
38
|
+
{ name = "exifread", specifier = ">=2.3.2" },
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[[package]]
|
|
42
|
+
name = "plum-py"
|
|
43
|
+
version = "0.8.7"
|
|
44
|
+
source = { registry = "https://pypi.org/simple" }
|
|
45
|
+
sdist = { url = "https://files.pythonhosted.org/packages/3a/2a/a650b0cde5a15f4a9375df43bd7eacaffb65b30c8395b6b6cd84df2bf7ae/plum-py-0.8.7.tar.gz", hash = "sha256:40a25a70f7fd213f57cdd1decc65874df2d213d19d63478a1addcca748c13c4e", size = 116231, upload-time = "2024-05-12T02:01:48.18Z" }
|
|
46
|
+
wheels = [
|
|
47
|
+
{ url = "https://files.pythonhosted.org/packages/2f/da/8a9bdf5d3ea4b13d3142e0c77d6e85e4c2668aef6e4b9d5e9a6619049bdc/plum_py-0.8.7-py3-none-any.whl", hash = "sha256:d791f059ef159adbe3c3b036557b5b431fa07db226a9de106a74e5e57441741d", size = 69991, upload-time = "2023-08-14T21:56:31.953Z" },
|
|
48
|
+
]
|