哔哩哔哩粉丝计数器:设置ESP32显示GIF动画

NO.1
下载GIF

参考地址

https://www.dongtaituku.com/erciyuan/202203/732777.html

选择一个GIF

NO.2
编辑GIF

使用网站

https://ezgif.com/

调整尺寸

选择GIF Resizer

此图片的alt属性为空;文件名为image-347-1024x454.png

上传GIF

选择要编辑的GIF并点击上传

此图片的alt属性为空;文件名为image-348-1024x408.png

调整尺寸

本文为调整60×60

此图片的alt属性为空;文件名为image-349-1024x538.png

转为JPG序列帧

点击split,并选择为JPG格式

按已知的测试

目前如果不适用jpg图片,会无法转为esp32需要的dat文件,png格式不支持

如果不使用这个网站,而是使用python代码吧gif转为jpg,同样也会遇到esp32转换格式不支持的问题

此图片的alt属性为空;文件名为image-350-1024x535.png

下载序列帧

下载打包好的序列帧

此图片的alt属性为空;文件名为image-351-1024x582.png

解压缩

把下载的jpg序列帧解压缩

此图片的alt属性为空;文件名为image-352-1024x219.png

使用以下代码把jpg转为二级制文件

# img_to_binary.py
import struct
import numpy as np
from PIL import Image  # PIL就是pillow库


def color565(r, g, b):
return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3


def main():
for i in range(1, 11):
        img = Image.open("./images/PuBu{}.jpg".format(i))
# print(img.format, img.size, img.mode)
        img_data = np.array(img)  

with open("./images/PuBu{}.dat".format(i), "wb") as f:
for line in img_data:
for dot in line:
                    f.write(struct.pack("H", color565(dot[0], dot[1], dot[2]))[::-1])


if __name__ == '__main__':
    main()

得到dat文件

此图片的alt属性为空;文件名为image-353-1024x195.png

esp32开启wifi准备接收二进制流文件

# recv_img_dat.py 在MicroPython上启动TCP服务器,接收数据
import time
import network
import machine
import socket


def do_connect():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect('dsx2020', '13545631471')  # WIFI名称和密码
        i = 1
while not wlan.isconnected():
            print("正在链接...{}".format(i))
            i += 1
            time.sleep(1)
    print('network config:', wlan.ifconfig())


# 0. 链接wifi
do_connect()

# 1. 创建TCP套接字
server_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2. 绑定本地信息
server_s.bind(("", 8080))

# 3. 设置为被动的
server_s.listen(128)

print("等待对方链接...")

# 4. 等待客户端链接
new_s, client_info = server_s.accept()

print("等待对方发送图片数据...")

# 3. 创建文件,接收数据
for i in range(1, 12):
with open("PuBu{}.dat".format(i), "wb") as f:
for j in range(60):
# 3.1 接收数据
            data = new_s.recv(120)  # 240*2=480 一行有240个点,每个点有2个字节
# 3.2 写到文件
            f.write(data)
    print("接收完毕{}".format(i))
print("全部数据接收完毕")

# 7. 关闭套接字
new_s.close()
server_s.close()

使用python发送文件

# send_img_dat_to_esp.py 发送二进制文件到开发板中
from socket import *

# 1. 创建socket
tcp_client_socket = socket(AF_INET, SOCK_STREAM)

# 2. 链接服务器
tcp_client_socket.connect(("192.168.1.192", 8080))  # ESP32开发板的IP地址和端口号

# 2. 打开文件,发送数据
for i in range(1, 12):
with open("./dat3/PuBu{}.dat".format(i), "rb") as f:
for j in range(60):
# 3.1 写到文件
            data = f.read(120)
# 3.2 接收数据
            tcp_client_socket.send(data)  # 240*2=480 一行有240个点,每个点有2个字节
    print("发送完毕{}".format(i))
print("所有数据发送完毕")

注意以上的都是60或者120,因为我们的图片尺寸是60×60

如果图片是80×80之类的,可以改为80,160,按照这个规律

满屏就是240×240,改为240,480等

NO.3
ESP32显示图片

确认esp32收到图片后

此图片的alt属性为空;文件名为image-354.png

执行代码

# show_img.py 显示图片代码
from machine import Pin, SPI
import st7789_new
import time


tft = st7789_new.ST7889_Image(SPI(2, 60000000), dc=Pin(2), cs=Pin(5), rst=Pin(15))
tft.fill(st7789_new.color565(0, 0, 0))  # 背景设置为黑色


def show_img():
with open("image.dat", "rb") as f:
for row in range(60,120):
            buffer = f.read(120)
            tft.show_img(0, row, 239, row, buffer)



f_list = [open("PuBu{}.dat".format(i), "rb") for i in range(1, 11)]
def show_img2():
while True:
for f in f_list:  # 遍历14个文件,显示图片
            f.seek(0)
for row in range(60, 120, 1):
                buffer = f.read(120)
                tft.show_img(120, row, 239, row+24, buffer)


#show_img()
show_img2()

x轴

for row in range(60, 120, 1):

60和120是要渲染的x轴,可以是(0,60,1)左上角,也可以是(60,120,1),左上角 向右移动60px,也可以是(180,240,1)等

y轴

tft.show_img(120, row, 239, row+24, buffer)

120,239,可以随意改为240以内的数字,并查看当前gif所处的位置,按照效果调整即可,比如

tft.show_img(0, row, 60, row+24, buffer)

tft.show_img(60, row, 120, row+24, buffer)

+24不用变,这个是控制GIF的刷新频率的

NO.4
添加文字的代码

图片和文字同时存在

# show_img.py 显示图片代码
from machine import Pin, SPI
import st7789_new
import time

import st7789py
import vga2_bold_16x32 as font



tft = st7789_new.ST7889_Image(SPI(2, 60000000), dc=Pin(2), cs=Pin(5), rst=Pin(15))
tft.fill(st7789_new.color565(0, 0, 0))  # 背景设置为黑色

# 创建显示屏对象
tft2 = st7789py.ST7789(SPI(2, 60000000), 240, 240, reset=Pin(15), dc=Pin(2), cs=Pin(5), backlight=Pin(22), rotation=0)
# 显示Hello
tft2.text(font, "fans:1200", 30, 60, st7789py.color565(255, 169, 77), st7789py.color565(0, 0, 0))
tft2.text(font, "num:99", 30, 100, st7789py.color565(255, 255, 255), st7789py.color565(0, 0, 0))



f_list = [open("PuBu{}.dat".format(i), "rb") for i in range(1, 11)]
def show_img2():

while True:
for f in f_list:  # 遍历14个文件,显示图片
            f.seek(0)
for row in range(60, 120, 1):
                buffer = f.read(120)
                tft.show_img(150, row, 210, row+24, buffer)


show_img2()
NO.5
最终效果

NO.6
Tips

本文仅为哔哩哔哩粉丝计数器笔记

实际操作较为繁琐,关键代码后续补充

END