webpdec.h: single-file WebP decoder
libwebp 1.6.0's decode + demux path (lossy VP8, lossless VP8L, VP8X container, ALPH alpha, and the WebPDemux/WebPAnimDecoder animation API) amalgamated into one stb-style header, built as portable C99 with all SIMD, threads and host file I/O disabled. amalgamate.py regenerates webpdec.h from a pinned, auto-cloned libwebp checkout; tests/run.sh checks decode output bit-exactly against reference libwebp. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
/* test harness: decode a .webp to RGBA, report, dump a PPM for eyeballing */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define WEBPDEC_IMPLEMENTATION
|
||||
#include "webpdec.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) { fprintf(stderr, "usage: %s file.webp [out.ppm]\n", argv[0]); return 2; }
|
||||
FILE *f = fopen(argv[1], "rb");
|
||||
if (!f) { perror("open"); return 1; }
|
||||
fseek(f, 0, SEEK_END); long n = ftell(f); fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = malloc(n);
|
||||
if (fread(buf, 1, n, f) != (size_t)n) { perror("read"); return 1; }
|
||||
fclose(f);
|
||||
|
||||
int w = 0, h = 0;
|
||||
if (!WebPGetInfo(buf, n, &w, &h)) { fprintf(stderr, "not a webp / bad header\n"); return 1; }
|
||||
printf("WebPGetInfo: %dx%d\n", w, h);
|
||||
|
||||
uint8_t *rgba = WebPDecodeRGBA(buf, n, &w, &h);
|
||||
if (!rgba) { fprintf(stderr, "decode FAILED\n"); return 1; }
|
||||
printf("decoded: %dx%d, RGBA (R,G,B,A top-to-bottom)\n", w, h);
|
||||
|
||||
/* sample a few pixels */
|
||||
long center = ((long)h/2 * w + w/2) * 4;
|
||||
printf("center px RGBA = %d %d %d %d\n",
|
||||
rgba[center], rgba[center+1], rgba[center+2], rgba[center+3]);
|
||||
|
||||
/* checksum + alpha presence */
|
||||
unsigned long sum = 0; int has_alpha = 0;
|
||||
for (long i = 0; i < (long)w*h; i++) {
|
||||
sum += rgba[i*4] + rgba[i*4+1] + rgba[i*4+2];
|
||||
if (rgba[i*4+3] != 255) has_alpha = 1;
|
||||
}
|
||||
printf("rgb checksum=%lu non-opaque-alpha=%s\n", sum, has_alpha ? "yes" : "no");
|
||||
|
||||
if (argc >= 3) { /* .raw => raw RGBA dump; else opaque PPM */
|
||||
const char *p = argv[2];
|
||||
size_t L = 0; while (p[L]) L++;
|
||||
FILE *o = fopen(argv[2], "wb");
|
||||
if (L >= 4 && p[L-4]=='.' && p[L-3]=='r' && p[L-2]=='a' && p[L-1]=='w') {
|
||||
fwrite(rgba, 4, (size_t)w*h, o);
|
||||
} else {
|
||||
fprintf(o, "P6\n%d %d\n255\n", w, h);
|
||||
for (long i = 0; i < (long)w*h; i++) fwrite(&rgba[i*4], 1, 3, o);
|
||||
}
|
||||
fclose(o);
|
||||
printf("wrote %s\n", argv[2]);
|
||||
}
|
||||
WebPFree(rgba);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user