Hi, I know some of you will say that patch is not sexy :) It's my first look into wrlib. I will provide more.
The patch is working on that: 1) the tests examples were not compiling cause of a missing X11 lib call 2) load.c is used to identify the file format, i rebased the checks on what is provided from mime package, it will be faster 3) 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 inlined & enclosed regards, david --- wrlib/load.c | 18 ++-- wrlib/load_ppm.c | 270 +++++++++++++++++++++++++++++++++++++++-------- wrlib/tests/Makefile.am | 2 +- wrlib/tests/testdraw.c | 1 + wrlib/tests/view.c | 6 +- 5 files changed, 240 insertions(+), 57 deletions(-) diff --git a/wrlib/load.c b/wrlib/load.c index 94ef564..061a50d 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 @@ -275,7 +275,7 @@ char *RGetImageFileFormat(const char *file) static WRImgFormat identFile(const char *path) { FILE *file; - unsigned char buffer[32]; + unsigned char buffer[7]; size_t nread; assert(path != NULL); @@ -295,7 +295,7 @@ static WRImgFormat identFile(const char *path) RETRY( fclose(file) ) /* check for XPM */ - if (strncmp((char *)buffer, "/* XPM */", 9) == 0) + if (strncmp((char *)buffer, "/* XPM", 6) == 0) return IM_XPM; /* check for TIFF */ @@ -303,14 +303,12 @@ static WRImgFormat identFile(const char *path) || (buffer[0] == 'M' && buffer[1] == 'M' && buffer[2] == 0 && buffer[3] == '*')) return IM_TIFF; -#ifdef USE_PNG /* check for PNG */ - if (!png_sig_cmp(buffer, 0, 8)) + if (buffer[0] == 0x89 && buffer[1] == 'P' && buffer[2] == 'N' && buffer[3] == 'G') return IM_PNG; -#endif - /* check for raw PPM or PGM */ - if (buffer[0] == 'P' && (buffer[1] == '5' || buffer[1] == '6')) + /* check for PBM or PGM or PPM */ + if (buffer[0] == 'P' && (buffer[1] > '0' && buffer[1] < '7') && (buffer[2] == 0x0a || buffer[2] == 0x20 || buffer[2] == 0x09 || buffer[2] == 0x0d)) return IM_PPM; /* check for JPEG */ @@ -318,7 +316,7 @@ static WRImgFormat identFile(const char *path) return IM_JPEG; /* check for GIF */ - if (buffer[0] == 'G' && buffer[1] == 'I' && buffer[2] == 'F') + if (buffer[0] == 'G' && buffer[1] == 'I' && buffer[2] == 'F' && buffer[3] == '8') return IM_GIF; return IM_UNKNOWN; diff --git a/wrlib/load_ppm.c b/wrlib/load_ppm.c index 49c10db..b45d0f0 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 <stdlib.h> #include <stdio.h> #include <string.h> +#include <limits.h> #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; } diff --git a/wrlib/tests/Makefile.am b/wrlib/tests/Makefile.am index e447e97..76c9872 100644 --- a/wrlib/tests/Makefile.am +++ b/wrlib/tests/Makefile.am @@ -8,7 +8,7 @@ EXTRA_DIST = test.png tile.xpm ballot_box.xpm AM_CPPFLAGS = -I$(srcdir)/.. $(DFLAGS) @HEADER_SEARCH_PATH@ -LIBLIST = $(top_builddir)/wrlib/libwraster.la +LIBLIST = $(top_builddir)/wrlib/libwraster.la @XLIBS@ testdraw_SOURCES = testdraw.c testdraw_LDADD = $(LIBLIST) diff --git a/wrlib/tests/testdraw.c b/wrlib/tests/testdraw.c index 8d416bb..2b209f5 100644 --- a/wrlib/tests/testdraw.c +++ b/wrlib/tests/testdraw.c @@ -561,6 +561,7 @@ int main(int argc, char **argv) { RContextAttributes attr; int visualID = -1; + (void) argc; ProgName = strrchr(argv[0], '/'); if (!ProgName) diff --git a/wrlib/tests/view.c b/wrlib/tests/view.c index 6b107af..52c3ade 100644 --- a/wrlib/tests/view.c +++ b/wrlib/tests/view.c @@ -24,8 +24,10 @@ int main(int argc, char **argv) attr.colors_per_channel = 4; ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr); - if (argc < 2) + if (argc < 2) { + printf("using default image as none was provided\n"); img = RGetImageFromXPMData(ctx, image_name); + } else img = RLoadImage(ctx, argv[1], 0); @@ -70,7 +72,7 @@ int main(int argc, char **argv) exit(1); } - printf("%ix%i\n", img->width, img->height); + printf("size is %ix%i\n", img->width, img->height); win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 10, 10, img->width, img->height, 0, 0, 0); XSetWindowBackgroundPixmap(dpy, win, pix); -- 1.7.10.4
0001-Improved-NETPBM-support-file-format-detection-and-fi.patch
Description: Binary data