-
Notifications
You must be signed in to change notification settings - Fork 0
/
apnggif.py
119 lines (91 loc) · 2.81 KB
/
apnggif.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import apnggif_sys
import logging
import coloredlogs
import oppapi
from typing import Union, Tuple, Optional, List
from pathlib import Path
log = logging.getLogger("apnggif")
Input = Union[str, Path, List[str], List[Path]]
Output = Optional[Union[str, Path, List[str], List[Path]]]
Transparency = Optional[int]
Color = Optional[Union[str, Tuple[int, int, int]]]
class Error(Exception):
"""
Exception class for apnggif.
"""
def apnggif(png: Input, gif: Output = None, tlevel: Transparency = None, bg: Color = None):
"""
Python interface to apng2gif.
"""
log.debug(f"apnggif(png={png}, gif={gif}, tlevel={tlevel}, bg={bg})")
pngs = read_input(png)
gifs = read_output(gif, pngs)
if len(pngs) != len(gifs):
raise Error("png input length != gif output length")
if tlevel and bg:
raise Error("You can't set both transparency and bg.")
if tlevel is None:
if bg is None:
tlevel = 128
else:
tlevel = -1
if bg is None:
bg = ""
for png, gif in zip(pngs, gifs):
log.info(f'apnggif("{png}", "{gif}", {tlevel}, "{bg}"))')
apnggif_sys.apnggif(png, gif, tlevel, bg)
def read_input(png: Input) -> List[str]:
if not png:
raise Error("png source is not specified")
if isinstance(png, (list, tuple)):
pass
elif isinstance(png, str):
png = [Path(png)]
elif isinstance(png, Path):
png = [png]
png = [p if isinstance(p, Path) else Path(p) for p in png]
return [str(p.resolve()) for p in png]
def read_output(inp: Output, png: Optional[List[Union[str, Path]]] = None) -> List[str]:
gifs: List = []
if isinstance(inp, str):
gifs = [inp]
elif isinstance(inp, Path):
gifs = [inp]
elif isinstance(inp, (list, tuple)):
gifs = inp
elif not inp and png:
for p in png:
p = str(p.resolve()) if isinstance(p, Path) else p
if p[-4:].lower() == ".png":
gifs.append(p[:-4] + ".gif")
else:
gifs.append(p)
return [str(p.resolve()) if isinstance(p, Path) else p for p in gifs]
@oppapi.oppapi
class Opt:
"""
apnggif - Convert APNG to GIF.
"""
png: List[Path]
""" List of PNGs """
tlevel: Optional[int]
""" Transparency level, defaults to 128 """
bg: Optional[str]
""" Background color """
verbose: Optional[bool]
""" Enable verbose logging """
def main():
"""
apnggif - Convert APNG to GIF.
"""
opt = oppapi.from_args(Opt)
coloredlogs.install(
level="DEBUG" if opt.verbose else "INFO", logger=log, fmt="%(levelname)s %(message)s"
)
log.debug(opt)
try:
apnggif(opt.png, tlevel=opt.tlevel, bg=opt.bg)
except Exception as e:
log.error(e)
if __name__ == "__main__":
main()