From d6969177ed75991222213606e74d6aedf3073a95 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Sun, 20 Sep 2026 00:29:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- .vscode/settings.json | 3 +- __pycache__/remo_disp_server.cpython-312.pyc | Bin 0 -> 24614 bytes _proto_test.png | Bin 0 -> 1123 bytes remo_disp_server.py | 52 ++++++++++++++----- remo_disp_ui.html | 41 +++++++++++---- 6 files changed, 73 insertions(+), 25 deletions(-) create mode 100644 __pycache__/remo_disp_server.cpython-312.pyc create mode 100644 _proto_test.png diff --git a/.gitignore b/.gitignore index 3776a10..d0835e6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ !.vscode/launch.json !.vscode/extensions.json *.code-workspace - +*.log # Local History for Visual Studio Code .history/ *.app diff --git a/.vscode/settings.json b/.vscode/settings.json index a8c2003..4b5a294 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,4 @@ { "python-envs.defaultEnvManager": "ms-python.python:conda", - "python-envs.defaultPackageManager": "ms-python.python:conda", - "python-envs.pythonProjects": [] + "python-envs.defaultPackageManager": "ms-python.python:conda" } \ No newline at end of file diff --git a/__pycache__/remo_disp_server.cpython-312.pyc b/__pycache__/remo_disp_server.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..45394011bfee28bd620ecafa46eb4552306f614a GIT binary patch literal 24614 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 b!jdDCIA|~RcXg>>>CMO2j_A1XKDqw`nqGIe literal 0 HcmV?d00001 diff --git a/_proto_test.png b/_proto_test.png new file mode 100644 index 0000000000000000000000000000000000000000..735da167548df560e14d7784549f6c7c3e22c264 GIT binary patch literal 1123 zcmV-p1f2VcP)005u?00000qqJIp000CkNklZF7^At=QVcv>+P{Lnq3#wpS_iMQVj1h#M4?tgJkxt;G4MW2$s3`y>kakd~ zGl2`ccrH%r!Zwh_>eg;rI8lTh3;pqp)C8oQf z+d3y`b=B~nep1XtGy#U=hC%}=9-4|)pv7ql_la`->j$3eyItmv$zXn#B0v1WZTCR; z8e8-h4puPaqmOD92Oqmw$xR>BGhCtcEIL^{ALo>0erYYE*cYY)y?3;7hbInhd#JR! zt?PsRJj_@)gf7t#S8NU?L5 zcetaxw{Ij|3V^rHyLT!*Yl63~^=yZXfPLFLaP9m&rc4-Ip}_EQYK1p6t|fE))_X9^ z;FY9z@yjcOhbFCmX~H@Xay84SP$>UX|NFAUD^2CqeoWXeN=FGi(BLmE>Kr8RwoT@L z+|4VQ=aA(u6}gH^r#~(gQJ+`R2oAw)p(F zI&T84t{R%ME)-$2qb~}ufYT^2!MftF6Y@80mnq;f#M7JE>i_8Vxb9ZUB!8Wa*;D5z zm0$c;;X7gK*5?k(r=Fm^b>X9_?c_DeKd>u9WM$$d-QbkojI!kv1nb(z5kl2ECyuo; z-MVQ@ot)*3`X7lVtlO5Q5~2e9E4eJGbN1KzJ%8tmM>4wz)!jujt*S zxAYhX&96Vaw{JwSj*YH)_f82@N9NIbwnLaYHj1_L^WxO0k(Y-rP`-NQ^X0e4ZwYr@ zz-saJ^?t>}`!W_5L_^%MIaI(ft%A>K6{PTy?w$coX{qn5ell&pCR{mZr0k&ZyLXYw z?Q)+mb(uf??Ec5Lb@iusj#`luf_1>p$Bdj{9l?!qM0{Y09QGI^LiGw6{9auU?mEjl p=d-*Coil+}SIrIo^|kvj#y=uXkhD{(g1rC$002ovPDHLkV1oXTE$09L literal 0 HcmV?d00001 diff --git a/remo_disp_server.py b/remo_disp_server.py index 4617a46..e41f612 100644 --- a/remo_disp_server.py +++ b/remo_disp_server.py @@ -267,18 +267,39 @@ def mono_to_png(data: bytes, width: int, height: int) -> Optional[bytes]: height=height, len_=len(data), ) - img = Image.new("1", (width, height)) # 创建 1bpp 黑白图像 - pix = img.load() # 获取像素访问对象 - ''' - for y in range(height): - for x in range(width): - bi = (y * width + x) // 8 # 字节索引:每 8 像素一字节 - bit = 7 - (x % 8) # 位索引:高位在前 - pix[x, y] = 0 if (bi < len(data) and (data[bi] >> bit) & 1) else 255 # 1→白 0→黑 - ''' - for y in range(height): - for x in range(width): - pix[x, y] = data[y * width + x] + expected_bits = (width * height + 7) // 8 # 1bpp 打包长度 + expected_bytes = width * height # 每像素 1 字节(0/1或0-255)长度 + + if len(data) == expected_bits: + # 1bpp:每字节 8 像素,高位在前 + logger.debug("[mono_to_png] 使用 1bpp 打包解码") + img = Image.new("1", (width, height)) + pix = img.load() + for y in range(height): + row_base = y * width + for x in range(width): + byte_i = (row_base + x) // 8 + bit_i = 7 - (x % 8) + bit = (data[byte_i] >> bit_i) & 1 + pix[x, y] = 255 if bit else 0 + elif len(data) == expected_bytes: + # 8bit:每字节直接对应一个像素,非零当作白 + logger.debug("[mono_to_png] 使用每像素 1 字节解码") + img = Image.new("1", (width, height)) + pix = img.load() + for y in range(height): + row_base = y * width + for x in range(width): + pix[x, y] = 255 if data[row_base + x] else 0 + else: + logger.warning( + "[mono_to_png] payload 长度不匹配,丢弃该帧: data_len={len_}, expected_bits={bits}, expected_bytes={bytes}", + len_=len(data), + bits=expected_bits, + bytes=expected_bytes, + ) + return None + buf = io.BytesIO() # 内存缓冲区 img.save(buf, format="PNG") # 保存为 PNG 格式 png_bytes = buf.getvalue() @@ -329,7 +350,7 @@ def _screen_refresh_loop(): # 当前协议未返回宽高,这里固定为 160x160,可根据实际情况调整 w, h = 160, 160 png = mono_to_png(data, w, h) # 转为 PNG - if png: + if png and isinstance(png, (bytes, bytearray)) and png.startswith(b"\x89PNG\r\n\x1a\n"): b64 = base64.b64encode(png).decode("ascii") # base64 编码便于 JSON 传输 for sid in list(_screen_clients): # 复制列表避免迭代时修改 try: @@ -344,6 +365,11 @@ def _screen_refresh_loop(): sid=sid, err=e, ) + elif png: + logger.warning( + "[_screen_refresh_loop] 生成的 PNG 无效或签名错误,丢弃该帧 png_len={len_}", + len_=len(png), + ) else: # 拉取失败,累计连续失败次数 consecutive_failures += 1 diff --git a/remo_disp_ui.html b/remo_disp_ui.html index fc253f8..2358cb4 100644 --- a/remo_disp_ui.html +++ b/remo_disp_ui.html @@ -392,8 +392,12 @@ } }); // 服务端推送屏幕:data.png 为 base64 编码的 PNG,解码后绘制到 canvas + const scale = 2; // 放大倍数(160x160 -> 320x320) + let canvasInitialized = false; + let latestFrameId = 0; // 用于丢弃旧帧,避免异步解码乱序导致闪烁 socket.on('screen', (data) => { if (!data.png) return; + const frameId = ++latestFrameId; // 无 base64 数据则跳过 const binary = atob(data.png); // base64 解码为二进制字符串 @@ -406,21 +410,38 @@ // 创建临时 URL const img = new Image(); img.onload = () => { - // 图片加载完成后,放大一倍显示(160x160 -> 320x320) - const scale = 2; - canvas.width = img.width * scale; - canvas.height = img.height * scale; + // 图片加载完成后:若该帧不是最新帧则直接丢弃 + if (frameId !== latestFrameId) { + URL.revokeObjectURL(url); + return; + } + + // 首帧初始化 canvas 尺寸(只做一次,避免反复重设导致清空闪烁) + const targetW = img.width * scale; + const targetH = img.height * scale; + if (!canvasInitialized) { + canvas.width = targetW; + canvas.height = targetH; + canvasInitialized = true; + canvas.style.display = 'block'; + placeholder.style.display = 'none'; + } + const ctx = canvas.getContext('2d'); ctx.imageSmoothingEnabled = false; - // 关闭平滑,像素清晰放大 + // 关闭平滑:像素清晰放大 ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height); - // 绘制到 canvas(2 倍尺寸) - canvas.style.display = 'block'; - placeholder.style.display = 'none'; - // 显示 canvas,隐藏占位符 + URL.revokeObjectURL(url); // 释放临时 URL }; + img.onerror = () => { + // 发生错误时同样释放临时 URL + if (frameId === latestFrameId) { + // 不弹窗,避免影响观察;必要时可在这里加日志 + } + URL.revokeObjectURL(url); + }; img.src = url; // 触发加载 }); @@ -465,6 +486,8 @@ placeholder.style.display = ''; placeholder.textContent = '点击「连接」连接装置'; // 隐藏 canvas,显示占位符 + canvasInitialized = false; + latestFrameId = 0; } document.querySelectorAll('.dpad .btn, .action-btn').forEach(btn => {