4.3 KiB
4.3 KiB
ImageSee 图像解码库
vpsdk/imagesee 是一个纯用户态的 PNG / JPEG 解码库,配套示例应用
Apps/ImageSee 在窗口中并排显示解码结果。
1. 目录与模块
vpsdk/imagesee/
├── imagesee.vp 公共 API:load / decode_memory / checksum
├── image.vp Image 类型与像素打包(0xAARRGGBB)
├── inflate.vp zlib / DEFLATE(stored / fixed / dynamic Huffman)
├── png.vp PNG:全部颜色类型、1/2/4/8/16 位、Adam7
└── jpeg.vp JPEG:baseline/extended sequential、4:4:4/4:2:2/4:2:0
Apps/ImageSee/ 示例应用(窗口 + 两块 FBCanvas)
Assets/images/ 示例图片(由 Scripts/gen_imagesee_assets.py 生成)
2. 公共 API
import vpsdk.imagesee.imagesee as imagesee
img = imagesee.load("/IMAGES/SAMPLE.PNG") # 失败返回 None
if img is not None:
w = img.width
h = img.height
c = img.pixels[y * w + x] # 0xAARRGGBB
r = (c >> 16) & 0xFF
g = (c >> 8) & 0xFF
b = c & 0xFF
img2 = imagesee.decode_memory(buf, size) # 已有字节流时使用
sum32 = imagesee.checksum(img) # FNV-1a,用于回归比对
name = imagesee.format_name(img) # "png" / "jpeg"
像素格式与 ViperOS 窗口 / FBCanvas 一致:0xAARRGGBB,alpha 字节目前由
合成层忽略,解码器一律输出 255(PNG 的透明像素保留 alpha=0 于像素字中)。
3. PNG 支持
- 签名、IHDR、PLTE、tRNS、IDAT(可多块)、IEND
- 颜色类型:0(灰度)、2(RGB)、3(调色板)、4(灰度+alpha)、6(RGBA)
- 位深:1/2/4/8/16(按 PNG 规则缩小到 8 位输出)
- 过滤:None / Sub / Up / Average / Paeth
- Adam7 隔行扫描
- 解码后输出 RGBA;调色板 tRNS、灰度和 RGB 的透明色都会转成 alpha=0
4. JPEG 支持
- Baseline / extended sequential Huffman(SOF0 / SOF1)
- 灰度与 YCbCr,色度子采样 4:4:4 / 4:2:2 / 4:2:0(以及任意 H/V 因子)
- DQT(8/16 位)、DHT、DRI + RSTn 重启标记
- 组件按 ID 识别(1=Y、2=Cb、3=Cr),也兼容 Adobe APP14 的 RGB 变换
- 8×8 浮点 IDCT,YCbCr → RGB 后输出
限制:渐进式 JPEG(SOF2)目前明确返回 None(不做“解一半”的错误输出);
CMYK/YCCK 返回 None;不支持 EXIF 方向、缩略图、算术编码。
5. 示例应用
/APPS/IMAGESEE.ELF 启动后:
- 依次解码并打印
/IMAGES/SAMPLE.PNG、PHOTO.JPG、GRAY.JPG、PAL.PNG、INTER.PNG的尺寸、FNV 校验和与 3 个采样像素; - 创建窗口,左画 PNG、右画 JPEG(等比缩放居中);
- 失败时对应面板显示品红/深蓝棋盘,串口打印
FAILED stage=N。
build.py 会:
- 编译
Apps/ImageSee到disk/apps/imagesee.elf - 把
Assets/images/*.png|jpg复制到disk/images/ - 内核
main.vp在 Explorer/FontDemo 之后自动 spawn ImageSee(pid=7)
重建示例图片:
python Scripts/gen_imagesee_assets.py # 需要 Pillow,仅生成资源时使用
6. 已验证
2026-10-28,QEMU 512MB,无头启动:
| 文件 | 类型 | 结果 |
|---|---|---|
| sample.png | RGBA,非隔行 | 解码像素/校验和与 PIL 完全一致 |
| pal.png | 调色板 + tRNS | 完全一致 |
| inter.png | RGBA,Adam7,alpha 渐变 | 完全一致 |
| photo.jpg | baseline 4:2:0 | 尺寸/采样点与 PIL 在 ±11 内(IDCT/上采样差异) |
| gray.jpg | 灰度 baseline | 采样点完全一致 |
7. Explorer 桌面壁纸
Explorer 启动时调用 imagesee.load("/sys/images/screen/background.jpg"):
- 成功:按“cover”等比裁切铺满 framebuffer,任务栏/窗口叠加在壁纸上
- 失败(文件不存在/解码失败):重试一次;仍失败则保持原来的深色纯色背景
- 构建:
build.py把Assets/background.jpg复制到disk/sys/images/screen/background.jpg - 重新生成壁纸:
python Scripts/gen_imagesee_assets.py(960×540 baseline JPEG)
8. 内存
解码使用 stdlib.malloc(mmap 后端,free 为空操作)。一次 load 会保留:
- 压缩文件字节
- DEFLATE 解压后的扫描线缓冲(PNG)
- 最终
w*h*4像素 - JPEG 的量化系数与分量平面
因此适合中小图片(示例 320×220)。超大图片(>4096²)不建议在当前堆上尝试。