diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2011-03-11 03:28:42 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2011-03-11 03:28:42 +0000 |
commit | 3f7f181714ab33d18bd53cf45fc0391424ac1357 (patch) | |
tree | f843f8a263a28774f50fd7bf1e0309dae64c0721 | |
parent | 203e49361723c72e45906d360d5d6e9019594893 (diff) | |
download | netpbm-mirror-3f7f181714ab33d18bd53cf45fc0391424ac1357.tar.gz netpbm-mirror-3f7f181714ab33d18bd53cf45fc0391424ac1357.tar.xz netpbm-mirror-3f7f181714ab33d18bd53cf45fc0391424ac1357.zip |
Add -byrow
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1428 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r-- | converter/other/pngtopam.c | 107 |
1 files changed, 90 insertions, 17 deletions
diff --git a/converter/other/pngtopam.c b/converter/other/pngtopam.c index dd16d431..635c8aa0 100644 --- a/converter/other/pngtopam.c +++ b/converter/other/pngtopam.c @@ -43,6 +43,7 @@ struct CmdlineInfo { float gamma; /* -1.0 means unspecified */ const char * text; unsigned int time; + unsigned int byrow; }; @@ -93,6 +94,8 @@ parseCommandLine(int argc, &textSpec, 0); OPTENT3(0, "time", OPT_FLAG, NULL, &cmdlineP->time, 0); + OPTENT3(0, "byrow", OPT_FLAG, NULL, + &cmdlineP->byrow, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ @@ -309,7 +312,19 @@ typedef struct { -----------------------------------------------------------------------------*/ struct pngx * pngxP; png_byte ** pngRaster; + /* The entire raster of the PNG. Null if this is a + row-at-a-time object. Constant. + + We give a pointer into this to the user. + */ + png_byte * rowBuf; + /* The buffer in which we put the most recently read row. + Null if this is an all-at-once object. Constant. + + We give a pointer into this to the user. + */ unsigned int nextRowNum; + /* The number of the next row to be read from this object. */ } Reader; @@ -333,6 +348,8 @@ reader_createAllAtOnce(struct pngx * const pngxP, allocPngRaster(pngxP, &readerP->pngRaster); + readerP->rowBuf = NULL; + png_read_image(pngxP->png_ptr, readerP->pngRaster); readerP->nextRowNum = 0; @@ -342,20 +359,45 @@ reader_createAllAtOnce(struct pngx * const pngxP, +static Reader * +reader_createRowByRow(struct pngx * const pngxP, + FILE * const ifP) { +/*---------------------------------------------------------------------------- + Create a Reader object that uses libpng's one-row-at-a-time raster reading + interface (libpng calls this the "low level" interface). + + The Reader object reads from the PNG file, via libpng, as its client + requests the rows. +-----------------------------------------------------------------------------*/ + Reader * readerP; + + MALLOCVAR_NOFAIL(readerP); + + readerP->pngxP = pngxP; + + readerP->pngRaster = NULL; + + MALLOCARRAY(readerP->rowBuf, computePngLineSize(pngxP)); + + if (!readerP->rowBuf) + pm_error("Could not allocate %u bytes for a PNG row buffer", + computePngLineSize(pngxP)); + + readerP->nextRowNum = 0; + + return readerP; +} + + + static void reader_destroy(Reader * const readerP) { - png_read_end(readerP->pngxP->png_ptr, readerP->pngxP->info_ptr); - - /* Note that some of info_ptr is not defined until png_read_end() - completes. That's because it comes from chunks that are at the - end of the stream. In particular, comment and time chunks may - be at the end. Furthermore, they may be in both places, in - which case info_ptr contains different information before and - after png_read_end(). - */ - - freePngRaster(readerP->pngRaster, readerP->pngxP); + if (readerP->pngRaster) + freePngRaster(readerP->pngRaster, readerP->pngxP); + + if (readerP->rowBuf) + free(readerP->rowBuf); free(readerP); } @@ -364,13 +406,25 @@ reader_destroy(Reader * const readerP) { static png_byte * reader_read(Reader * const readerP) { +/*---------------------------------------------------------------------------- + Return a pointer to the next row of the raster. + The pointer is into storage owned by this object. It is good until + the next read from the object, while the object exists. +-----------------------------------------------------------------------------*/ png_byte * retval; - if (readerP->nextRowNum >= readerP->pngxP->info_ptr->height) - retval = NULL; - else - retval = readerP->pngRaster[readerP->nextRowNum++]; + if (readerP->pngRaster) { + if (readerP->nextRowNum >= readerP->pngxP->info_ptr->height) + retval = NULL; + else + retval = readerP->pngRaster[readerP->nextRowNum]; + } else { + png_read_row(readerP->pngxP->png_ptr, readerP->rowBuf, NULL); + retval = readerP->rowBuf; + } + + ++readerP->nextRowNum; return retval; } @@ -398,6 +452,22 @@ readPngInit(struct pngx * const pngxP, +static void +readPngTerm(struct pngx * const pngxP) { + + png_read_end(pngxP->png_ptr, pngxP->info_ptr); + + /* Note that some of info_ptr is not defined until png_read_end() + completes. That's because it comes from chunks that are at the + end of the stream. In particular, comment and time chunks may + be at the end. Furthermore, they may be in both places, in + which case info_ptr contains different information before and + after png_read_end(). + */ +} + + + static png_uint_16 getPngVal(const png_byte ** const pp, int const bitDepth) { @@ -1394,11 +1464,12 @@ convertpng(FILE * const ifP, readPngInit(pngxP, ifP); - rasterReaderP = reader_createAllAtOnce(pngxP, ifP); - if (verbose) dumpPngInfo(pngxP); + rasterReaderP = cmdline.byrow ? + reader_createRowByRow(pngxP, ifP) : reader_createAllAtOnce(pngxP, ifP); + if (cmdline.time) showTime(pngxP); if (tfP) @@ -1429,6 +1500,8 @@ convertpng(FILE * const ifP, reader_destroy(rasterReaderP); + readPngTerm(pngxP); + fflush(stdout); pngx_destroy(pngxP); |