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
Loading
ili9341-cap-touch