From 89973760e357aaf87b834f93e133ffb76b157d4b Mon Sep 17 00:00:00 2001 From: giraffedata Date: Tue, 29 Aug 2006 16:19:20 +0000 Subject: Add pm_errormsg(), pm_setusererrormsg(), pm_setusermessage(), release memory before longjmping git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@30 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- lib/libppm1.c | 290 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 199 insertions(+), 91 deletions(-) (limited to 'lib/libppm1.c') diff --git a/lib/libppm1.c b/lib/libppm1.c index 57a1db7d..a7ea78cf 100644 --- a/lib/libppm1.c +++ b/lib/libppm1.c @@ -19,6 +19,7 @@ #include #include #include + #include "ppm.h" #include "libppm.h" #include "pgm.h" @@ -29,6 +30,7 @@ #include "libpam.h" #include "fileio.h" #include "mallocvar.h" +#include "nstring.h" pixel * @@ -150,124 +152,211 @@ ppm_readppminit(FILE * const fileP, -void -ppm_readppmrow(FILE* const fileP, - pixel* const pixelrow, - int const cols, - pixval const maxval, - int const format) { - - switch (format) { - case PPM_FORMAT: { - unsigned int col; - for (col = 0; col < cols; ++col) { - pixval const r = pm_getuint(fileP); - pixval const g = pm_getuint(fileP); - pixval const b = pm_getuint(fileP); - - if (r > maxval) - pm_error("Red sample value %u is greater than maxval (%u)", - r, maxval); - if (g > maxval) - pm_error("Green sample value %u is greater than maxval (%u)", - g, maxval); - if (b > maxval) - pm_error("Blue sample value %u is greater than maxval (%u)", - b, maxval); - - PPM_ASSIGN(pixelrow[col], r, g, b); - } +static void +readppm(FILE * const fileP, + pixel * const pixelrow, + unsigned int const cols, + pixval const maxval, + int const format) { + + unsigned int col; + + for (col = 0; col < cols; ++col) { + pixval const r = pm_getuint(fileP); + pixval const g = pm_getuint(fileP); + pixval const b = pm_getuint(fileP); + + if (r > maxval) + pm_error("Red sample value %u is greater than maxval (%u)", + r, maxval); + if (g > maxval) + pm_error("Green sample value %u is greater than maxval (%u)", + g, maxval); + if (b > maxval) + pm_error("Blue sample value %u is greater than maxval (%u)", + b, maxval); + + PPM_ASSIGN(pixelrow[col], r, g, b); } - break; +} - /* For PAM, we require a depth of 3, which means the raster format - is identical to Raw PPM! How convenient. - */ - case PAM_FORMAT: - case RPPM_FORMAT: { - unsigned int const bytesPerSample = maxval < 256 ? 1 : 2; - unsigned int const bytesPerRow = cols * 3 * bytesPerSample; - - unsigned int bufferCursor; - unsigned char * rowBuffer; - ssize_t rc; - MALLOCARRAY(rowBuffer, bytesPerRow); + +static void +readrppm(FILE * const fileP, + pixel * const pixelrow, + unsigned int const cols, + pixval const maxval, + int const format) { + + unsigned int const bytesPerSample = maxval < 256 ? 1 : 2; + unsigned int const bytesPerRow = cols * 3 * bytesPerSample; - if (rowBuffer == NULL) - pm_error("Unable to allocate memory for row buffer " - "for %u columns", cols); + unsigned char * rowBuffer; + const char * error; + + MALLOCARRAY(rowBuffer, bytesPerRow); + + if (rowBuffer == NULL) + asprintfN(&error, "Unable to allocate memory for row buffer " + "for %u columns", cols); + else { + ssize_t rc; rc = fread(rowBuffer, 1, bytesPerRow, fileP); if (feof(fileP)) - pm_error("Unexpected EOF reading row of PPM image."); + asprintfN(&error, "Unexpected EOF reading row of PPM image."); else if (ferror(fileP)) - pm_error("Error reading row. fread() errno=%d (%s)", - errno, strerror(errno)); + asprintfN(&error, "Error reading row. fread() errno=%d (%s)", + errno, strerror(errno)); else if (rc != bytesPerRow) - pm_error("Error reading row. Short read of %u bytes " - "instead of %u", rc, bytesPerRow); - - bufferCursor = 0; /* start at beginning of rowBuffer[] */ + asprintfN(&error, "Error reading row. Short read of %u bytes " + "instead of %u", rc, bytesPerRow); + else { + unsigned int bufferCursor; + + error = NULL; + + bufferCursor = 0; /* start at beginning of rowBuffer[] */ - if (bytesPerSample == 1) { - unsigned int col; - for (col = 0; col < cols; ++col) { - pixval const r = rowBuffer[bufferCursor++]; - pixval const g = rowBuffer[bufferCursor++]; - pixval const b = rowBuffer[bufferCursor++]; - PPM_ASSIGN(pixelrow[col], r, g, b); - } - } else { - /* two byte samples */ - unsigned int col; - for (col = 0; col < cols; ++col) { - pixval r, g, b; - - r = rowBuffer[bufferCursor++] << 8; - r |= rowBuffer[bufferCursor++]; - - g = rowBuffer[bufferCursor++] << 8; - g |= rowBuffer[bufferCursor++]; - - b = rowBuffer[bufferCursor++] << 8; - b |= rowBuffer[bufferCursor++]; - - PPM_ASSIGN(pixelrow[col], r, g, b); + if (bytesPerSample == 1) { + unsigned int col; + for (col = 0; col < cols; ++col) { + pixval const r = rowBuffer[bufferCursor++]; + pixval const g = rowBuffer[bufferCursor++]; + pixval const b = rowBuffer[bufferCursor++]; + PPM_ASSIGN(pixelrow[col], r, g, b); + } + } else { + /* two byte samples */ + unsigned int col; + for (col = 0; col < cols; ++col) { + pixval r, g, b; + + r = rowBuffer[bufferCursor++] << 8; + r |= rowBuffer[bufferCursor++]; + + g = rowBuffer[bufferCursor++] << 8; + g |= rowBuffer[bufferCursor++]; + + b = rowBuffer[bufferCursor++] << 8; + b |= rowBuffer[bufferCursor++]; + + PPM_ASSIGN(pixelrow[col], r, g, b); + } } } free(rowBuffer); } - break; + if (error) { + pm_errormsg("%s", error); + strfree(error); + pm_longjmp(); + } +} - case PGM_FORMAT: - case RPGM_FORMAT: { - gray * const grayrow = pgm_allocrow(cols); + + +static void +readpgm(FILE * const fileP, + pixel * const pixelrow, + unsigned int const cols, + pixval const maxval, + int const format) { + + jmp_buf jmpbuf; + jmp_buf * origJmpbufP; + gray * grayrow; + + grayrow = pgm_allocrow(cols); + + if (setjmp(jmpbuf) != 0) { + pgm_freerow(grayrow); + pm_setjmpbuf(origJmpbufP); + pm_longjmp(); + } else { unsigned int col; + + pm_setjmpbufsave(&jmpbuf, &origJmpbufP); pgm_readpgmrow(fileP, grayrow, cols, maxval, format); + for (col = 0; col < cols; ++col) { pixval const g = grayrow[col]; PPM_ASSIGN(pixelrow[col], g, g, g); } - pgm_freerow(grayrow); + pm_setjmpbuf(origJmpbufP); } - break; + pgm_freerow(grayrow); +} - case PBM_FORMAT: - case RPBM_FORMAT: { - bit * const bitrow = pbm_allocrow(cols); + + +static void +readpbm(FILE * const fileP, + pixel * const pixelrow, + unsigned int const cols, + pixval const maxval, + int const format) { + + jmp_buf jmpbuf; + jmp_buf * origJmpbufP; + bit * bitrow; + + bitrow = pbm_allocrow(cols); + + if (setjmp(jmpbuf) != 0) { + pbm_freerow(bitrow); + pm_setjmpbuf(origJmpbufP); + pm_longjmp(); + } else { unsigned int col; + pm_setjmpbufsave(&jmpbuf, &origJmpbufP); + pbm_readpbmrow(fileP, bitrow, cols, format); + for (col = 0; col < cols; ++col) { pixval const g = (bitrow[col] == PBM_WHITE) ? maxval : 0; PPM_ASSIGN(pixelrow[col], g, g, g); } - pbm_freerow(bitrow); + pm_setjmpbuf(origJmpbufP); } - break; + pbm_freerow(bitrow); +} + + + +void +ppm_readppmrow(FILE * const fileP, + pixel * const pixelrow, + int const cols, + pixval const maxval, + int const format) { + + switch (format) { + case PPM_FORMAT: + readppm(fileP, pixelrow, cols, maxval, format); + break; + + /* For PAM, we require a depth of 3, which means the raster format + is identical to Raw PPM! How convenient. + */ + case PAM_FORMAT: + case RPPM_FORMAT: + readrppm(fileP, pixelrow, cols, maxval, format); + break; + + case PGM_FORMAT: + case RPGM_FORMAT: + readpgm(fileP, pixelrow, cols, maxval, format); + break; + + case PBM_FORMAT: + case RPBM_FORMAT: + readpbm(fileP, pixelrow, cols, maxval, format); + break; default: pm_error("Invalid format code"); @@ -281,17 +370,36 @@ ppm_readppm(FILE * const fileP, int * const colsP, int * const rowsP, pixval * const maxvalP) { - pixel** pixels; - int row; + + jmp_buf jmpbuf; + jmp_buf * origJmpbufP; + pixel ** pixels; + int cols, rows; + pixval maxval; int format; - ppm_readppminit(fileP, colsP, rowsP, maxvalP, &format); + ppm_readppminit(fileP, &cols, &rows, &maxval, &format); - pixels = ppm_allocarray(*colsP, *rowsP); + pixels = ppm_allocarray(cols, rows); - for (row = 0; row < *rowsP; ++row) - ppm_readppmrow(fileP, pixels[row], *colsP, *maxvalP, format); + if (setjmp(jmpbuf) != 0) { + ppm_freearray(pixels, rows); + pm_setjmpbuf(origJmpbufP); + pm_longjmp(); + } else { + unsigned int row; + pm_setjmpbufsave(&jmpbuf, &origJmpbufP); + + for (row = 0; row < rows; ++row) + ppm_readppmrow(fileP, pixels[row], cols, maxval, format); + + *colsP = cols; + *rowsP = rows; + *maxvalP = maxval; + + pm_setjmpbuf(origJmpbufP); + } return pixels; } -- cgit 1.4.1