py-img-processor 1.2.4__tar.gz → 1.3.2__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.
- {py_img_processor-1.2.4/py_img_processor.egg-info → py_img_processor-1.3.2}/PKG-INFO +9 -7
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/README.md +8 -6
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/__init__.py +6 -1
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/enums.py +0 -4
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/main.py +1 -1
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/__init__.py +10 -1
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/alpha.py +2 -2
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/base.py +8 -6
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/blur.py +2 -2
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/circle.py +2 -2
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/crop.py +2 -2
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/gray.py +2 -2
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/merge.py +2 -2
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/resize.py +2 -2
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/rotate.py +2 -2
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/parsers/watermark.py +3 -3
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/processor.py +42 -28
- {py_img_processor-1.2.4 → py_img_processor-1.3.2/py_img_processor.egg-info}/PKG-INFO +9 -7
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/LICENSE +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/MANIFEST.in +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/exceptions.py +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/imgprocessor/utils.py +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/py_img_processor.egg-info/SOURCES.txt +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/py_img_processor.egg-info/dependency_links.txt +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/py_img_processor.egg-info/entry_points.txt +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/py_img_processor.egg-info/not-zip-safe +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/py_img_processor.egg-info/requires.txt +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/py_img_processor.egg-info/top_level.txt +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/setup.cfg +0 -0
- {py_img_processor-1.2.4 → py_img_processor-1.3.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: py-img-processor
|
|
3
|
-
Version: 1.2
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Image editor using Python and Pillow.
|
|
5
5
|
Home-page: https://github.com/SkylerHu/py-img-processor.git
|
|
6
6
|
Author: SkylerHu
|
|
@@ -68,7 +68,7 @@ Image editor using Python and Pillow.
|
|
|
68
68
|
| DEBUG | bool | 是否debug开发模式 | False |
|
|
69
69
|
| PROCESSOR_MAX_FILE_SIZE | int | 处理原图的大小限制, 单位 MB | 20 |
|
|
70
70
|
| PROCESSOR_MAX_W_H | int | 处理图像,原图宽高像素限制 | 30000 |
|
|
71
|
-
| PROCESSOR_MAX_PIXEL | int | width x height总像素3
|
|
71
|
+
| PROCESSOR_MAX_PIXEL | int | width x height总像素3亿,处理前后的值都被此配置限制,会覆盖`Image.MAX_IMAGE_PIXELS`设置 | 300000000 |
|
|
72
72
|
| PROCESSOR_DEFAULT_QUALITY | int | 图像处理后的默认质量 | 75 |
|
|
73
73
|
| PROCESSOR_TEXT_FONT | str | 默认字体文件,默认从系统中寻找;也可以直接传递字体文件路径 | Arial Unicode.ttf |
|
|
74
74
|
| PROCESSOR_WORKSPACES | tuple | 限制水印等资源路径 (startswith匹配), 默认无限制 | `()` |
|
|
@@ -86,16 +86,18 @@ Image editor using Python and Pillow.
|
|
|
86
86
|
|
|
87
87
|
### 处理函数
|
|
88
88
|
```python
|
|
89
|
-
from imgprocessor.processor import process_image
|
|
89
|
+
from imgprocessor.processor import process_image, process_image_obj
|
|
90
90
|
|
|
91
|
-
process_image(input_uri,
|
|
91
|
+
process_image(input_uri, params, out_path=out_path)
|
|
92
|
+
# 或者
|
|
93
|
+
process_image_obj(im, params, out_path=out_path)
|
|
92
94
|
```
|
|
93
95
|
|
|
94
96
|
参数说明:
|
|
95
97
|
|
|
96
98
|
- `input_uri` str,输入图像文件路径或者链接地址
|
|
97
|
-
- `out_path` str, 输出图像保存路径
|
|
98
99
|
- `params` str or json,图像处理参数,参数说明详见 [Reference.md](https://github.com/SkylerHu/py-img-processor/blob/master/docs/Reference.md)
|
|
100
|
+
- `out_path` str, 输出图像保存路径, 默认为空,为空时返回二进制内容
|
|
99
101
|
|
|
100
102
|
|
|
101
103
|
### 图像处理参数为字符串
|
|
@@ -111,9 +113,9 @@ from imgprocessor.processor import process_image
|
|
|
111
113
|
|
|
112
114
|
process_image(
|
|
113
115
|
"docs/imgs/lenna-400x225.jpg",
|
|
114
|
-
"/tmp/output.png",
|
|
115
116
|
# 对图片缩放、裁剪、生成圆角、并转成png存储
|
|
116
117
|
f"resize,s_200/crop,w_200,h_200,g_center/watermark,text_{base64url_encode('Hello 世界')},color_FFF,size_20/circle,r_10/format,png",
|
|
118
|
+
out_path="/tmp/output.png",
|
|
117
119
|
)
|
|
118
120
|
```
|
|
119
121
|
|
|
@@ -129,7 +131,6 @@ process_image(
|
|
|
129
131
|
```python
|
|
130
132
|
process_image(
|
|
131
133
|
"docs/imgs/lenna-400x225.jpg",
|
|
132
|
-
"/tmp/output.png",
|
|
133
134
|
{
|
|
134
135
|
"actions": [
|
|
135
136
|
{"key": "resize", "s": 200},
|
|
@@ -140,6 +141,7 @@ process_image(
|
|
|
140
141
|
],
|
|
141
142
|
"format": "png",
|
|
142
143
|
},
|
|
144
|
+
out_path="/tmp/output.png",
|
|
143
145
|
)
|
|
144
146
|
```
|
|
145
147
|
该操作与上述字符串示例参数等效。
|
|
@@ -42,7 +42,7 @@ Image editor using Python and Pillow.
|
|
|
42
42
|
| DEBUG | bool | 是否debug开发模式 | False |
|
|
43
43
|
| PROCESSOR_MAX_FILE_SIZE | int | 处理原图的大小限制, 单位 MB | 20 |
|
|
44
44
|
| PROCESSOR_MAX_W_H | int | 处理图像,原图宽高像素限制 | 30000 |
|
|
45
|
-
| PROCESSOR_MAX_PIXEL | int | width x height总像素3
|
|
45
|
+
| PROCESSOR_MAX_PIXEL | int | width x height总像素3亿,处理前后的值都被此配置限制,会覆盖`Image.MAX_IMAGE_PIXELS`设置 | 300000000 |
|
|
46
46
|
| PROCESSOR_DEFAULT_QUALITY | int | 图像处理后的默认质量 | 75 |
|
|
47
47
|
| PROCESSOR_TEXT_FONT | str | 默认字体文件,默认从系统中寻找;也可以直接传递字体文件路径 | Arial Unicode.ttf |
|
|
48
48
|
| PROCESSOR_WORKSPACES | tuple | 限制水印等资源路径 (startswith匹配), 默认无限制 | `()` |
|
|
@@ -60,16 +60,18 @@ Image editor using Python and Pillow.
|
|
|
60
60
|
|
|
61
61
|
### 处理函数
|
|
62
62
|
```python
|
|
63
|
-
from imgprocessor.processor import process_image
|
|
63
|
+
from imgprocessor.processor import process_image, process_image_obj
|
|
64
64
|
|
|
65
|
-
process_image(input_uri,
|
|
65
|
+
process_image(input_uri, params, out_path=out_path)
|
|
66
|
+
# 或者
|
|
67
|
+
process_image_obj(im, params, out_path=out_path)
|
|
66
68
|
```
|
|
67
69
|
|
|
68
70
|
参数说明:
|
|
69
71
|
|
|
70
72
|
- `input_uri` str,输入图像文件路径或者链接地址
|
|
71
|
-
- `out_path` str, 输出图像保存路径
|
|
72
73
|
- `params` str or json,图像处理参数,参数说明详见 [Reference.md](./docs/Reference.md)
|
|
74
|
+
- `out_path` str, 输出图像保存路径, 默认为空,为空时返回二进制内容
|
|
73
75
|
|
|
74
76
|
|
|
75
77
|
### 图像处理参数为字符串
|
|
@@ -85,9 +87,9 @@ from imgprocessor.processor import process_image
|
|
|
85
87
|
|
|
86
88
|
process_image(
|
|
87
89
|
"docs/imgs/lenna-400x225.jpg",
|
|
88
|
-
"/tmp/output.png",
|
|
89
90
|
# 对图片缩放、裁剪、生成圆角、并转成png存储
|
|
90
91
|
f"resize,s_200/crop,w_200,h_200,g_center/watermark,text_{base64url_encode('Hello 世界')},color_FFF,size_20/circle,r_10/format,png",
|
|
92
|
+
out_path="/tmp/output.png",
|
|
91
93
|
)
|
|
92
94
|
```
|
|
93
95
|
|
|
@@ -103,7 +105,6 @@ process_image(
|
|
|
103
105
|
```python
|
|
104
106
|
process_image(
|
|
105
107
|
"docs/imgs/lenna-400x225.jpg",
|
|
106
|
-
"/tmp/output.png",
|
|
107
108
|
{
|
|
108
109
|
"actions": [
|
|
109
110
|
{"key": "resize", "s": 200},
|
|
@@ -114,6 +115,7 @@ process_image(
|
|
|
114
115
|
],
|
|
115
116
|
"format": "png",
|
|
116
117
|
},
|
|
118
|
+
out_path="/tmp/output.png",
|
|
117
119
|
)
|
|
118
120
|
```
|
|
119
121
|
该操作与上述字符串示例参数等效。
|
|
@@ -3,9 +3,11 @@ import os
|
|
|
3
3
|
import traceback
|
|
4
4
|
import importlib
|
|
5
5
|
|
|
6
|
+
from PIL import Image
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
__all__ = ["settings", "VERSION"]
|
|
8
|
-
__version__ = "1.2
|
|
10
|
+
__version__ = "1.3.2"
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
VERSION = __version__
|
|
@@ -72,3 +74,6 @@ class SettingsProxy(object):
|
|
|
72
74
|
|
|
73
75
|
|
|
74
76
|
settings = SettingsProxy()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
Image.MAX_IMAGE_PIXELS = settings.PROCESSOR_MAX_PIXEL
|
|
@@ -31,10 +31,6 @@ class ImageOrientation(ChoiceEnum):
|
|
|
31
31
|
class OpAction(ChoiceEnum):
|
|
32
32
|
"""支持的操作类型"""
|
|
33
33
|
|
|
34
|
-
# 以下几个比较特殊,在保存文件时使用
|
|
35
|
-
FORMAT = ("format", "格式")
|
|
36
|
-
QUALITY = ("quality", "质量")
|
|
37
|
-
INTERLACE = ("interlace", "渐进显示")
|
|
38
34
|
# 其他
|
|
39
35
|
RESIZE = ("resize", "缩放")
|
|
40
36
|
CROP = ("crop", "裁剪")
|
|
@@ -95,7 +95,7 @@ def main(argv: typing.Optional[list[str]] = None) -> int:
|
|
|
95
95
|
if not os.path.exists(cur_out_dir):
|
|
96
96
|
os.makedirs(cur_out_dir)
|
|
97
97
|
try:
|
|
98
|
-
process_image(file_path,
|
|
98
|
+
process_image(file_path, param_str, out_path=out_path)
|
|
99
99
|
print(f"{tag}\t 成功", flush=True)
|
|
100
100
|
except Exception as e:
|
|
101
101
|
print(f"{tag}\t \033[31m失败:{e}\033[0m", file=sys.stderr, flush=True)
|
|
@@ -33,6 +33,14 @@ _ACTION_PARASER_MAP: dict[str, typing.Any] = {
|
|
|
33
33
|
class ProcessParams(object):
|
|
34
34
|
"""图像处理输入参数"""
|
|
35
35
|
|
|
36
|
+
@classmethod
|
|
37
|
+
def init(cls, params: typing.Union["ProcessParams", dict, str]) -> "ProcessParams":
|
|
38
|
+
if isinstance(params, ProcessParams):
|
|
39
|
+
return params
|
|
40
|
+
if isinstance(params, dict):
|
|
41
|
+
return cls(**params)
|
|
42
|
+
return cls.parse_str(params)
|
|
43
|
+
|
|
36
44
|
def __init__(
|
|
37
45
|
self,
|
|
38
46
|
enable_base64: bool = False,
|
|
@@ -66,6 +74,7 @@ class ProcessParams(object):
|
|
|
66
74
|
|
|
67
75
|
save_args = [""] # 加空字符串,是为了保证解析出key
|
|
68
76
|
|
|
77
|
+
save_keys = list(ImgSaveParser.ARGS.keys())
|
|
69
78
|
for item in value.split("/"):
|
|
70
79
|
if not item:
|
|
71
80
|
continue
|
|
@@ -77,7 +86,7 @@ class ProcessParams(object):
|
|
|
77
86
|
key, param_str = info
|
|
78
87
|
if not key:
|
|
79
88
|
raise ParamParseException(f"参数必须指定操作类型 [{item}]不符合参数要求")
|
|
80
|
-
if key in
|
|
89
|
+
if key in save_keys:
|
|
81
90
|
save_args.append(f"{key}_{param_str}")
|
|
82
91
|
else:
|
|
83
92
|
action_cls = _ACTION_PARASER_MAP.get(key)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from PIL import
|
|
5
|
+
from PIL import ImageFile
|
|
6
6
|
|
|
7
7
|
from imgprocessor import enums
|
|
8
8
|
from .base import BaseParser, pre_processing
|
|
@@ -23,7 +23,7 @@ class AlphaParser(BaseParser):
|
|
|
23
23
|
) -> None:
|
|
24
24
|
self.value = value
|
|
25
25
|
|
|
26
|
-
def do_action(self, im:
|
|
26
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
27
27
|
im = pre_processing(im, use_alpha=True)
|
|
28
28
|
if self.value < 100:
|
|
29
29
|
_, _, _, alpha_channel = im.split()
|
|
@@ -9,7 +9,7 @@ import urllib.parse
|
|
|
9
9
|
from urllib.request import urlretrieve
|
|
10
10
|
from contextlib import contextmanager
|
|
11
11
|
|
|
12
|
-
from PIL import Image, ImageOps
|
|
12
|
+
from PIL import Image, ImageOps, ImageFile
|
|
13
13
|
|
|
14
14
|
from py_enum import ChoiceEnum
|
|
15
15
|
from imgprocessor import settings, enums, utils
|
|
@@ -43,7 +43,7 @@ class BaseParser(object):
|
|
|
43
43
|
"""由子类继承实现各类实例的数据校验"""
|
|
44
44
|
pass
|
|
45
45
|
|
|
46
|
-
def do_action(self, im:
|
|
46
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
47
47
|
raise NotImplementedError
|
|
48
48
|
|
|
49
49
|
def to_dict(self) -> dict:
|
|
@@ -214,7 +214,7 @@ class BaseParser(object):
|
|
|
214
214
|
return params
|
|
215
215
|
|
|
216
216
|
|
|
217
|
-
def pre_processing(im:
|
|
217
|
+
def pre_processing(im: ImageFile.ImageFile, use_alpha: bool = False) -> ImageFile.ImageFile:
|
|
218
218
|
"""预处理图像,默认转成`RGB`,若为`use_alpha=True`转为`RGBA`
|
|
219
219
|
|
|
220
220
|
Args:
|
|
@@ -367,7 +367,7 @@ def compute_splice_two_im(
|
|
|
367
367
|
return w, h, x1, y1, x2, y2
|
|
368
368
|
|
|
369
369
|
|
|
370
|
-
def validate_ori_im(ori_im:
|
|
370
|
+
def validate_ori_im(ori_im: ImageFile.ImageFile) -> None:
|
|
371
371
|
src_w, src_h = ori_im.size
|
|
372
372
|
if src_w > settings.PROCESSOR_MAX_W_H or src_h > settings.PROCESSOR_MAX_W_H:
|
|
373
373
|
raise ProcessLimitException(
|
|
@@ -377,7 +377,7 @@ def validate_ori_im(ori_im: Image) -> None:
|
|
|
377
377
|
raise ProcessLimitException(f"图像总像素不可超过{settings.PROCESSOR_MAX_PIXEL}像素,输入图像({src_w}, {src_h})")
|
|
378
378
|
|
|
379
379
|
|
|
380
|
-
def copy_full_img(ori_im:
|
|
380
|
+
def copy_full_img(ori_im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
381
381
|
out_im = ori_im.copy()
|
|
382
382
|
# 复制格式信息
|
|
383
383
|
out_im.format = ori_im.format
|
|
@@ -433,6 +433,8 @@ def trans_uri_to_im(uri: str, use_copy: bool = False) -> typing.Generator:
|
|
|
433
433
|
|
|
434
434
|
class ImgSaveParser(BaseParser):
|
|
435
435
|
KEY = ""
|
|
436
|
+
|
|
437
|
+
# 定义的key注意和枚举 `OpAction` 中的key不能重复
|
|
436
438
|
ARGS = {
|
|
437
439
|
"format": {"type": enums.ArgType.STRING.value, "default": None},
|
|
438
440
|
"quality": {"type": enums.ArgType.INTEGER.value, "default": None, "min": 1, "max": 100},
|
|
@@ -458,7 +460,7 @@ class ImgSaveParser(BaseParser):
|
|
|
458
460
|
if self.format not in fmt_values:
|
|
459
461
|
raise ParamValidateException(f"参数 format 只能是其中之一:{fmt_values}")
|
|
460
462
|
|
|
461
|
-
def compute(self, in_im:
|
|
463
|
+
def compute(self, in_im: ImageFile.ImageFile, out_im: ImageFile.ImageFile) -> dict:
|
|
462
464
|
kwargs = {
|
|
463
465
|
"format": self.format or in_im.format,
|
|
464
466
|
# png 和 gif 格式的选项是 interlace(一般翻译成交错),jpeg(jpg) 的选项则是 progressive (翻译成 渐进)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from PIL import
|
|
5
|
+
from PIL import ImageFilter, ImageFile
|
|
6
6
|
|
|
7
7
|
from imgprocessor import enums
|
|
8
8
|
from .base import BaseParser, pre_processing
|
|
@@ -23,7 +23,7 @@ class BlurParser(BaseParser):
|
|
|
23
23
|
) -> None:
|
|
24
24
|
self.r = r
|
|
25
25
|
|
|
26
|
-
def do_action(self, im:
|
|
26
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
27
27
|
im = pre_processing(im)
|
|
28
28
|
im = im.filter(ImageFilter.GaussianBlur(radius=self.r))
|
|
29
29
|
return im
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from PIL import Image, ImageDraw
|
|
5
|
+
from PIL import Image, ImageDraw, ImageFile
|
|
6
6
|
|
|
7
7
|
from imgprocessor import enums, settings
|
|
8
8
|
from .base import BaseParser, pre_processing
|
|
@@ -32,7 +32,7 @@ class CircleParser(BaseParser):
|
|
|
32
32
|
|
|
33
33
|
return r
|
|
34
34
|
|
|
35
|
-
def do_action(self, im:
|
|
35
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
36
36
|
im = pre_processing(im, use_alpha=True)
|
|
37
37
|
|
|
38
38
|
src_w, src_h = im.size
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
|
-
from PIL import
|
|
4
|
+
from PIL import ImageFile
|
|
5
5
|
from imgprocessor import enums, settings
|
|
6
6
|
from imgprocessor.exceptions import ParamValidateException
|
|
7
7
|
from .base import BaseParser, pre_processing, compute_by_geography, compute_by_ratio
|
|
@@ -89,7 +89,7 @@ class CropParser(BaseParser):
|
|
|
89
89
|
|
|
90
90
|
return x, y, w, h
|
|
91
91
|
|
|
92
|
-
def do_action(self, im:
|
|
92
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
93
93
|
im = pre_processing(im)
|
|
94
94
|
x, y, w, h = self.compute(*im.size)
|
|
95
95
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from PIL import
|
|
5
|
+
from PIL import ImageFile
|
|
6
6
|
|
|
7
7
|
from imgprocessor import enums
|
|
8
8
|
from .base import BaseParser
|
|
@@ -19,6 +19,6 @@ class GrayParser(BaseParser):
|
|
|
19
19
|
) -> None:
|
|
20
20
|
pass
|
|
21
21
|
|
|
22
|
-
def do_action(self, im:
|
|
22
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
23
23
|
im = im.convert("L")
|
|
24
24
|
return im
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from PIL import Image
|
|
5
|
+
from PIL import Image, ImageFile
|
|
6
6
|
|
|
7
7
|
from imgprocessor import enums, settings
|
|
8
8
|
from imgprocessor.exceptions import ParamValidateException
|
|
@@ -115,7 +115,7 @@ class MergeParser(BaseParser):
|
|
|
115
115
|
|
|
116
116
|
return w, h, x1, y1, x2, y2
|
|
117
117
|
|
|
118
|
-
def do_action(self, im:
|
|
118
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
119
119
|
im = pre_processing(im, use_alpha=True)
|
|
120
120
|
|
|
121
121
|
# 处理要合并的图像
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from PIL import Image, ImageOps
|
|
5
|
+
from PIL import Image, ImageOps, ImageFile
|
|
6
6
|
from imgprocessor import enums, settings
|
|
7
7
|
from imgprocessor.exceptions import ParamValidateException, ProcessLimitException
|
|
8
8
|
from .base import BaseParser, pre_processing
|
|
@@ -112,7 +112,7 @@ class ResizeParser(BaseParser):
|
|
|
112
112
|
raise ProcessLimitException(f"缩放的目标图像总像素不可超过{settings.PROCESSOR_MAX_PIXEL}像素")
|
|
113
113
|
return (w, h)
|
|
114
114
|
|
|
115
|
-
def do_action(self, im:
|
|
115
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
116
116
|
im = pre_processing(im)
|
|
117
117
|
size = self.compute(*im.size)
|
|
118
118
|
if size == im.size:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from PIL import
|
|
5
|
+
from PIL import ImageFile
|
|
6
6
|
|
|
7
7
|
from imgprocessor import enums
|
|
8
8
|
from .base import BaseParser, pre_processing
|
|
@@ -23,7 +23,7 @@ class RotateParser(BaseParser):
|
|
|
23
23
|
) -> None:
|
|
24
24
|
self.value = value
|
|
25
25
|
|
|
26
|
-
def do_action(self, im:
|
|
26
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
27
27
|
im = pre_processing(im)
|
|
28
28
|
if 0 < self.value < 360:
|
|
29
29
|
# 函数提供的是逆时针旋转
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding=utf-8
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
|
-
from PIL import Image, ImageFont, ImageDraw
|
|
5
|
+
from PIL import Image, ImageFont, ImageDraw, ImageFile
|
|
6
6
|
|
|
7
7
|
from imgprocessor import enums, settings, utils
|
|
8
8
|
from imgprocessor.exceptions import ParamValidateException
|
|
@@ -113,7 +113,7 @@ class WatermarkParser(BaseParser):
|
|
|
113
113
|
if not self.image and not self.text:
|
|
114
114
|
raise ParamValidateException("image或者text参数必须传递一个")
|
|
115
115
|
|
|
116
|
-
def get_watermark_im(self) ->
|
|
116
|
+
def get_watermark_im(self) -> ImageFile.ImageFile:
|
|
117
117
|
"""初始化水印对象"""
|
|
118
118
|
w1, h1, w2, h2 = 0, 0, 0, 0
|
|
119
119
|
icon = None
|
|
@@ -171,7 +171,7 @@ class WatermarkParser(BaseParser):
|
|
|
171
171
|
|
|
172
172
|
return mark
|
|
173
173
|
|
|
174
|
-
def do_action(self, im:
|
|
174
|
+
def do_action(self, im: ImageFile.ImageFile) -> ImageFile.ImageFile:
|
|
175
175
|
im = pre_processing(im, use_alpha=True)
|
|
176
176
|
src_w, src_h = im.size
|
|
177
177
|
|
|
@@ -4,7 +4,7 @@ import typing
|
|
|
4
4
|
import tempfile
|
|
5
5
|
import colorsys
|
|
6
6
|
|
|
7
|
-
from PIL import Image, ImageOps
|
|
7
|
+
from PIL import Image, ImageOps, ImageFile
|
|
8
8
|
|
|
9
9
|
from imgprocessor import enums, settings
|
|
10
10
|
from imgprocessor.parsers import BaseParser, ProcessParams
|
|
@@ -13,29 +13,8 @@ from imgprocessor.parsers.base import trans_uri_to_im
|
|
|
13
13
|
|
|
14
14
|
class ProcessorCtr(object):
|
|
15
15
|
|
|
16
|
-
def __init__(self, input_uri: str, out_path: str, params: typing.Union[ProcessParams, dict, str]) -> None:
|
|
17
|
-
# 输入文件检验路径
|
|
18
|
-
self.input_uri = BaseParser._validate_uri(input_uri)
|
|
19
|
-
self.out_path = out_path
|
|
20
|
-
# 初始化处理参数
|
|
21
|
-
if isinstance(params, dict):
|
|
22
|
-
params = ProcessParams(**params)
|
|
23
|
-
elif isinstance(params, str):
|
|
24
|
-
params = ProcessParams.parse_str(params)
|
|
25
|
-
params = typing.cast(ProcessParams, params)
|
|
26
|
-
self.params = params
|
|
27
|
-
|
|
28
|
-
def run(self) -> typing.Optional[typing.ByteString]:
|
|
29
|
-
# 初始化输入
|
|
30
|
-
with trans_uri_to_im(self.input_uri) as ori_im:
|
|
31
|
-
# 处理图像
|
|
32
|
-
im = self.handle_img_actions(ori_im, self.params.actions)
|
|
33
|
-
# 输出、保存
|
|
34
|
-
kwargs = self.params.save_parser.compute(ori_im, im)
|
|
35
|
-
return self.save_img_to_file(im, out_path=self.out_path, **kwargs)
|
|
36
|
-
|
|
37
16
|
@classmethod
|
|
38
|
-
def handle_img_actions(cls, ori_im:
|
|
17
|
+
def handle_img_actions(cls, ori_im: ImageFile.ImageFile, actions: list[BaseParser]) -> ImageFile.ImageFile:
|
|
39
18
|
im = ori_im
|
|
40
19
|
# 解决旋转问题
|
|
41
20
|
im = ImageOps.exif_transpose(im)
|
|
@@ -46,7 +25,7 @@ class ProcessorCtr(object):
|
|
|
46
25
|
@classmethod
|
|
47
26
|
def save_img_to_file(
|
|
48
27
|
cls,
|
|
49
|
-
im:
|
|
28
|
+
im: ImageFile.ImageFile,
|
|
50
29
|
out_path: typing.Optional[str] = None,
|
|
51
30
|
**kwargs: typing.Any,
|
|
52
31
|
) -> typing.Optional[typing.ByteString]:
|
|
@@ -76,14 +55,17 @@ class ProcessorCtr(object):
|
|
|
76
55
|
|
|
77
56
|
|
|
78
57
|
def process_image(
|
|
79
|
-
input_uri: str,
|
|
58
|
+
input_uri: str,
|
|
59
|
+
params: typing.Union[ProcessParams, dict, str],
|
|
60
|
+
out_path: typing.Optional[str] = None,
|
|
61
|
+
**kwargs: typing.Any,
|
|
80
62
|
) -> typing.Optional[typing.ByteString]:
|
|
81
63
|
"""处理图像
|
|
82
64
|
|
|
83
65
|
Args:
|
|
84
66
|
input_uri: 输入图像路径
|
|
85
|
-
out_path: 输出图像保存路径
|
|
86
67
|
params: 图像处理参数
|
|
68
|
+
out_path: 输出图像保存路径
|
|
87
69
|
|
|
88
70
|
Raises:
|
|
89
71
|
ProcessLimitException: 超过处理限制会抛出异常
|
|
@@ -91,8 +73,40 @@ def process_image(
|
|
|
91
73
|
Returns:
|
|
92
74
|
默认输出直接存储无返回,仅当out_path为空时会返回处理后图像的二进制内容
|
|
93
75
|
"""
|
|
94
|
-
|
|
95
|
-
|
|
76
|
+
# 初始化输入
|
|
77
|
+
params_obj: ProcessParams = ProcessParams.init(params)
|
|
78
|
+
with trans_uri_to_im(input_uri) as ori_im:
|
|
79
|
+
# 处理图像
|
|
80
|
+
im = ProcessorCtr.handle_img_actions(ori_im, params_obj.actions)
|
|
81
|
+
# 输出、保存
|
|
82
|
+
_kwargs = params_obj.save_parser.compute(ori_im, im)
|
|
83
|
+
_kwargs.update(kwargs)
|
|
84
|
+
ret = ProcessorCtr.save_img_to_file(im, out_path=out_path, **_kwargs)
|
|
85
|
+
return ret
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def process_image_obj(
|
|
89
|
+
ori_im: ImageFile.ImageFile,
|
|
90
|
+
params: typing.Union[ProcessParams, dict, str],
|
|
91
|
+
out_path: typing.Optional[str] = None,
|
|
92
|
+
**kwargs: typing.Any,
|
|
93
|
+
) -> typing.Optional[typing.ByteString]:
|
|
94
|
+
"""处理图像
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
ori_im: 输入图像为Image对象
|
|
98
|
+
params: 图像处理参数
|
|
99
|
+
out_path: 输出图像保存路径
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
默认输出直接存储无返回,仅当out_path为空时会返回处理后图像的二进制内容
|
|
103
|
+
"""
|
|
104
|
+
params_obj: ProcessParams = ProcessParams.init(params)
|
|
105
|
+
im = ProcessorCtr.handle_img_actions(ori_im, params_obj.actions)
|
|
106
|
+
_kwargs = params_obj.save_parser.compute(ori_im, im)
|
|
107
|
+
_kwargs.update(kwargs)
|
|
108
|
+
ret = ProcessorCtr.save_img_to_file(im, out_path=out_path, **_kwargs)
|
|
109
|
+
return ret
|
|
96
110
|
|
|
97
111
|
|
|
98
112
|
def extract_main_color(img_path: str, delta_h: float = 0.3) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: py-img-processor
|
|
3
|
-
Version: 1.2
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Image editor using Python and Pillow.
|
|
5
5
|
Home-page: https://github.com/SkylerHu/py-img-processor.git
|
|
6
6
|
Author: SkylerHu
|
|
@@ -68,7 +68,7 @@ Image editor using Python and Pillow.
|
|
|
68
68
|
| DEBUG | bool | 是否debug开发模式 | False |
|
|
69
69
|
| PROCESSOR_MAX_FILE_SIZE | int | 处理原图的大小限制, 单位 MB | 20 |
|
|
70
70
|
| PROCESSOR_MAX_W_H | int | 处理图像,原图宽高像素限制 | 30000 |
|
|
71
|
-
| PROCESSOR_MAX_PIXEL | int | width x height总像素3
|
|
71
|
+
| PROCESSOR_MAX_PIXEL | int | width x height总像素3亿,处理前后的值都被此配置限制,会覆盖`Image.MAX_IMAGE_PIXELS`设置 | 300000000 |
|
|
72
72
|
| PROCESSOR_DEFAULT_QUALITY | int | 图像处理后的默认质量 | 75 |
|
|
73
73
|
| PROCESSOR_TEXT_FONT | str | 默认字体文件,默认从系统中寻找;也可以直接传递字体文件路径 | Arial Unicode.ttf |
|
|
74
74
|
| PROCESSOR_WORKSPACES | tuple | 限制水印等资源路径 (startswith匹配), 默认无限制 | `()` |
|
|
@@ -86,16 +86,18 @@ Image editor using Python and Pillow.
|
|
|
86
86
|
|
|
87
87
|
### 处理函数
|
|
88
88
|
```python
|
|
89
|
-
from imgprocessor.processor import process_image
|
|
89
|
+
from imgprocessor.processor import process_image, process_image_obj
|
|
90
90
|
|
|
91
|
-
process_image(input_uri,
|
|
91
|
+
process_image(input_uri, params, out_path=out_path)
|
|
92
|
+
# 或者
|
|
93
|
+
process_image_obj(im, params, out_path=out_path)
|
|
92
94
|
```
|
|
93
95
|
|
|
94
96
|
参数说明:
|
|
95
97
|
|
|
96
98
|
- `input_uri` str,输入图像文件路径或者链接地址
|
|
97
|
-
- `out_path` str, 输出图像保存路径
|
|
98
99
|
- `params` str or json,图像处理参数,参数说明详见 [Reference.md](https://github.com/SkylerHu/py-img-processor/blob/master/docs/Reference.md)
|
|
100
|
+
- `out_path` str, 输出图像保存路径, 默认为空,为空时返回二进制内容
|
|
99
101
|
|
|
100
102
|
|
|
101
103
|
### 图像处理参数为字符串
|
|
@@ -111,9 +113,9 @@ from imgprocessor.processor import process_image
|
|
|
111
113
|
|
|
112
114
|
process_image(
|
|
113
115
|
"docs/imgs/lenna-400x225.jpg",
|
|
114
|
-
"/tmp/output.png",
|
|
115
116
|
# 对图片缩放、裁剪、生成圆角、并转成png存储
|
|
116
117
|
f"resize,s_200/crop,w_200,h_200,g_center/watermark,text_{base64url_encode('Hello 世界')},color_FFF,size_20/circle,r_10/format,png",
|
|
118
|
+
out_path="/tmp/output.png",
|
|
117
119
|
)
|
|
118
120
|
```
|
|
119
121
|
|
|
@@ -129,7 +131,6 @@ process_image(
|
|
|
129
131
|
```python
|
|
130
132
|
process_image(
|
|
131
133
|
"docs/imgs/lenna-400x225.jpg",
|
|
132
|
-
"/tmp/output.png",
|
|
133
134
|
{
|
|
134
135
|
"actions": [
|
|
135
136
|
{"key": "resize", "s": 200},
|
|
@@ -140,6 +141,7 @@ process_image(
|
|
|
140
141
|
],
|
|
141
142
|
"format": "png",
|
|
142
143
|
},
|
|
144
|
+
out_path="/tmp/output.png",
|
|
143
145
|
)
|
|
144
146
|
```
|
|
145
147
|
该操作与上述字符串示例参数等效。
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{py_img_processor-1.2.4 → py_img_processor-1.3.2}/py_img_processor.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{py_img_processor-1.2.4 → py_img_processor-1.3.2}/py_img_processor.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|