Files
MeowOS-SDK/sdk
AskaEth d84dd949c7 SDK: 图片解码真缩解后端 —— JPEG DCT 域 / PNG 逐行 / BMP 跳行(M23)
stb 的 stbi_load_scaled 是「先整幅解、再重采样」:2000x3000 baseline 峰值 10.07MB、
渐进式 25.84MB、1600x2400 PNG 25.65MB,真机解码余量只有 ~4.2MB。新增解码后端在
解码期只算目标分辨率,峰值只与输出尺寸相关:

- meow_jpeg.c:自写纯 C JPEG 解码(baseline + progressive,Huffman)。按
  ceil(8*maxdim/长边) 选 N 点 DCT 缩解(N=1..7),基函数为「8 点 IDCT 按像素区间
  盒式平均」的 Q12 定点(DC 恒为 F00/8,N 之间亮度一致);系数边解边累加进分量平面,
  不留整幅系数阵列;渐进式跳过精细化扫描(Ah>0)、只解各频带首次扫描 —— 渐进式与
  baseline 内存足迹相同(这是 libjpeg 系列做不到的:它对渐进式必须整幅驻留 JBLOCK)。
  不支持项(4 分量 CMYK/YCCK、算术/无损/分层、12bit 精度)返回 0 回退 stb。
- meow_png_stream.c:libz 逐行 inflate + 反滤波,只把需要的列写进目标行;
  gray/gray+A/RGB/RGBA/调色板,1/2/4/8/16bit(16→8 取高字节);Adam7 等回退 stb。
  BMP 按目标行 seek + 行内跳列(8bpp 调色板/16bpp RGB555/24/32bpp),不读全图。
- meow_ui_img.c:load_file_dim / load_mem_dim 先进后端,失败/不支持回落 stb 旧路径
  (stbi_load_scaled + 精修);输出尺寸与 meow_img_downscale 同公式,对外语义不变。

宿主实测(--wrap malloc,maxdim=720,M23 前后同一夹具):
  2000x3000 baseline     10.07 → 1.86 MiB
  2000x3000 progressive  25.84 → 1.86 MiB
  1600x2400 PNG          25.65 → 1.33 MiB
  1600x2400 BMP          15.97 → 1.32 MiB
  4MP/8MP/12MP JPEG       9.67/13.37/20.12 → 2.30/2.20/2.29 MiB(不随分辨率线性增长)

sdk/test_meow_img_stream.c:峰值断言(≤2.5MiB)、与 stb 整幅+降采样的像素比对
(平均差 4.4-13.7/255,块均值结构相关 ≥0.88)、内存入口逐字节一致、回退矩阵
(CMYK/1bpp BMP/Adam7 PNG)、restart marker、缩解阶扫描 N=4/5/7、坏图容错。
build_sdk.sh 增加 meow_jpeg / meow_png_stream 两个 TU(MIPS32 -Os 零警告)。
体积:目标码 +24.9KB(meow_ui.a +25.5KB),picbrowser 静态二进制 +18.2KB。
2026-11-05 21:33:54 +08:00
..

sdk/ — meow_ui 应用框架(源码 + 构建)

本目录是 meow_ui.a 的自包含源码树:公共头在 include/(伞头 meow_ui.h), 构建脚本 build_sdk.sh,宿主逻辑测试 test_*.c。上手指南见仓库根 README.md 与 docs/APP_DEV_GUIDE.md。

构建

cd sdk
./build_sdk.sh        # 产出 sdk/meow_ui.a(mipsel 静态库)

交叉编译器默认 $HOME/Project/R3ProII/.tools/zig-mipsel-cc,可用 MEOW_CC 覆盖。

时钟:mipsel o32 时钟/睡眠 ABI 修复(已内置)

公开 SDK 现已内置 mipsel o32 时钟/睡眠 ABI 修复(见 CLOCK_ABI.md), 源码在 meow_ui_time.c。

  • 背景:zig 内置 musl 在 mipsel 上「头文件声明 64 位 time_t、实现却走 time32 系统调用」, 导致 meow_ui_time_ms() 毫秒位恒 0、高 32 位随机;usleep() 亚秒等待立即返回(忙等空转)。
  • 修复:meow_ui_time_ms() 直接按内核 o32 ABI(8 字节 {int32 sec; int32 nsec;})取时, 再自行升成 64 位毫秒;同一 TU 强定义 __clock_gettime / __clock_gettime64 / __clock_nanosleep / __clock_nanosleep_time64 / __nanosleep_time64,在链接期接管 libc 里那份 ABI 不一致的实现。
  • 链接顺序要求:应用必须把 meow_ui.a 放在 -lc 之前(cc ... meow_ui.a ... -lc), 强定义才能生效。仓库内 examples/hello/build_hello.sh 与 tuku/build_tuku.sh 均如此; 自定义构建脚本请照抄这个顺序,否则取时/睡眠会静默回到坏实现。
  • 非 mipsel 目标(宿主单测、aarch64 等)走普通 clock_gettime,行为不变。

已知限制

  • 2038 前有效:内核侧仍是 time32(tv_sec 为 int32),秒数超出 INT32_MAX 即溢出; 本修复只保证「头/实现的宽度一致」,不把内核升到 time64。
  • 同源缺陷未修:futex 相对超时(pthread_cond_timedwait 的亚秒等待)、timerfd_settime、 clock_settime/clock_adjtime、pselect/ppoll 等仍受同一句 !__ILP32__ 影响; 清单与影响见 CLOCK_ABI.md §6。SDK 自身不直接使用这些路径。
  • 真机验收:本修复的证据是反汇编 + 宿主单测(本机无 qemu-mipsel),设备侧仍需实测确认。

宿主测试

无硬件即可跑(gcc 直接编译,不链 meow_ui.a):

cd sdk
# 时钟换算与单调性
gcc -Os -Wall -Wextra -I. -Iinclude -c meow_ui_time.c -o meow_ui_time_host.o
gcc -Os -Wall -Wextra -I. -Iinclude test_meow_time.c meow_ui_time_host.o -o test_meow_time
./test_meow_time                       # == PASS == / checks=N

# 伞头与其余模块测试(示例)
gcc -I. -Iinclude test_umbrella.c <各 sdk 源 .c> test_host_stub.c -lpthread -o test_umbrella
./test_umbrella

注意:宿主编译时 meow_ui_time.c 走 MEOW_TIME32_KERNEL_ABI 0 分支(普通 clock_gettime), 因此宿主测试不能证明 mipsel o32 路径正确 —— 那条路径的正确性靠 CLOCK_ABI.md §4 的 反汇编证据(nm 符号来源 + syscall 4263/4265 的 8 字节转换)。