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

Attachment: 0001-Improved-NETPBM-support-file-format-detection-and-fi.patch
Description: Binary data

Reply via email to