/* rdimg.c — stb_image 封装(实现见 rdimg.h)。 */ #include "rdimg.h" #include "stb_image.h" #include #include int rdimg_probe_wh(const uint8_t *data, size_t size, int *w, int *h) { if (!data || !w || !h) return -1; int x = 0, y = 0, c = 0; if (!stbi_info_from_memory(data, (int)size, &x, &y, &c)) return -1; *w = x; *h = y; return 0; } /* 双线性采样单通道:src 步长 sw,取 (fx,fy) 浮点邻近 4 像素加权。 */ static int bilin(const uint8_t *s, int sw, int sh, double fx, double fy, int ch) { int x0 = (int)fx, y0 = (int)fy; double dx = fx - x0, dy = fy - y0; int x1 = x0 + 1 < sw ? x0 + 1 : x0; int y1 = y0 + 1 < sh ? y0 + 1 : y0; double top = s[y0 * sw * ch + x0 * ch] * (1 - dx) + s[y0 * sw * ch + x1 * ch] * dx; double bot = s[y1 * sw * ch + x0 * ch] * (1 - dx) + s[y1 * sw * ch + x1 * ch] * dx; return (int)(top * (1 - dy) + bot * dy); } int rdimg_decode_scale(const uint8_t *data, size_t size, int max_w, int max_h, uint16_t **out565, int *ow, int *oh) { if (!data || !out565) return -1; *out565 = NULL; *ow = *oh = 0; int w = 0, h = 0, ch = 0; /* 请求 RGB(3 通道)便于统一处理 */ stbi_uc *px = stbi_load_from_memory(data, (int)size, &w, &h, &ch, 3); if (!px || w <= 0 || h <= 0) return -1; /* 缩放:长边超 max 才缩(不放大) */ double scale = 1.0; if (w > max_w && max_w > 0) scale = (double)max_w / w; if (h > max_h && max_h > 0) { double s2 = (double)max_h / h; if (s2 < scale) scale = s2; } int dw = (int)(w * scale), dh = (int)(h * scale); if (dw < 1) dw = 1; if (dh < 1) dh = 1; uint16_t *dst = (uint16_t *)malloc((size_t)dw * (size_t)dh * 2); if (!dst) { stbi_image_free(px); return -6; } if (scale == 1.0) { /* 原尺寸直接转 565 */ for (int yy = 0; yy < dh; yy++) { const stbi_uc *s = px + (size_t)yy * w * 3; uint16_t *d = dst + (size_t)yy * dw; for (int xx = 0; xx < dw; xx++) { int r = s[xx*3], g = s[xx*3+1], b = s[xx*3+2]; d[xx] = (uint16_t)(((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); } } } else { for (int yy = 0; yy < dh; yy++) { double fy = (double)yy / scale; uint16_t *d = dst + (size_t)yy * dw; for (int xx = 0; xx < dw; xx++) { double fx = (double)xx / scale; int r = bilin(px, w, h, fx, fy, 3); int g = bilin((const uint8_t*)px + 1, w, h, fx, fy, 3); int b = bilin((const uint8_t*)px + 2, w, h, fx, fy, 3); d[xx] = (uint16_t)(((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); } } } stbi_image_free(px); *out565 = dst; *ow = dw; *oh = dh; return 0; }