From 5c96c69cb5f96caaeb2f73eeabc44af2f5955488 Mon Sep 17 00:00:00 2001 From: David Maciejak Date: Sat, 15 Feb 2014 18:25:13 +0800 Subject: [PATCH] wrlib: Improved NETPBM support, file format detection 1) according to that checks i was able to see that some netpbm support type are missing (exactly: ascii graymap (PGM files) and pixmap (PPM) and ascii/binary bitmap (PBM)) See the link below for more details. http://en.wikipedia.org/wiki/Netpbm_format Signed-off-by: Carlos R. Mafra --- wrlib/load.c | 4 +- wrlib/load_ppm.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 228 insertions(+), 46 deletions(-) diff --git a/wrlib/load.c b/wrlib/load.c index 94ef5640..9667ed2b 100644 --- a/wrlib/load.c +++ b/wrlib/load.c @@ -78,8 +78,8 @@ char **RSupportedFileFormats(void) /* built-in */ tmp[i++] = "XPM"; - /* built-in */ - tmp[i++] = "PPM"; + /* built-in PNM here refers to anymap format: PPM, PGM, PBM */ + tmp[i++] = "PNM"; #ifdef USE_TIFF tmp[i++] = "TIFF"; #endif diff --git a/wrlib/load_ppm.c b/wrlib/load_ppm.c index 49c10dbb..b45d0f0e 100644 --- a/wrlib/load_ppm.c +++ b/wrlib/load_ppm.c @@ -3,6 +3,7 @@ * Raster graphics library * * Copyright (c) 1997-2003 Alfredo K. Kojima + * Copyright (c) 2014 Window Maker Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,79 +27,248 @@ #include #include #include +#include #include "wraster.h" #include "imgformat.h" -static RImage *load_graymap(FILE *file, int w, int h, int max, int raw) +/* fileio.c - routines to read elements based on Netpbm +** +** Copyright (C) 1988 by Jef Poskanzer. +*/ + +char pm_getc(FILE * const fileP) +{ + int ich; + char ch; + + ich = getc(fileP); + if (ich == EOF) + fprintf(stderr, "EOF / read error reading a byte\n"); + ch = (char)ich; + + if (ch == '#') { + do { + ich = getc(fileP); + if (ich == EOF) + fprintf(stderr, "EOF / read error reading a byte\n"); + ch = (char)ich; + } while (ch != '\n' && ch != '\r'); + } + return ch; +} + +unsigned char pm_getrawbyte(FILE * const file) +{ + int iby; + + iby = getc(file); + if (iby == EOF) + fprintf(stderr, "EOF / read error reading a one-byte sample\n"); + return (unsigned char)iby; +} + +int pm_getuint(FILE * const ifP) +{ + char ch; + unsigned int i; + + do { + ch = pm_getc(ifP); + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); + + if (ch < '0' || ch > '9') + fprintf(stderr, "junk in file where an unsigned integer should be\n"); + + i = 0; + do { + unsigned int const digitVal = ch - '0'; + + if (i > INT_MAX / 10) { + fprintf(stderr, "ASCII decimal integer in file is too large to be processed\n"); + return -1; + } + + i *= 10; + + if (i > INT_MAX - digitVal) { + fprintf(stderr, "ASCII decimal integer in file is too large to be processed\n"); + return -1; + } + + i += digitVal; + + ch = pm_getc(ifP); + } while (ch >= '0' && ch <= '9'); + + return i; +} +/******************************************************************************************/ + +/* PGM: support for portable graymap ascii and binary encoding */ +static RImage *load_graymap(FILE * file, int w, int h, int max, int raw) { RImage *image; unsigned char *ptr; - char *buf; int x, y; image = RCreateImage(w, h, 0); if (!image) return NULL; - if (!raw) + if (raw != '2' && raw != '5') return image; if (max < 256) { - buf = malloc(w + 1); - if (!buf) - return NULL; - ptr = image->data; - for (y = 0; y < h; y++) { - if (!fread(buf, w, 1, file)) { - free(buf); - RErrorCode = RERR_BADIMAGEFILE; - return NULL; + if (raw == '2') { + int val; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + val = pm_getuint(file); + + if (val > max || val < 0) { + RErrorCode = RERR_BADIMAGEFILE; + return NULL; + } + + val = val * 255 / max; + *(ptr++) = val; + *(ptr++) = val; + *(ptr++) = val; + } } + } else { + if (raw == '5') { + char *buf; + buf = malloc(w + 1); + if (!buf) + return NULL; + for (y = 0; y < h; y++) { + if (!fread(buf, w, 1, file)) { + free(buf); + RErrorCode = RERR_BADIMAGEFILE; + return NULL; + } - for (x = 0; x < w; x++) { - *(ptr++) = buf[x]; - *(ptr++) = buf[x]; - *(ptr++) = buf[x]; + for (x = 0; x < w; x++) { + *(ptr++) = buf[x]; + *(ptr++) = buf[x]; + *(ptr++) = buf[x]; + } + } + free(buf); } } - free(buf); } - return image; } -static RImage *load_pixmap(FILE *file, int w, int h, int max, int raw) +/* PPM: support for portable pixmap ascii and binary encoding */ +static RImage *load_pixmap(FILE * file, int w, int h, int max, int raw) { RImage *image; - int i; - char buf[3]; unsigned char *ptr; + int i = 0; image = RCreateImage(w, h, 0); if (!image) return NULL; - if (!raw) + if (raw != '3' && raw != '6') return image; ptr = image->data; if (max < 256) { - i = 0; + if (raw == '3') { + int x, y, val; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + for (i = 0; i < 3; i++) { + val = pm_getuint(file); + + if (val > max || val < 0) { + RErrorCode = RERR_BADIMAGEFILE; + return NULL; + } + + val = val * 255 / max; + *(ptr++) = val; + } + } + } + } else if (raw == '6') { + char buf[3]; + while (i < w * h) { + if (fread(buf, 1, 3, file) != 3) { + RErrorCode = RERR_BADIMAGEFILE; + return NULL; + } + + *(ptr++) = buf[0]; + *(ptr++) = buf[1]; + *(ptr++) = buf[2]; + i++; + } + } + } + return image; +} + +/* PBM: support for portable bitmap ascii and binary encoding */ +static RImage *load_bitmap(FILE * file, int w, int h, int max, int raw) +{ + RImage *image; + int val; + unsigned char *ptr; + + image = RCreateImage(w, h, 0); + if (!image) + return NULL; + + if (raw != '1' && raw != '4') + return image; + + ptr = image->data; + if (raw == '1') { + int i = 0; while (i < w * h) { - if (fread(buf, 1, 3, file) != 3) { + val = pm_getuint(file); + + if (val > max || val < 0) { RErrorCode = RERR_BADIMAGEFILE; return NULL; } - *(ptr++) = buf[0]; - *(ptr++) = buf[1]; - *(ptr++) = buf[2]; + val = (val == 0) ? 255 : 0; + *(ptr++) = val; + *(ptr++) = val; + *(ptr++) = val; i++; } - } + } else { + if (raw == '4') { + unsigned char buf; + int bitshift; + int x, y; + for (y = 0; y < h; y++) { + bitshift = -1; + for (x = 0; x < w; x++) { + if (bitshift == -1) { + buf = pm_getrawbyte(file); + bitshift = 7; + } + val = (buf >> bitshift) & 1; + val = (val == 0) ? 255 : 0; + --bitshift; + *(ptr++) = val; + *(ptr++) = val; + *(ptr++) = val; + } + } + } + } return image; } @@ -123,8 +293,8 @@ RImage *RLoadPPM(const char *file_name) return NULL; } - /* only accept raw pixmaps or graymaps */ - if (buffer[0] != 'P' || (buffer[1] != '5' && buffer[1] != '6')) { + /* accept bitmaps, pixmaps or graymaps */ + if (buffer[0] != 'P' || (buffer[1] < '1' && buffer[1] > '6')) { RErrorCode = RERR_BADFORMAT; fclose(file); return NULL; @@ -152,24 +322,36 @@ RImage *RLoadPPM(const char *file_name) return NULL; } - if (!fgets(buffer, 255, file)) { - RErrorCode = RERR_BADIMAGEFILE; - fclose(file); - return NULL; + if (type != '1' && type != '4') { + if (!fgets(buffer, 255, file)) { + RErrorCode = RERR_BADIMAGEFILE; + fclose(file); + return NULL; + } + /* get max value */ + if (sscanf(buffer, "%i", &m) != 1 || m < 1) { + /* Short file */ + RErrorCode = RERR_BADIMAGEFILE; + fclose(file); + return NULL; + } + } else { + m = 1; } - if (sscanf(buffer, "%i", &m) != 1 || m < 1) { - /* Short file */ - RErrorCode = RERR_BADIMAGEFILE; - fclose(file); - return NULL; + /* check portable bitmap type, ascii = 1 and binary = 4 */ + if (type == '1' || type == '4') + image = load_bitmap(file, w, h, m, type); + else { + /* check portable graymap type, ascii = 2 and binary = 5 */ + if (type == '2' || type == '5') + image = load_graymap(file, w, h, m, type); + else + /* check portable pixmap type, ascii = 3 and binary = 6 */ + if (type == '3' || type == '6') + image = load_pixmap(file, w, h, m, type); } - if (type == '5') - image = load_graymap(file, w, h, m, type == '5'); - else if (type == '6') - image = load_pixmap(file, w, h, m, type == '6'); - fclose(file); return image; } -- 2.11.4.GIT