from machine import Pin, SPI
from ili9341 import Display, color565
import urequests
import struct
import network
import time
import gc
import esp
import os
# 顯示器參數
ROTATION = 180
spi = SPI(1, baudrate=20000000, sck=Pin(15), mosi=Pin(7))
display = Display(spi, cs=Pin(4), dc=Pin(6), rst=Pin(5), rotation=ROTATION)
display.clear(color565(0, 255, 0))
print('w=', display.width, 'h=', display.height)
# Wi-Fi 連線
SSID = 'Wokwi-GUEST'
PASSWORD = ''
def do_connect(ssid=SSID, password=PASSWORD):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('Connecting to network...')
wlan.connect(ssid, password)
while not wlan.isconnected():
pass
print('網路設定:', wlan.ifconfig())
do_connect()
# 解析 BMP 文件頭
def parse_bmp_header(bmp_data):
if bmp_data[:2] != b'BM': # BMP 檔案應以 "BM" 開頭
raise ValueError("無效的 BMP 檔案")
pixel_data_offset = struct.unpack('<I', bmp_data[10:14])[0]
width = struct.unpack('<I', bmp_data[18:22])[0]
height = struct.unpack('<I', bmp_data[22:26])[0]
bpp = struct.unpack('<H', bmp_data[28:30])[0] # 每像素位數
print(f"圖像寬度: {width}, 高度: {height}, 偏移: {pixel_data_offset}, 每像素位數: {bpp}")
if bpp != 24:
raise ValueError("只支援 24 位元的 BMP 檔案")
return width, height, pixel_data_offset
# 縮放圖像到顯示器大小 240x320
def resize_image(original_data, original_width, original_height, target_width, target_height):
print('縮放圖像到顯示器大小 240x320')
resized_data = bytearray(target_width * target_height * 3) # 24-bit 顏色
for y in range(target_height):
for x in range(target_width):
# 使用最近鄰插值法 (Nearest Neighbor)
src_x = int(x * original_width / target_width)
src_y = int(y * original_height / target_height)
idx = (src_x + src_y * original_width) * 3
r, g, b = original_data[idx:idx + 3]
resized_idx = (x + y * target_width) * 3
resized_data[resized_idx:resized_idx + 3] = bytes([r, g, b])
print(f"縮放後的數據大小: {len(resized_data)} bytes")
return resized_data
# 將像素資料轉換為 RGB565 格式
def convert_to_rgb565(pixel_data, width, height):
print("將像素資料轉換為 RGB565 格式")
rgb565_data = bytearray(width * height * 2) # 每個像素用 2 字節表示
for y in range(height):
for x in range(width):
idx = (x + y * width) * 3 # BMP 原始資料的索引
r, g, b = pixel_data[idx], pixel_data[idx + 1], pixel_data[idx + 2]
# RGB888 轉換為 RGB565
r5 = r >> 3 # 取高 5 位
g6 = g >> 2 # 取高 6 位
b5 = b >> 3 # 取高 5 位
rgb565 = (r5 << 11) | (g6 << 5) | b5 # 合成 RGB565 格式
# 將 RGB565 資料保存到陣列
rgb565_data_idx = (x + y * width) * 2
rgb565_data[rgb565_data_idx] = rgb565 & 0xFF # 低 8 位
rgb565_data[rgb565_data_idx + 1] = (rgb565 >> 8) & 0xFF # 高 8 位
print(f"RGB565 資料大小: {len(rgb565_data)} bytes")
return rgb565_data
# 更新下載並顯示 BMP 的函數
def download_and_display_bmp(url, display, target_width=240, target_height=320):
try:
gc.collect()
# 下載 BMP 圖片
print("正在下載 BMP 圖像...")
response = urequests.get(url)
if response.status_code == 200:
print("下載 BMP 圖像 OK")
bmp_data = response.content
# 解析 BMP 頭信息
width, height, pixel_data_offset = parse_bmp_header(bmp_data)
print(f"BMP 圖片寬度: {width}, 高度: {height}")
# 提取像素資料
pixel_data = bmp_data[pixel_data_offset:]
# 將像素資料轉換為 RGB565
rgb565_data = convert_to_rgb565(pixel_data, width, height)
# 縮放至顯示大小(若需要)
print("顯示縮放後的圖像")
start_time = time.ticks_ms() # 記錄顯示開始時間
display.draw_sprite(rgb565_data, 0, 0, target_width, target_height)
# 計算顯示時間
display_time = time.ticks_diff(time.ticks_ms(), start_time)
print("顯示時間: {} 毫秒".format(display_time))
print("圖像顯示完成!")
else:
print("下載 BMP 圖像失敗,狀態碼:", response.status_code)
except Exception as e:
print("下載或顯示圖像時出錯:", e)
# BMP 圖片網址
bmp_url = 'https://samples-files.com/samples/images/bmp/480-360-sample.bmp'
download_and_display_bmp(bmp_url, display)
Loading
esp32-s3-devkitc-1
esp32-s3-devkitc-1
Loading
ili9341-cap-touch
ili9341-cap-touch