Skip to content

Commit d258dde

Browse files
author
funnygeeker
committed
Add missing files
1 parent 3ca0396 commit d258dde

File tree

3 files changed

+227
-0
lines changed

3 files changed

+227
-0
lines changed

tool/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## 工具(Chinese)
2+
3+
### 说明
4+
- 这里包含了一些 `Python` 程序,可以用它们将您的的图片或者视频转换为 `micropython-easydisplay` 所支持的图片格式
5+
- 请注意,这是 `Python` 程序,并不能在 `MicroPython` 上面运行,请保证您的 `Python` 版本大于 `3.8`
6+
7+
8+
## Tools (English)
9+
10+
### Description
11+
- This section includes some Python programs that can be used to convert your images or videos to the image format supported by `micropython-easydisplay`.
12+
- Please note that these are Python programs and cannot be run on MicroPython. Please ensure that your Python version is greater than `3.8`.

tool/image_tools.py

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# 您可以通过使用 python3 的 pillow 库将图片转换为 pbm 格式,比如:
2+
# convert_type = "1" # 1 为黑白图像,RGBA 为彩色图像
3+
# from PIL import Image
4+
# with Image.open("文件名.png", "r") as img:
5+
# img2 = img.convert(convert_type)
6+
# img2.save("文件名.pbm")
7+
8+
import os
9+
10+
try:
11+
from PIL import Image
12+
except ImportError:
13+
os.system('pip3 install pillow -i https://mirrors.aliyun.com/pypi/simple/')
14+
from PIL import Image
15+
16+
17+
def _get_output_path(file: str, path: str, extension: str = None):
18+
"""
19+
根据文件路径和输出路径,获取输出文件的路径
20+
21+
Args:
22+
file: 文件路径
23+
path: 输出路径
24+
extension: 文件扩展名,为 None 时保持扩展名不变
25+
26+
Returns:
27+
文件名
28+
"""
29+
file_name = file.split("/")[-1] # 除去原路径,保留文件名
30+
file_name = file_name.split(".")
31+
if extension:
32+
if len(file_name) > 1: # 若需要更改扩展名且已存在文件扩展名,则去除
33+
del file_name[-1]
34+
file_name[-1] += ".{}".format(extension.lstrip(".")) # 增加扩展名
35+
36+
file_name = ".".join(file_name) # 考虑文件名含多个 "." 的情况
37+
return "{}/{}".format(path.rstrip("/"), file_name) # 将文件名与输出路径合并
38+
39+
40+
def _color(r: int, g: int, b: int) -> int:
41+
"""
42+
将 (0-255) 值的:红绿蓝 转换为 16-bit 的 565 编码
43+
44+
Args:
45+
r: 红
46+
g: 绿
47+
b: 蓝
48+
49+
Returns:
50+
color (int): 0-65535
51+
"""
52+
return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3
53+
54+
55+
def _calculate_palette(color, bg_color) -> tuple:
56+
"""
57+
通过 主体颜色 和 背景颜色 计算调色板
58+
59+
Args:
60+
color: 主体颜色
61+
bg_color: 背景颜色
62+
"""
63+
return [bg_color & 0xFF, (bg_color & 0xFF00) >> 8], [color & 0xFF, (color & 0xFF00) >> 8]
64+
65+
66+
def _flatten_byte_data(byte_data, palette) -> bytearray:
67+
"""
68+
将 二进制 黑白图像渲染为 RGB565 彩色图像
69+
Args:
70+
byte_data: 图像数据
71+
palette: 调色板
72+
73+
Returns:
74+
75+
"""
76+
_temp = []
77+
r = range(7, -1, -1)
78+
for _byte in byte_data:
79+
for _b in r:
80+
_temp.extend(palette[(_byte >> _b) & 0x01])
81+
return bytearray(_temp)
82+
83+
84+
def _convert_image(file, output_path=".", convert_type="1", size: tuple = None, image_type: str = "pbm"):
85+
"""
86+
将图片转换为 指定 格式
87+
88+
Args:
89+
file: 原图片路径
90+
output_path: 输出路径(文件夹)
91+
convert_type: 图像类型("1" 为黑白图像,"RGBA" 为彩色图像)
92+
size: 图像大小
93+
image_type: 图像类型(图像文件后缀名)
94+
"""
95+
with Image.open(file, "r") as img:
96+
img2 = img.convert(convert_type)
97+
if size:
98+
img2 = img2.resize(size, Image.LANCZOS)
99+
file_path = _get_output_path(file, output_path, image_type)
100+
path = file_path.split('/')
101+
del path[-1]
102+
path = "/".join(path)
103+
if not os.path.exists(path):
104+
os.makedirs(path)
105+
img2.save(file_path)
106+
107+
108+
def image_to_pbm(file, output_path=".", convert_type="1", size: tuple = None):
109+
"""
110+
将图片转换为 PBM 格式
111+
112+
Args:
113+
file: 原图片路径
114+
output_path: 输出路径(文件夹)
115+
convert_type: 图像类型("1" 为黑白图像,"RGBA" 为彩色图像)
116+
size: 图像大小
117+
"""
118+
_convert_image(file, output_path, convert_type, size, "pbm")
119+
120+
121+
def image_to_bmp(file, output_path=".", convert_type="1", size: tuple = None):
122+
"""
123+
将图片转换为 BMP 格式
124+
125+
Args:
126+
file: 原图片路径
127+
output_path: 输出路径(文件夹)
128+
convert_type: 图像类型("1" 为黑白图像,"RGBA" 为彩色图像)
129+
size: 图像大小
130+
"""
131+
_convert_image(file, output_path, convert_type, size, "bmp")
132+
133+
134+
def pbm_to_dat(file, output_path=".", color: int = 65535, bg_color: int = 0, reverse: bool = False):
135+
"""
136+
将 PBM 图片转换为 micropython-easydisplay 专用的 DAT 格式
137+
138+
Args:
139+
file: 原图片路径
140+
output_path: 输出路径(文件夹)
141+
color: 图案颜色(仅黑白两色的 PBM 图片生效)
142+
bg_color: 背景颜色(仅黑白两色的 PBM 图片生效)
143+
reverse: 图像颜色反转
144+
"""
145+
with open(file, "rb") as img:
146+
file_format = img.readline() # 读取文件格式
147+
if file_format == b"P4\n" or file_format == b"P6\n":
148+
_width, _height = [int(value) for value in img.readline().split()] # 获取图片的宽度和高度
149+
with open(_get_output_path(file, output_path, "dat"), "wb") as f:
150+
f.write('EasyDisplay\nV1\n{} {}\n'.format(_width, _height).encode('utf-8')) # 写入文件头
151+
print(_width, _height)
152+
if file_format == b"P4\n":
153+
palette = _calculate_palette(color, bg_color) # 计算调色板
154+
data = img.read(4096)
155+
while data:
156+
if reverse:
157+
data = bytes([~b & 0xFF for b in data])
158+
f.write(_flatten_byte_data(data, palette))
159+
data = img.read(4096)
160+
elif file_format == b"P6\n":
161+
max_pixel_value = img.readline() # 获取最大像素值
162+
buffer = bytearray(_width * 2)
163+
for _y in range(_height): # 逐行处理图片
164+
for _x in range(_width): # 逐像素处理
165+
color_bytearray = img.read(3)
166+
r, g, b = color_bytearray[0], color_bytearray[1], color_bytearray[2]
167+
if reverse:
168+
r = 255 - r
169+
g = 255 - g
170+
b = 255 - b
171+
buffer[_x * 2: (_x + 1) * 2] = _color(r, g, b).to_bytes(2, 'big') # 通过索引赋值
172+
f.write(buffer)
173+
else:
174+
try:
175+
raise TypeError("[ERROR] Unsupported File Format {} !".format(file_format.rstrip(b"\n")))
176+
except:
177+
raise TypeError("[ERROR] Unsupported File Format!")
178+
179+
180+
if __name__ == "__main__":
181+
# 使用示例
182+
image_to_pbm("(image_file_path)", "(image_output_folder)", "RGBA", size=(64, 64))
183+
pbm_to_dat("(pbm_file_path)", "(image_output_folder)")
184+
image_to_bmp("(image_file_path)", "(image_output_folder)", "RGBA", size=(64, 64))

tool/video_tools.py

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import os
2+
3+
try:
4+
import cv2
5+
except ImportError:
6+
os.system('pip3 install opencv-python -i https://mirrors.aliyun.com/pypi/simple/')
7+
import cv2
8+
9+
10+
def convert_video_to_png(video_path: str, output_path: str, interval: int = 10):
11+
"""
12+
将视频转换为图片
13+
14+
Args:
15+
video_path: 视频文件路径
16+
output_path: 图片输出路径(文件夹)
17+
interval: 每间隔 X 帧,截取取一张图片
18+
"""
19+
num = 1
20+
vid = cv2.VideoCapture(video_path)
21+
while vid.isOpened():
22+
is_read, frame = vid.read()
23+
if is_read:
24+
if num % interval == 1:
25+
file_num = '%08d' % num
26+
cv2.imwrite(f"{output_path.rstrip('/')}/{file_num}.png", frame)
27+
# 00000100.jpg 代表第111帧
28+
cv2.waitKey(1)
29+
num += 1
30+
else:
31+
break

0 commit comments

Comments
 (0)