Files
MeowOS-SDK/sdk/meow_jpeg.h
T
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

49 lines
2.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* meow_jpeg.h — M23 真缩解后端内部接口(**不对外导出**,不在 meow_ui.h 伞头里)。
*
* 后端直接产出「目标显示尺寸」的 RGBA,不做「先整幅解、再重采样」:
* - JPEG(meow_jpeg.c):DCT 域缩解 1/8、1/4、1/2(N=1/2/4 点 IDCT),渐进式只解到
* 首个精细化扫描(首个 Ah>0)为止——低频带此时已完整,再往后只是为了更细的量化精度。
* - PNG(meow_png_stream.c):libz inflate 逐行 defilter,按步长丢行丢列直写目标尺寸。
* - BMP(meow_png_stream.c):按行 seek + 行内跳列(同一套「只碰需要的行」思路)。
* 三者峰值都只与「输出尺寸 + 目标图像」相关,不随源图分辨率线性增长。
*
* 不支持的特性一律返回 0,由 meow_ui_img.c 回退 stb(行为与 M23 之前完全一致):
* 4 分量 CMYK/YCCK、算术编码/无损/分层 JPEG、Adam7 交错 PNG、1/2/4bpp 与 RLE BMP 等。
*
* 许可证:本文件与 meow_jpeg.c / meow_png_stream.c 为 MeowOS 自写代码(MIT,随 SDK 发布)。
* 不引入第三方解码器源码——理由见 M23 报告「为什么不用 IJG libjpeg」:libjpeg 系列对
* 渐进式 JPEG 必须整幅驻留系数阵列(≈1 字节/源像素/分量),正是审计里 +23.5MB 的来源,
* 换成它也无法把渐进式峰值压到 2.5MB 以内。
*/
#ifndef MEOW_JPEG_H
#define MEOW_JPEG_H
#include <stddef.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/* 解码 path / 内存里的图,直接产出「长边 ≤ maxdim 且按 meow_img_downscale 同一公式等比缩放」
* 的 tw×th RGBA(4 通道 straight alpha,malloc 分配,调用方 free)。
* 返回 1 成功(tw/th/rgba 已填);0 = 不支持/失败/不需要(调用方回退 stb 或旧入口)。 */
int meow_img_backend_file(const char *path, int maxdim, int *tw, int *th, unsigned char **rgba);
int meow_img_backend_mem(const void *buf, size_t len, int maxdim, int *tw, int *th, unsigned char **rgba);
/* 目标尺寸:与 meow_img_downscale 同一公式(长边 = maxdim,短边按比例截断,下限 1)。 */
void meow_img_target_dims(int w, int h, int maxdim, int *tw, int *th);
/* meow_png_stream.c 提供(PNG 逐行 inflate / BMP 按行跳采样)。f 与 mem 二选一:
* f != NULL 走文件流(只读需要的行/块),否则从 mem[0..len) 读。 */
int meow_png_decode_stream(FILE *f, const unsigned char *mem, size_t len,
int maxdim, int *tw, int *th, unsigned char **rgba);
int meow_bmp_decode_stream(FILE *f, const unsigned char *mem, size_t len,
int maxdim, int *tw, int *th, unsigned char **rgba);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_JPEG_H */