Files
ViperOS/docs/imagesee.md
T

4.3 KiB
Raw Blame History

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 启动后:

  1. 依次解码并打印 /IMAGES/SAMPLE.PNG、PHOTO.JPG、GRAY.JPG、 PAL.PNG、INTER.PNG 的尺寸、FNV 校验和与 3 个采样像素;
  2. 创建窗口,左画 PNG、右画 JPEG(等比缩放居中);
  3. 失败时对应面板显示品红/深蓝棋盘,串口打印 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²)不建议在当前堆上尝试。