diff --git a/stb_image.h b/stb_image.h index d9c21bc..ea2de78 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6999,19 +6999,36 @@ static int stbi__pnm_test(stbi__context *s) char p, t; p = (char) stbi__get8(s); t = (char) stbi__get8(s); - if (p != 'P' || (t != '5' && t != '6')) { + if (p != 'P' || (t < '1' || t > '6')) { stbi__rewind( s ); return 0; } return 1; } +typedef enum { + STBI__PNM_BINARY, + STBI__PNM_ASCII, + STBI__PNM_BITMAP, +} stbi__pnm_format; + +typedef struct { + stbi__context *s; + int maxv; + stbi__pnm_format format; +} stbi__pnm; + +static int stbi__pnm_info_raw(stbi__pnm *p, int *x, int *y, int *comp); +static int stbi__pnm_getinteger(stbi__context *s, char *c); + static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; STBI_NOTUSED(ri); - if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + stbi__pnm p; + p.s = s; + if (!stbi__pnm_info_raw(&p, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) return 0; *x = s->img_x; @@ -7023,7 +7040,23 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); - stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + switch (p.format) { + case STBI__PNM_BINARY: + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + break; + default: + STBI_FREE(out); + return NULL; + } + + if(p.maxv != 255) { + /* https://onlinegdb.com/ryWybrS0m */ + size_t i; + int adjust = (255 << 16) / p.maxv; + for(i = 0; i < s->img_n * s->img_x * s->img_y; i++) + out[i] = (out[i] * adjust + 0x8000) >> 16; + } if (req_comp && req_comp != s->img_n) { out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); @@ -7068,43 +7101,60 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c) return value; } -static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +static int stbi__pnm_info_raw(stbi__pnm *p, int *x, int *y, int *comp) { - int maxv, dummy; - char c, p, t; + int dummy; + char c, m, t; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; - stbi__rewind(s); + stbi__rewind(p->s); // Get identifier - p = (char) stbi__get8(s); - t = (char) stbi__get8(s); - if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind(s); + m = (char) stbi__get8(p->s); + t = (char) stbi__get8(p->s); + if (m != 'P') { + stbi__rewind(p->s); return 0; } - *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + if (t != '5' && t != '6') { + if (t != '2' && t != '3' && t != '1') { + if (t != '4') { + stbi__rewind(p->s); + return 0; + } else p->format = STBI__PNM_BITMAP; + } else p->format = STBI__PNM_ASCII; + } else p->format = STBI__PNM_BINARY; + *comp = (t == '6' || t == '3') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm - c = (char) stbi__get8(s); - stbi__pnm_skip_whitespace(s, &c); + c = (char) stbi__get8(p->s); + stbi__pnm_skip_whitespace(p->s, &c); + *x = stbi__pnm_getinteger(p->s, &c); // read width - *x = stbi__pnm_getinteger(s, &c); // read width - stbi__pnm_skip_whitespace(s, &c); + stbi__pnm_skip_whitespace(p->s, &c); + *y = stbi__pnm_getinteger(p->s, &c); // read height - *y = stbi__pnm_getinteger(s, &c); // read height - stbi__pnm_skip_whitespace(s, &c); + if (p->format != STBI__PNM_BITMAP) { + stbi__pnm_skip_whitespace(p->s, &c); + p->maxv = stbi__pnm_getinteger(p->s, &c); // read max value + } else + p->maxv = 1; - maxv = stbi__pnm_getinteger(s, &c); // read max value - - if (maxv > 255) + if (p->maxv > 255) return stbi__err("max value > 255", "PPM image not 8-bit"); else return 1; } + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__pnm p; + p.s = s; + return stbi__pnm_info_raw(&p, x, y, comp); +} #endif static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) diff --git a/tests/t/Makefile b/tests/t/Makefile index c42ddd0..1873d73 100644 --- a/tests/t/Makefile +++ b/tests/t/Makefile @@ -3,9 +3,9 @@ CFLAGS = $(INCLUDES) -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_DIV CPPFLAGS = $(INCLUDES) -Wno-write-strings -DSTB_DIVIDE_TEST LDLIBS = -lm -all: clean image_pnm_8bit +all: clean image_pnm image_pnm_8bit clean: - rm -f image_pnm_8bit + rm -f image_pnm image_pnm_8bit .PHONY: all clean diff --git a/tests/tx/image_pnm.c b/tests/t/image_pnm.c similarity index 100% rename from tests/tx/image_pnm.c rename to tests/t/image_pnm.c diff --git a/tests/tx/image_pnm.t b/tests/t/image_pnm.t similarity index 100% rename from tests/tx/image_pnm.t rename to tests/t/image_pnm.t diff --git a/tests/tx/Makefile b/tests/tx/Makefile index 850b4a5..ff892c3 100644 --- a/tests/tx/Makefile +++ b/tests/tx/Makefile @@ -3,9 +3,9 @@ CFLAGS = $(INCLUDES) -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_DIV CPPFLAGS = $(INCLUDES) -Wno-write-strings -DSTB_DIVIDE_TEST LDLIBS = -lm -all: clean image_pnm image_pnm_ascii +all: clean image_pnm_ascii clean: - rm -f image_pnm image_pnm_ascii + rm -f image_pnm_ascii .PHONY: all clean