diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2017-03-28 15:34:36 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2017-03-28 15:34:36 +0000 |
commit | ca561223546a7e8acd055d5b2114869dd88f5114 (patch) | |
tree | 79a54d551eac6df794c539d8b8924aab217a1941 /converter | |
parent | 8b32628b4c65cdd2b09e877150bbc4bcdd9b6ba7 (diff) | |
download | netpbm-mirror-ca561223546a7e8acd055d5b2114869dd88f5114.tar.gz netpbm-mirror-ca561223546a7e8acd055d5b2114869dd88f5114.tar.xz netpbm-mirror-ca561223546a7e8acd055d5b2114869dd88f5114.zip |
Copy Development as new Advanced
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@2932 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter')
-rw-r--r-- | converter/other/bmptopnm.c | 28 | ||||
-rw-r--r-- | converter/other/fiasco/lib/error.c | 8 | ||||
-rw-r--r-- | converter/other/giftopnm.c | 330 | ||||
-rw-r--r-- | converter/other/jbig/libjbig/jbig.c | 2 | ||||
-rw-r--r-- | converter/other/pamtopng.c | 1 | ||||
-rw-r--r-- | converter/other/pamtotiff.c | 92 | ||||
-rw-r--r-- | converter/other/pnmtops.c | 6 | ||||
-rw-r--r-- | converter/other/tifftopnm.c | 540 |
8 files changed, 583 insertions, 424 deletions
diff --git a/converter/other/bmptopnm.c b/converter/other/bmptopnm.c index c39b4fd7..54868364 100644 --- a/converter/other/bmptopnm.c +++ b/converter/other/bmptopnm.c @@ -695,6 +695,13 @@ bmpReadinfoheader(FILE * const ifP, *errorP = NULL; *bytesReadP = cInfoHeaderSize; } + /* Part of our anti-arithmetic overflow strategy is to make sure height + and width always fit in 16 bits, so they can be multiplied together. + This shouldn't be a problem, since they come from 16 bit fields in + the BMP info header. + */ + assert(headerP->cols < (1<<16)); + assert(headerP->rows < (1<<16)); } @@ -1204,6 +1211,9 @@ bmpReadraster(FILE * const ifP, */ unsigned char ** bmpRaster; + assert(cols < (1<<16)); + assert(bytesPerRow < (1<<16)); + bmpRaster = allocBmpRaster(rows, bytesPerRow); *bytesReadP = 0; @@ -1456,8 +1466,8 @@ readBmp(FILE * const ifP, static void writeRasterGen(unsigned char ** const bmpRaster, - int const cols, - int const rows, + unsigned int const cols, + unsigned int const rows, int const format, unsigned int const cBitCount, struct pixelformat const pixelformat, @@ -1492,8 +1502,8 @@ writeRasterGen(unsigned char ** const bmpRaster, static void writeRasterPbm(unsigned char ** const bmpRaster, - int const cols, - int const rows, + unsigned int const cols, + unsigned int const rows, xel const colormap[]) { /*---------------------------------------------------------------------------- Write the PBM raster to Standard Output corresponding to the raw BMP @@ -1510,9 +1520,9 @@ writeRasterPbm(unsigned char ** const bmpRaster, We destroy *bmpRaster as a side effect. -----------------------------------------------------------------------------*/ - unsigned int const colChars = pbm_packed_bytes(cols); + unsigned int const colCharCt = pbm_packed_bytes(cols); - int row; + unsigned int row; enum colorFormat {BlackWhite, WhiteBlack}; enum colorFormat colorformat; @@ -1521,12 +1531,12 @@ writeRasterPbm(unsigned char ** const bmpRaster, else colorformat = BlackWhite; - for (row=0; row < rows; ++row){ + for (row = 0; row < rows; ++row){ unsigned char * const bitrow = bmpRaster[row]; if (colorformat == BlackWhite) { unsigned int i; - for (i = 0; i < colChars; ++i) + for (i = 0; i < colCharCt; ++i) bitrow[i] = ~bitrow[i]; /* flip all pixels */ } @@ -1550,7 +1560,7 @@ main(int argc, const char ** argv) { and gray. */ int cols, rows; - unsigned char **bmpRaster; + unsigned char ** bmpRaster; /* The raster part of the BMP image, as a row x column array, with each element being a raw byte from the BMP raster. Note that bmpRaster[0] is really Row 0 -- the top row of the image, even diff --git a/converter/other/fiasco/lib/error.c b/converter/other/fiasco/lib/error.c index aeb6eaf9..08291ce0 100644 --- a/converter/other/fiasco/lib/error.c +++ b/converter/other/fiasco/lib/error.c @@ -84,10 +84,10 @@ set_error(const char *format, ...) { char * const vstring = va_arg (args, char *); len += strlen(vstring); } else if (*str == 'd') { - va_arg (args, int); + (void)va_arg(args, int); len += 10; } else if (*str == 'c') { - va_arg (args, int); + (void)va_arg(args, int); len += 1; } else return; @@ -129,10 +129,10 @@ error(const char *format, ...) { char * const vstring = va_arg (args, char *); len += strlen(vstring); } else if (*str == 'd') { - va_arg (args, int); + (void)va_arg(args, int); len += 10; } else if (*str == 'c') { - va_arg (args, int); + (void)va_arg(args, int); len += 1; } else { #if HAVE_SETJMP_H diff --git a/converter/other/giftopnm.c b/converter/other/giftopnm.c index b0d479d5..f0946c9e 100644 --- a/converter/other/giftopnm.c +++ b/converter/other/giftopnm.c @@ -24,6 +24,7 @@ #define _BSD_SOURCE /* for strcaseeq */ #include <string.h> #include <assert.h> +#include <stdbool.h> #include "pm_config.h" #include "pm_c_util.h" @@ -42,13 +43,13 @@ #define MAX_LZW_BITS 12 #ifndef FASTPBMRENDER - #define FASTPBMRENDER TRUE + #define FASTPBMRENDER true #endif static const bool useFastPbmRender = FASTPBMRENDER; #ifndef REPORTLZWCODES - #define REPORTLZWCODES FALSE + #define REPORTLZWCODES false #endif static const bool wantLzwCodes = REPORTLZWCODES; @@ -61,7 +62,11 @@ readFile(FILE * const ifP, unsigned char * const buffer, size_t const len, const char ** const errorP) { +/*---------------------------------------------------------------------------- + Read the next 'len' bytes from *ifP into 'buffer'. + Fail if there aren't that many bytes to read. +-----------------------------------------------------------------------------*/ size_t bytesRead; bytesRead = fread(buffer, 1, len, ifP); @@ -92,7 +97,7 @@ struct CmdlineInfo { bool allImages; /* He wants all the images */ unsigned int imageNum; /* image number he wants from input, starting at 0. Undefined - if allImages is TRUE + if allImages is true */ const char * alphaFileName; unsigned int quitearly; @@ -102,7 +107,7 @@ struct CmdlineInfo { static void -parseCommandLine(int argc, char ** argv, +parseCommandLine(int argc, const char ** argv, struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that @@ -136,20 +141,20 @@ parseCommandLine(int argc, char ** argv, &alphaSpec, 0); opt.opt_table = option_def; - opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ - opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + opt.short_allowed = false; /* We have no short (old-fashioned) options */ + opt.allowNegNum = false; /* We have no parms that are negative numbers */ - pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ free(option_def); if (!imageSpec) { cmdlineP->imageNum = 0; - cmdlineP->allImages = FALSE; + cmdlineP->allImages = false; } else { if (strcaseeq(image, "all")) { - cmdlineP->allImages = TRUE; + cmdlineP->allImages = true; } else { char * tailptr; @@ -165,7 +170,7 @@ parseCommandLine(int argc, char ** argv, pm_error("Invalid value for 'image' option. You specified " "zero. The first image is 1."); - cmdlineP->allImages = FALSE; + cmdlineP->allImages = false; cmdlineP->imageNum = (unsigned int) imageNum - 1; } } @@ -312,8 +317,8 @@ readColorMap(FILE * const ifP, assert(cmapSize <= MAXCOLORMAPSIZE); - *hasGrayP = FALSE; /* initial assumption */ - *hasColorP = FALSE; /* initial assumption */ + *hasGrayP = false; /* initial assumption */ + *hasColorP = false; /* initial assumption */ for (i = 0; i < cmapSize; ++i) { const char * error; @@ -327,16 +332,16 @@ readColorMap(FILE * const ifP, if (rgb[0] == rgb[1] && rgb[1] == rgb[2]) { if (rgb[0] != 0 && rgb[0] != GIFMAXVAL) - *hasGrayP = TRUE; + *hasGrayP = true; } else - *hasColorP = TRUE; + *hasColorP = true; } cmapP->size = cmapSize; } -static bool zeroDataBlock = FALSE; +static bool zeroDataBlock = false; /* the most recently read DataBlock was an EOD marker, i.e. had zero length */ @@ -355,10 +360,10 @@ getDataBlock(FILE * const ifP, of the datablock at 'buf', and its length as *lengthP. Except that if we hit EOF or have an I/O error reading the first - byte (size field) of the DataBlock, we return *eofP == TRUE and + byte (size field) of the DataBlock, we return *eofP == true and *lengthP == 0. - We return *eofP == FALSE if we don't hit EOF or have an I/O error. + We return *eofP == false if we don't hit EOF or have an I/O error. If we hit EOF or have an I/O error reading the data portion of the DataBlock, we exit the program with pm_error(). @@ -375,21 +380,21 @@ getDataBlock(FILE * const ifP, error); pm_strfree(error); *errorP = NULL; - *eofP = TRUE; + *eofP = true; *lengthP = 0; } else { if (verbose) pm_message("%d byte block at Position %ld", count, pos); - *eofP = FALSE; + *eofP = false; *lengthP = count; if (count == 0) { *errorP = NULL; - zeroDataBlock = TRUE; + zeroDataBlock = true; } else { const char * error; - zeroDataBlock = FALSE; + zeroDataBlock = false; readFile(ifP, buf, count, &error); if (error) { @@ -417,7 +422,7 @@ readThroughEod(FILE * const ifP) { unsigned char buf[256]; bool eod; - eod = FALSE; /* initial value */ + eod = false; /* initial value */ while (!eod) { bool eof; unsigned int count; @@ -430,7 +435,7 @@ readThroughEod(FILE * const ifP) { "anyway as if an EOD marker were at the end " "of the file."); if (error || eof || count == 0) - eod = TRUE; + eod = true; } } @@ -471,7 +476,7 @@ doCommentExtension(FILE * const ifP) { unsigned int blocklen; bool done; - done = FALSE; + done = false; while (!done) { bool eof; const char * error; @@ -480,7 +485,7 @@ doCommentExtension(FILE * const ifP) { pm_error("Error reading a data block in a comment extension. %s", error); if (blocklen == 0 || eof) - done = TRUE; + done = true; else { buf[blocklen] = '\0'; if (showComment) { @@ -622,7 +627,7 @@ getAnotherBlock(FILE * const ifP, /* Add the next block to the buffer */ getDataBlock(ifP, &gsP->buf[gsP->bufCount], &eof, &count, errorP); if (*errorP) - gsP->streamExhausted = TRUE; + gsP->streamExhausted = true; else { if (eof) { pm_message("EOF encountered in image " @@ -652,7 +657,7 @@ getCode_init(struct GetCodeState * const getCodeStateP) { getCodeStateP->buf[1] = 0; getCodeStateP->bufCount = 2; getCodeStateP->curbit = getCodeStateP->bufCount * 8; - getCodeStateP->streamExhausted = FALSE; + getCodeStateP->streamExhausted = false; } @@ -708,14 +713,14 @@ getCode_get(struct GetCodeState * const gsP, 'codeSize' is the number of bits in the code we are to get. - Return *eofP == TRUE iff we hit the end of the stream. That means a legal + Return *eofP == true iff we hit the end of the stream. That means a legal end of stream, marked by an EOD marker, not just end of file. An end of file in the middle of the GIF stream is an error. If there are bits left in the stream, but not 'codeSize' of them, we - call that a success with *eofP == TRUE. + call that a success with *eofP == true. - Return the code read (assuming *eofP == FALSE and *errorP == NULL) + Return the code read (assuming *eofP == false and *errorP == NULL) as *codeP. -----------------------------------------------------------------------------*/ @@ -737,7 +742,7 @@ getCode_get(struct GetCodeState * const gsP, /* The buffer still doesn't have enough bits in it; that means there were no data blocks left to read. */ - *eofP = TRUE; + *eofP = true; { int const bitsUnused = gsP->bufCount * 8 - gsP->curbit; @@ -754,7 +759,7 @@ getCode_get(struct GetCodeState * const gsP, pm_message("LZW code=0x%03x [%d]", *codeP, codeSize); gsP->curbit += codeSize; - *eofP = FALSE; + *eofP = false; } } } @@ -824,7 +829,7 @@ termStack(struct Stack * const stackP) { LZW is an extension of Limpel-Ziv. The two extensions are: - 1) in Limpel-Ziv, codes are all the same number of bits. In + 1) In Limpel-Ziv, codes are all the same number of bits. In LZW, they start out small and increase as the stream progresses. 2) LZW has a clear code that resets the string table and code @@ -860,7 +865,22 @@ termStack(struct Stack * const stackP) { static int const maxLzwCodeCt = (1<<MAX_LZW_BITS); -struct Decompressor { +typedef struct { +/*---------------------------------------------------------------------------- + An entry in the decompressor LZW code table. +-----------------------------------------------------------------------------*/ + unsigned int next; + /* The next code in the expansion after the one this entry specifies; + this is either another index into the LZW code table or a direct + code, which means it's the last data element in the expansion. + */ + unsigned int dataElement; + /* The data element (color map index or gray level) to add to the + expansion for this entry. + */ +} CodeTableEntry; + +typedef struct { struct Stack stack; bool fresh; /* The stream is right after a clear code or at the very beginning */ @@ -894,18 +914,24 @@ struct Decompressor { /* We are to tolerate bad input data as best we can, rather than just declaring an error and bailing out. */ - unsigned int table[(1 << MAX_LZW_BITS)][2]; /* LZW code table */ -}; + CodeTableEntry table[(1 << MAX_LZW_BITS)]; /* LZW code table */ + /* This contains the strings of expansions of LZW string codes, in + linked list form. table[N] gives the first data element for the + string with string code N and the LZW code for the rest of the + string. The latter is often a string code itself, which can also + be looked up in this table. + */ +} Decompressor; static void -resetDecompressor(struct Decompressor * const decompP) { +resetDecompressor(Decompressor * const decompP) { decompP->codeSize = decompP->initCodeSize+1; decompP->maxCodeCt = 1 << decompP->codeSize; decompP->nextTableSlot = decompP->maxDataVal + 3; - decompP->fresh = TRUE; + decompP->fresh = true; } @@ -919,7 +945,7 @@ validateTransparentIndex(unsigned int const transparentIndex, if (transparentIndex >= cmapSize) { if (tolerateBadInput) { if (transparentIndex > maxDataVal) - pm_error("Invalid transparent index value: %d", + pm_error("Invalid transparent index value: %u", transparentIndex); } else { pm_error("Invalid transparent index value %d in image with " @@ -936,13 +962,13 @@ validateTransparentIndex(unsigned int const transparentIndex, static void -lzwInit(struct Decompressor * const decompP, - FILE * const ifP, - int const initCodeSize, - unsigned int const cmapSize, - bool const haveTransColor, - unsigned int const transparentIndex, - bool const tolerateBadInput) { +lzwInit(Decompressor * const decompP, + FILE * const ifP, + int const initCodeSize, + unsigned int const cmapSize, + bool const haveTransColor, + unsigned int const transparentIndex, + bool const tolerateBadInput) { unsigned int const maxDataVal = (1 << initCodeSize) - 1; @@ -972,8 +998,8 @@ lzwInit(struct Decompressor * const decompP, { unsigned int i; for (i = 0; i <= maxDataVal; ++i) { - decompP->table[i][0] = 0; - decompP->table[i][1] = i < cmapSize ? i : 0; + decompP->table[i].next = 0; + decompP->table[i].dataElement = i < cmapSize ? i : 0; } } decompP->haveTransColor = haveTransColor; @@ -987,7 +1013,7 @@ lzwInit(struct Decompressor * const decompP, getCode_init(&getCodeState); - decompP->fresh = TRUE; + decompP->fresh = true; initStack(&decompP->stack, maxLzwCodeCt); @@ -997,8 +1023,8 @@ lzwInit(struct Decompressor * const decompP, static void -lzwAdjustForPBM(struct Decompressor * const decompP, - GifColorMap const cmap) { +lzwAdjustForPBM(Decompressor * const decompP, + GifColorMap const cmap) { /*---------------------------------------------------------------------------- In the PBM case we use the table index value directly instead of looking up the color map for each pixel. @@ -1009,13 +1035,14 @@ lzwAdjustForPBM(struct Decompressor * const decompP, ----------------------------------------------------------------------------*/ unsigned int i; for (i = 0; i < cmap.size; ++i) - decompP->table[i][1] = cmap.map[i][0] == 0 ? PBM_BLACK : PBM_WHITE; + decompP->table[i].dataElement = + cmap.map[i][0] == 0 ? PBM_BLACK : PBM_WHITE; } static void -lzwTerm(struct Decompressor * const decompP) { +lzwTerm(Decompressor * const decompP) { termStack(&decompP->stack); } @@ -1023,8 +1050,8 @@ lzwTerm(struct Decompressor * const decompP) { static void -pushWholeStringOnStack(struct Decompressor * const decompP, - unsigned int const code0) { +pushWholeStringOnStack(Decompressor * const decompP, + unsigned int const code0) { /*---------------------------------------------------------------------------- Get the whole string that compression code 'code0' represents and push it onto the code stack so the leftmost code is on top. Set @@ -1035,21 +1062,47 @@ pushWholeStringOnStack(struct Decompressor * const decompP, for (stringCount = 0, code = code0; code > decompP->maxDataVal; - ++stringCount, code = decompP->table[code][0] + ++stringCount, code = decompP->table[code].next ) { - pushStack(&decompP->stack, decompP->table[code][1]); + pushStack(&decompP->stack, decompP->table[code].dataElement); } - decompP->firstcode = decompP->table[code][1]; + decompP->firstcode = decompP->table[code].dataElement; pushStack(&decompP->stack, decompP->firstcode); } static void -expandCodeOntoStack(struct Decompressor * const decompP, - unsigned int const incode, - const char ** const errorP) { +addLzwStringCode(Decompressor * const decompP) { + + if (decompP->nextTableSlot < maxLzwCodeCt) { + decompP->table[decompP->nextTableSlot].next = + decompP->prevcode; + decompP->table[decompP->nextTableSlot].dataElement = + decompP->firstcode; + ++decompP->nextTableSlot; + if (decompP->nextTableSlot >= decompP->maxCodeCt) { + /* We've used up all the codes of the current code size. + Future codes in the stream will have codes one bit longer. + But there's an exception if we're already at the LZW + maximum, in which case the codes will simply continue + the same size. + */ + if (decompP->codeSize < MAX_LZW_BITS) { + ++decompP->codeSize; + decompP->maxCodeCt = 1 << decompP->codeSize; + } + } + } +} + + + +static void +expandCodeOntoStack(Decompressor * const decompP, + unsigned int const incode, + const char ** const errorP) { /*---------------------------------------------------------------------------- 'incode' is an LZW string code. It represents a string of true data elements, as defined by the string translation table in *decompP. @@ -1064,58 +1117,56 @@ expandCodeOntoStack(struct Decompressor * const decompP, as *errorP). -----------------------------------------------------------------------------*/ unsigned int code; + const char * gifError; - *errorP = NULL; /* Initial value */ + gifError = NULL; /* Initial value */ if (incode <= decompP->maxDataVal) { if (incode < decompP->cmapSize) code = incode; /* Direct index */ else if (decompP->tolerateBadInput && decompP->haveTransColor && - decompP->table[incode][1] == decompP->transparentIndex) + decompP->table[incode].dataElement == + decompP->transparentIndex) /* transparent code outside cmap exceptional case */ code = incode; else - pm_asprintf(errorP, "Error in GIF image: invalid color code %u. " + pm_asprintf(&gifError, "Invalid color code %u. " "Valid color values are 0 - %u", incode, decompP->cmapSize - 1); - } - else if (incode < decompP->nextTableSlot) + } else if (incode < decompP->nextTableSlot) /* LZW string, defined */ code = incode; - else if (incode == decompP->nextTableSlot && !decompP->fresh) { + else if (incode == decompP->nextTableSlot) { /* It's a code that isn't in our translation table yet. - This does not happen with the decoder in a fresh state. */ - if (wantLzwCodes && verbose) - pm_message ("LZW code valid, but not in decoder table"); - - pushStack(&decompP->stack, decompP->firstcode); - code = decompP->prevcode; + if (decompP->fresh) + pm_asprintf(&gifError, "LZW string code encountered with " + "decompressor in fresh state"); + else { + if (wantLzwCodes && verbose) + pm_message ("LZW code valid, but not in decoder table"); + + pushStack(&decompP->stack, decompP->firstcode); + code = decompP->prevcode; + } } else - pm_asprintf(errorP, "Error in GIF image: invalid LZW code"); - - if (!*errorP) { + pm_asprintf(&gifError, "LZW string code %u " + "is neither a previously defined one nor the " + "next in sequence to define (%u)", + incode, decompP->nextTableSlot); + + if (gifError) { + pm_asprintf(errorP, "INVALID GIF IMAGE: %s", gifError); + pm_strfree(gifError); + } else { pushWholeStringOnStack(decompP, code); - if (decompP->nextTableSlot < maxLzwCodeCt) { - decompP->table[decompP->nextTableSlot][0] = decompP->prevcode; - decompP->table[decompP->nextTableSlot][1] = decompP->firstcode; - ++decompP->nextTableSlot; - if (decompP->nextTableSlot >= decompP->maxCodeCt) { - /* We've used up all the codes of the current code size. - Future codes in the stream will have codes one bit longer. - But there's an exception if we're already at the LZW - maximum, in which case the codes will simply continue - the same size. - */ - if (decompP->codeSize < MAX_LZW_BITS) { - ++decompP->codeSize; - decompP->maxCodeCt = 1 << decompP->codeSize; - } - } - } + addLzwStringCode(decompP); + decompP->prevcode = incode; + + *errorP = NULL; } } @@ -1123,7 +1174,7 @@ expandCodeOntoStack(struct Decompressor * const decompP, static void lzwReadByteFresh(struct GetCodeState * const getCodeStateP, - struct Decompressor * const decompP, + Decompressor * const decompP, bool * const endOfImageP, unsigned char * const dataReadP, const char ** const errorP) { @@ -1143,7 +1194,7 @@ lzwReadByteFresh(struct GetCodeState * const getCodeStateP, assert(decompP->fresh); /* Entry requirement */ - decompP->fresh = FALSE; + decompP->fresh = false; do { getCode_get(getCodeStateP, decompP->ifP, decompP->codeSize, @@ -1152,11 +1203,11 @@ lzwReadByteFresh(struct GetCodeState * const getCodeStateP, if (!*errorP) { if (eof) - *endOfImageP = TRUE; + *endOfImageP = true; else if (code == decompP->endCode) { if (!zeroDataBlock) readThroughEod(decompP->ifP); - *endOfImageP = TRUE; + *endOfImageP = true; } else if (code >= decompP->cmapSize) { pm_asprintf(errorP, "Error in GIF image: invalid color code %u. " "Valid color values are: 0 - %u", @@ -1166,12 +1217,12 @@ lzwReadByteFresh(struct GetCodeState * const getCodeStateP, */ decompP->prevcode = decompP->firstcode = 0; - *endOfImageP = FALSE; + *endOfImageP = false; } else { /* valid code */ decompP->prevcode = code; - decompP->firstcode = decompP->table[code][1]; + decompP->firstcode = decompP->table[code].dataElement; *dataReadP = decompP->firstcode; - *endOfImageP = FALSE; + *endOfImageP = false; } } } @@ -1180,10 +1231,10 @@ lzwReadByteFresh(struct GetCodeState * const getCodeStateP, static void -lzwReadByte(struct Decompressor * const decompP, - unsigned char * const dataReadP, - bool * const endOfImageP, - const char ** const errorP) { +lzwReadByte(Decompressor * const decompP, + unsigned char * const dataReadP, + bool * const endOfImageP, + const char ** const errorP) { /*---------------------------------------------------------------------------- Return the next data element of the decompressed image. In the context of a GIF, a data element is the color table index of one pixel. @@ -1202,7 +1253,7 @@ lzwReadByte(struct Decompressor * const decompP, -----------------------------------------------------------------------------*/ if (!stackIsEmpty(&decompP->stack)) { *errorP = NULL; - *endOfImageP = FALSE; + *endOfImageP = false; *dataReadP = popStack(&decompP->stack); } else if (decompP->fresh) { lzwReadByteFresh(&getCodeState, decompP, endOfImageP, dataReadP, @@ -1225,10 +1276,10 @@ lzwReadByte(struct Decompressor * const decompP, if (code == decompP->endCode) { if (!zeroDataBlock) readThroughEod(decompP->ifP); - *endOfImageP = TRUE; + *endOfImageP = true; *errorP = NULL; } else { - *endOfImageP = FALSE; + *endOfImageP = false; expandCodeOntoStack(decompP, code, errorP); if (!*errorP) *dataReadP = popStack(&decompP->stack); @@ -1312,6 +1363,9 @@ renderRow(unsigned char * const cmapIndexRow, /*---------------------------------------------------------------------------- Convert one row of cmap indexes to PPM/PGM/PBM output. + The row is *xelrow, which is 'cols' columns wide and has pixels of format + 'format'. + Render the alpha row to *alphaFileP iff 'alphabits' is non-NULL. If 'haveTransColor' is false, render all white (i.e. the row is opaque). 'alphabits' is otherwise just a one-row buffer for us to use @@ -1407,12 +1461,12 @@ pnmFormat(bool const hasGray, static void -makePnmRow(struct Decompressor * const decompP, - unsigned int const cols, - unsigned int const rows, - bool const fillWithZero, - unsigned char * const cmapIndexRow, - const char ** const errorP) { +makePnmRow(Decompressor * const decompP, + unsigned int const cols, + unsigned int const rows, + bool const fillWithZero, + unsigned char *const cmapIndexRow, + const char ** const errorP) { bool fillingWithZero; unsigned int col; @@ -1456,15 +1510,15 @@ makePnmRow(struct Decompressor * const decompP, static void -convertRaster(struct Decompressor * const decompP, - unsigned int const cols, - unsigned int const rows, - GifColorMap const cmap, - bool const interlace, - FILE * const imageOutFileP, - FILE * const alphaFileP, - bool const hasGray, - bool const hasColor) { +convertRaster(Decompressor * const decompP, + unsigned int const cols, + unsigned int const rows, + GifColorMap const cmap, + bool const interlace, + FILE * const imageOutFileP, + FILE * const alphaFileP, + bool const hasGray, + bool const hasColor) { /*---------------------------------------------------------------------------- Read the raster from the GIF decompressor *decompP, and write it as a complete PNM stream (starting with the header) on *imageOutFileP and @@ -1493,9 +1547,9 @@ convertRaster(struct Decompressor * const decompP, MALLOCARRAY2(cmapIndexArray, interlace ? rows : 1 , cols); if (imageOutFileP) - pnm_writepnminit(imageOutFileP, cols, rows, GIFMAXVAL, format, FALSE); + pnm_writepnminit(imageOutFileP, cols, rows, GIFMAXVAL, format, false); if (alphaFileP) - pbm_writepbminit(alphaFileP, cols, rows, FALSE); + pbm_writepbminit(alphaFileP, cols, rows, false); xelrow = pnm_allocrow(cols); if (!xelrow) @@ -1559,13 +1613,13 @@ convertRaster(struct Decompressor * const decompP, static void -skipExtraneousData(struct Decompressor * const decompP) { +skipExtraneousData(Decompressor * const decompP) { unsigned char byteRead; bool endOfImage; const char * error; - endOfImage = FALSE; /* initial value */ + endOfImage = false; /* initial value */ lzwReadByte(decompP, &byteRead, &endOfImage, &error); @@ -1647,7 +1701,7 @@ readImageData(FILE * const ifP, bool const tolerateBadInput) { unsigned char lzwMinCodeSize; - struct Decompressor decomp; + Decompressor decomp; const char * error; readFile(ifP, &lzwMinCodeSize, sizeof(lzwMinCodeSize), &error); @@ -1788,7 +1842,7 @@ readExtensions(FILE* const ifP, next image or GIF stream terminator. If we encounter EOD (end of GIF stream) before we find an image - separator, we return *eodP == TRUE. Else *eodP == FALSE. + separator, we return *eodP == true. Else *eodP == false. If we hit end of file before an EOD marker, we fail. -----------------------------------------------------------------------------*/ @@ -1797,8 +1851,8 @@ readExtensions(FILE* const ifP, *errorP = NULL; /* initial value */ - eod = FALSE; - imageStart = FALSE; + eod = false; + imageStart = false; /* Read the image descriptor */ while (!imageStart && !eod && !*errorP) { @@ -1814,7 +1868,7 @@ readExtensions(FILE* const ifP, pm_strfree(error); } else { if (c == ';') { /* GIF terminator */ - eod = TRUE; + eod = true; } else if (c == '!') { /* Extension */ unsigned char functionCode; const char * error; @@ -1830,7 +1884,7 @@ readExtensions(FILE* const ifP, doExtension(ifP, functionCode, gif89P); } } else if (c == ',') - imageStart = TRUE; + imageStart = true; else pm_message("Encountered invalid character 0x%02x while " "seeking extension block, ignoring", (int)c); @@ -1961,7 +2015,7 @@ convertImage(FILE * const ifP, /*---------------------------------------------------------------------------- Read a single GIF image from the current position of file 'ifP'. - If 'skipIt' is TRUE, don't do anything else. Otherwise, write the + If 'skipIt' is true, don't do anything else. Otherwise, write the image to the current position of files *imageoutFileP and *alphafileP. If *alphafileP is NULL, though, don't write any alpha information. -----------------------------------------------------------------------------*/ @@ -2016,7 +2070,7 @@ disposeOfReadExtensionsError(const char * const error, pm_error("Error accessing Image %u of stream. %s", imageSeq, error); pm_strfree(error); - *eodP = TRUE; + *eodP = true; } } @@ -2037,7 +2091,7 @@ convertImages(FILE * const ifP, 'allImages' means Caller wants all the images in the stream. - 'requestedImageSeq' is meaningful only when 'allImages' is FALSE. It + 'requestedImageSeq' is meaningful only when 'allImages' is false. It is the sequence number of the one image Caller wants from the stream, with the first image being 0. @@ -2063,7 +2117,7 @@ convertImages(FILE * const ifP, readGifHeader(ifP, &gifScreen); - for (imageSeq = 0, eod = FALSE; + for (imageSeq = 0, eod = false; !eod && (allImages || imageSeq <= requestedImageSeq || drainStream); ++imageSeq) { @@ -2094,14 +2148,14 @@ convertImages(FILE * const ifP, int -main(int argc, char **argv) { +main(int argc, const char **argv) { struct CmdlineInfo cmdline; FILE * ifP; FILE * alphaFileP; FILE * imageOutFileP; - pnm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); verbose = cmdline.verbose; diff --git a/converter/other/jbig/libjbig/jbig.c b/converter/other/jbig/libjbig/jbig.c index 1ff867e8..0d29f770 100644 --- a/converter/other/jbig/libjbig/jbig.c +++ b/converter/other/jbig/libjbig/jbig.c @@ -29,8 +29,6 @@ #ifdef DEBUG #include <stdio.h> -#else -#define NDEBUG #endif #include <stdlib.h> diff --git a/converter/other/pamtopng.c b/converter/other/pamtopng.c index 528184b2..b7f779ca 100644 --- a/converter/other/pamtopng.c +++ b/converter/other/pamtopng.c @@ -41,6 +41,7 @@ #include <stdio.h> #include <stdlib.h> +#include <time.h> #include <png.h> /* setjmp.h needs to be included after png.h */ #include <setjmp.h> diff --git a/converter/other/pamtotiff.c b/converter/other/pamtotiff.c index 9270fd4c..32057e55 100644 --- a/converter/other/pamtotiff.c +++ b/converter/other/pamtotiff.c @@ -518,7 +518,7 @@ writeScanLines(struct pam * const pamP, The samples form pixel values according to the pixel format indicated by the TIFF photometric. E.g. if it is MINISWHITE, then a pixel is - one sample and a value of 0 for that sample means white. + grayscale, composed of one sample where a value of 0 means white. */ MALLOCARRAY(buf, bytesperrow); @@ -578,7 +578,7 @@ analyzeColorsInRgbInput(struct pam * const pamP, CmdlineInfo const cmdline, int const maxcolors, tupletable * const chvP, - unsigned int * const colorsP, + unsigned int * const colorCtP, bool * const grayscaleP) { /*---------------------------------------------------------------------------- Same as analyzeColors(), except assuming input image has R/G/B tuples. @@ -593,15 +593,15 @@ analyzeColorsInRgbInput(struct pam * const pamP, pm_message("computing colormap..."); chv = pnm_computetuplefreqtable2(pamP, NULL, maxcolors, pamP->maxval, - colorsP); + colorCtP); if (chv == NULL) { grayscale = FALSE; } else { unsigned int i; pm_message("%u color%s found", - *colorsP, *colorsP == 1 ? "" : "s"); + *colorCtP, *colorCtP == 1 ? "" : "s"); grayscale = TRUE; /* initial assumption */ - for (i = 0; i < *colorsP && grayscale; ++i) { + for (i = 0; i < *colorCtP && grayscale; ++i) { if (!pnm_rgbtupleisgray(chv[i]->tuple)) grayscale = FALSE; } @@ -635,21 +635,22 @@ analyzeColors(struct pam * const pamP, CmdlineInfo const cmdline, int const maxcolors, tupletable * const chvP, - unsigned int * const colorsP, + unsigned int * const colorCtP, bool * const grayscaleP) { /*---------------------------------------------------------------------------- Analyze the colors in the input image described by 'pamP', whose file is positioned to the raster. - If the colors, combined with command line options 'cmdline', indicate - a colormapped TIFF should be generated, return as *chvP the address - of a color map (in newly malloc'ed space). If a colormapped TIFF is - not indicated, return *chvP == NULL. - Return *grayscaleP == true iff the image should be stored as a grayscale image (which means the image is monochromatic and the user doesn't insist on color format). + If *grayscaleP is false and the colors, combined with command line options + 'cmdline', indicate a colormapped TIFF should be generated, return as *chvP + the address of a color map (in newly malloc'ed space) and the number of + colors in it as *colorCtP. If a colormapped color TIFF is not indicated, + return *chvP == NULL and nothing as *colorCtP. + Leave the file position undefined. -----------------------------------------------------------------------------*/ if (pamP->depth >= 3) @@ -657,7 +658,7 @@ analyzeColors(struct pam * const pamP, (tuple type RGB or RGB_ALPHA) */ analyzeColorsInRgbInput(pamP, cmdline, maxcolors, - chvP, colorsP, grayscaleP); + chvP, colorCtP, grayscaleP); else { *chvP = NULL; *grayscaleP = TRUE; @@ -667,9 +668,27 @@ analyzeColors(struct pam * const pamP, static void +reportTiffType(bool const grayscale, + bool const colormapped, + unsigned int const colorCt, + bool const verbose) { + + if (verbose) { + pm_message("Generating %s TIFF", grayscale ? "grayscale" : "color"); + + if (colormapped) + pm_message("TIFF will have palette of %u colors", colorCt); + else + pm_message("TIFF will be truecolor (24 bit RGB)"); + } +} + + + +static void computeRasterParm(struct pam * const pamP, tupletable const chv, - int const colors, + int const colorCt, bool const grayscale, int const compression, bool const minisblack, @@ -710,14 +729,14 @@ computeRasterParm(struct pam * const pamP, if (chv) { *samplesperpixelP = 1; /* Pixel is just the one index value */ *bitspersampleP = - colors <= 2 && indexsizeAllowed.b1 ? 1 : - colors <= 4 && indexsizeAllowed.b2 ? 2 : - colors <= 16 && indexsizeAllowed.b4 ? 4 : - colors <= 256 && indexsizeAllowed.b8 ? 8 : + colorCt <= 2 && indexsizeAllowed.b1 ? 1 : + colorCt <= 4 && indexsizeAllowed.b2 ? 2 : + colorCt <= 16 && indexsizeAllowed.b4 ? 4 : + colorCt <= 256 && indexsizeAllowed.b8 ? 8 : 0; if (*bitspersampleP == 0) pm_error("Your -indexbits option is insufficient for the " - "%d colors in this image.", colors); + "%d colors in this image.", colorCt); defaultPhotometric = PHOTOMETRIC_PALETTE; } else { @@ -737,11 +756,15 @@ computeRasterParm(struct pam * const pamP, } } - if (miniswhite) + if (miniswhite) { + if (!grayscale) + pm_error("Image is color, so -miniswhite is invalid"); *photometricP = PHOTOMETRIC_MINISWHITE; - else if (minisblack) + } else if (minisblack) { + if (!grayscale) + pm_error("Image is color, so -minisblack is invalid"); *photometricP = PHOTOMETRIC_MINISBLACK; - else + } else *photometricP = defaultPhotometric; { @@ -973,9 +996,9 @@ copyBufferToStdout(int const tmpfileFd) { static void -destroyTiffGenerator(WriteMethod const writeMethod, - TIFF * const tifP, - int const ofd) { +closeTiffGenerator(WriteMethod const writeMethod, + TIFF * const tifP, + int const ofd) { TIFFFlushData(tifP); @@ -995,7 +1018,7 @@ static void createTiffColorMap(struct pam * const pamP, unsigned int const bitspersample, tupletable const chv, - unsigned int const colors, + unsigned int const colorCt, unsigned short *** const tiffColorMapP) { unsigned int const colorMapSize = 1 << bitspersample; @@ -1010,7 +1033,7 @@ createTiffColorMap(struct pam * const pamP, for (i = 0; i < colorMapSize; ++i) { unsigned int plane; for (plane = 0; plane < pamP->depth; ++plane) { - if (i < colors) + if (i < colorCt) tiffColorMap[plane][i] = chv[i]->tuple[plane] * 65535L / pamP->maxval; else @@ -1137,7 +1160,7 @@ convertImage(FILE * const ifP, tuplehash cht; unsigned short ** tiffColorMap; /* malloc'ed */ struct pam pam; - unsigned int colors; + unsigned int colorCt; bool grayscale; unsigned short photometric; unsigned short samplesperpixel; @@ -1153,14 +1176,16 @@ convertImage(FILE * const ifP, pm_tell2(ifP, &rasterPos, sizeof(rasterPos)); - analyzeColors(&pam, cmdline, MAXCOLORS, &chv, &colors, &grayscale); + analyzeColors(&pam, cmdline, MAXCOLORS, &chv, &colorCt, &grayscale); + + reportTiffType(grayscale, chv != NULL, colorCt, cmdline.verbose); /* Go back to beginning of raster */ pm_seek2(ifP, &rasterPos, sizeof(rasterPos)); /* Figure out TIFF parameters. */ - computeRasterParm(&pam, chv, colors, grayscale, + computeRasterParm(&pam, chv, colorCt, grayscale, cmdline.compression, cmdline.minisblack, cmdline.miniswhite, cmdline.indexsizeAllowed, @@ -1173,10 +1198,10 @@ convertImage(FILE * const ifP, cht = NULL; tiffColorMap = NULL; } else { - createTiffColorMap(&pam, bitspersample, chv, colors, &tiffColorMap); + createTiffColorMap(&pam, bitspersample, chv, colorCt, &tiffColorMap); /* Convert color vector to color hash table, for fast lookup. */ - cht = pnm_computetupletablehash(&pam, chv, colors); + cht = pnm_computetupletablehash(&pam, chv, colorCt); pnm_freetupletable(&pam, chv); } @@ -1194,9 +1219,6 @@ convertImage(FILE * const ifP, - - - int main(int argc, const char *argv[]) { CmdlineInfo cmdline; @@ -1255,7 +1277,7 @@ main(int argc, const char *argv[]) { } } - destroyTiffGenerator(cmdline.writeMethod, tifP, ofd); + closeTiffGenerator(cmdline.writeMethod, tifP, ofd); pm_close(ifP); return 0; diff --git a/converter/other/pnmtops.c b/converter/other/pnmtops.c index c827f549..de0dfd8d 100644 --- a/converter/other/pnmtops.c +++ b/converter/other/pnmtops.c @@ -87,7 +87,7 @@ setSignals() { -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -209,7 +209,7 @@ validateCompDimension(unsigned int const value, static void parseCommandLine(int argc, const char ** argv, - struct cmdlineInfo * const cmdlineP) { + struct CmdlineInfo * const cmdlineP) { unsigned int imagewidthSpec, imageheightSpec; float imagewidth, imageheight; @@ -2035,7 +2035,7 @@ main(int argc, const char * argv[]) { FILE * ifP; const char * name; /* malloc'ed */ - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; pm_proginit(&argc, argv); diff --git a/converter/other/tifftopnm.c b/converter/other/tifftopnm.c index aabf9d09..e72aff5e 100644 --- a/converter/other/tifftopnm.c +++ b/converter/other/tifftopnm.c @@ -184,10 +184,10 @@ getBps(TIFF * const tif, unsigned short tiffBps; unsigned short bps; - int rc; + int fldPresent; - rc = TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &tiffBps); - bps = (rc == 0) ? 1 : tiffBps; + fldPresent = TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &tiffBps); + bps = fldPresent ? tiffBps : 1; if (bps < 1 || (bps > 8 && bps != 16 && bps != 32)) pm_error("This program can process Tiff images with only " @@ -219,26 +219,30 @@ struct tiffDirInfo { static void -tiffToImageDim(unsigned int const tiffCols, - unsigned int const tiffRows, +tiffToImageDim(unsigned int const tiffWidth, + unsigned int const tiffHeight, unsigned short const orientation, unsigned int * const imageColsP, unsigned int * const imageRowsP) { - +/*---------------------------------------------------------------------------- + Determine the image dimensions (as *imageColsP and *imageRowsP) from the + width, height, and orientation of the TIFF raster ('tiffWidth', + 'tiffHeight', and 'orientation', respectively. +-----------------------------------------------------------------------------*/ switch (orientation) { case ORIENTATION_TOPLEFT: case ORIENTATION_TOPRIGHT: case ORIENTATION_BOTRIGHT: case ORIENTATION_BOTLEFT: - *imageColsP = tiffCols; - *imageRowsP = tiffRows; + *imageColsP = tiffWidth; + *imageRowsP = tiffHeight; break; case ORIENTATION_LEFTTOP: case ORIENTATION_RIGHTTOP: case ORIENTATION_RIGHTBOT: case ORIENTATION_LEFTBOT: - *imageColsP = tiffRows; - *imageRowsP = tiffCols; + *imageColsP = tiffHeight; + *imageRowsP = tiffWidth; break; default: pm_error("Invalid value for orientation tag in TIFF directory: %u", @@ -257,28 +261,96 @@ getTiffDimensions(TIFF * const tiffP, dimensions of the internal raster matrix -- the dimensions of the actual visual image. -----------------------------------------------------------------------------*/ - int ok; + int fldPresent; unsigned int width, length; unsigned short tiffOrientation; unsigned short orientation; - int present; - ok = TIFFGetField(tiffP, TIFFTAG_IMAGEWIDTH, &width); - if (!ok) + fldPresent = TIFFGetField(tiffP, TIFFTAG_IMAGEWIDTH, &width); + if (!fldPresent) pm_error("Input Tiff file is invalid. It has no IMAGEWIDTH tag."); - ok = TIFFGetField(tiffP, TIFFTAG_IMAGELENGTH, &length); - if (!ok) + fldPresent = TIFFGetField(tiffP, TIFFTAG_IMAGELENGTH, &length); + if (!fldPresent) pm_error("Input Tiff file is invalid. It has no IMAGELENGTH tag."); - present = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); - orientation = present ? tiffOrientation : ORIENTATION_TOPLEFT; + fldPresent = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); + orientation = fldPresent ? tiffOrientation : ORIENTATION_TOPLEFT; tiffToImageDim(width, length, orientation, colsP, rowsP); } +static unsigned short +planarConfigFmTiff(TIFF * const tiffP) { + + int fldPresent; + unsigned short retval; + + fldPresent = TIFFGetField(tiffP, TIFFTAG_PLANARCONFIG, &retval); + + if (!fldPresent) + pm_error("PLANARCONFIG tag is not in Tiff file, though it " + "has more than one sample per pixel. " + "TIFFGetField() of it failed. This means the input " + "is not valid Tiff."); + + return retval; +} + + + +static void +validatePlanarConfig(unsigned short const planarconfig, + unsigned short const photomet) { + + switch (planarconfig) { + case PLANARCONFIG_CONTIG: + break; + case PLANARCONFIG_SEPARATE: + if (photomet != PHOTOMETRIC_RGB && + photomet != PHOTOMETRIC_SEPARATED) + pm_error("This program can handle separate planes only " + "with RGB (PHOTOMETRIC tag = %u) or SEPARATED " + "(PHOTOMETRIC tag = %u) data. The input Tiff file " + "has PHOTOMETRIC tag = %hu.", + PHOTOMETRIC_RGB, PHOTOMETRIC_SEPARATED, + photomet); + break; + default: + pm_error("Unrecognized PLANARCONFIG tag value in Tiff input: %u", + planarconfig); + } +} + + + +static unsigned short +orientationFmTiff(TIFF * const tiffP) { + + unsigned short tiffOrientation; + int fldPresent; + + fldPresent = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); + + return fldPresent ? tiffOrientation : ORIENTATION_TOPLEFT; +} + + + +static void +dumpHeader(const struct tiffDirInfo * const headerP) { + + pm_message("%ux%ux%u raster matrix, oriented %u", + headerP->width, headerP->height, + headerP->bps * headerP->spp, headerP->orientation); + pm_message("%hu bits/sample, %hu samples/pixel", + headerP->bps, headerP->spp); +} + + + static void readDirectory(TIFF * const tiffP, bool const headerdump, @@ -287,7 +359,7 @@ readDirectory(TIFF * const tiffP, Read various values of TIFF tags from the TIFF directory, and default them if not in there and make guesses where values are invalid. Exit program with error message if required tags aren't - there or values are inconsistent or beyond our capabilities. if + there or values are inconsistent or beyond our capabilities. If 'headerdump' is true, issue informational messages about what we find. @@ -295,7 +367,7 @@ readDirectory(TIFF * const tiffP, input file contains invalid values). We generally return those invalid values to our caller. -----------------------------------------------------------------------------*/ - int rc; + int fldPresent; unsigned short tiffSpp; if (headerdump) @@ -303,65 +375,35 @@ readDirectory(TIFF * const tiffP, getBps(tiffP, &headerP->bps); - rc = TIFFGetFieldDefaulted(tiffP, TIFFTAG_FILLORDER, &headerP->fillorder); - rc = TIFFGetField(tiffP, TIFFTAG_SAMPLESPERPIXEL, &tiffSpp); - headerP->spp = (rc == 0) ? 1 : tiffSpp; + fldPresent = + TIFFGetFieldDefaulted(tiffP, TIFFTAG_FILLORDER, &headerP->fillorder); + fldPresent = TIFFGetField(tiffP, TIFFTAG_SAMPLESPERPIXEL, &tiffSpp); + headerP->spp = fldPresent ? tiffSpp: 1; - rc = TIFFGetField(tiffP, TIFFTAG_PHOTOMETRIC, &headerP->photomet); - if (rc == 0) + fldPresent = TIFFGetField(tiffP, TIFFTAG_PHOTOMETRIC, &headerP->photomet); + if (!fldPresent) pm_error("PHOTOMETRIC tag is not in Tiff file. " "TIFFGetField() of it failed.\n" "This means the input is not valid Tiff."); - if (headerP->spp > 1) { - rc = TIFFGetField(tiffP, TIFFTAG_PLANARCONFIG, &headerP->planarconfig); - if (rc == 0) - pm_error("PLANARCONFIG tag is not in Tiff file, though it " - "has more than one sample per pixel. " - "TIFFGetField() of it failed. This means the input " - "is not valid Tiff."); - } else + if (headerP->spp > 1) + headerP->planarconfig = planarConfigFmTiff(tiffP); + else headerP->planarconfig = PLANARCONFIG_CONTIG; - switch (headerP->planarconfig) { - case PLANARCONFIG_CONTIG: - break; - case PLANARCONFIG_SEPARATE: - if (headerP->photomet != PHOTOMETRIC_RGB && - headerP->photomet != PHOTOMETRIC_SEPARATED) - pm_error("This program can handle separate planes only " - "with RGB (PHOTOMETRIC tag = %u) or SEPARATED " - "(PHOTOMETRIC tag = %u) data. The input Tiff file " - "has PHOTOMETRIC tag = %hu.", - PHOTOMETRIC_RGB, PHOTOMETRIC_SEPARATED, - headerP->photomet); - break; - default: - pm_error("Unrecognized PLANARCONFIG tag value in Tiff input: %u.\n", - headerP->planarconfig); - } + validatePlanarConfig(headerP->planarconfig, headerP->photomet); - rc = TIFFGetField(tiffP, TIFFTAG_IMAGEWIDTH, &headerP->width); - if (rc == 0) + fldPresent = TIFFGetField(tiffP, TIFFTAG_IMAGEWIDTH, &headerP->width); + if (!fldPresent) pm_error("Input Tiff file is invalid. It has no IMAGEWIDTH tag."); - rc = TIFFGetField(tiffP, TIFFTAG_IMAGELENGTH, &headerP->height); - if (rc == 0) + fldPresent = TIFFGetField(tiffP, TIFFTAG_IMAGELENGTH, &headerP->height); + if (!fldPresent) pm_error("Input Tiff file is invalid. It has no IMAGELENGTH tag."); - { - unsigned short tiffOrientation; - int present; - present = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); - headerP->orientation = - present ? tiffOrientation : ORIENTATION_TOPLEFT; - } - if (headerdump) { - pm_message("%ux%ux%u raster matrix, oriented %u", - headerP->width, headerP->height, - headerP->bps * headerP->spp, headerP->orientation); - pm_message("%hu bits/sample, %hu samples/pixel", - headerP->bps, headerP->spp); - } + headerP->orientation = orientationFmTiff(tiffP); + + if (headerdump) + dumpHeader(headerP); } @@ -535,7 +577,7 @@ computeFillorder(unsigned short const fillorderTag, static void -analyzeImageType(TIFF * const tif, +analyzeImageType(TIFF * const tiffP, unsigned short const bps, unsigned short const spp, unsigned short const photomet, @@ -544,129 +586,147 @@ analyzeImageType(TIFF * const tif, xel * const colormap, bool const headerdump, struct CmdlineInfo const cmdline) { +/*---------------------------------------------------------------------------- + Determine from the TIFF header in *tif certain properties of the image + as well as the proper format of PNM image for the conversion. - bool grayscale; - - /* How come we don't deal with the photometric for the monochrome - case (make sure it's one we know)? -Bryan 00.03.04 - */ - switch (photomet) { - case PHOTOMETRIC_MINISBLACK: - case PHOTOMETRIC_MINISWHITE: - if (spp != 1) - pm_error("This grayscale image has %d samples per pixel. " - "We understand only 1.", spp); - grayscale = TRUE; - *maxvalP = pm_bitstomaxval(MIN(bps,16)); - if (headerdump) - pm_message("grayscale image, (min=%s) output maxval %u ", - photomet == PHOTOMETRIC_MINISBLACK ? - "black" : "white", - *maxvalP - ); - break; + *formatP and *maxvalP are the basic PNM parameters. +-----------------------------------------------------------------------------*/ + switch (photomet) { + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_MINISWHITE: + if (spp != 1) + pm_error("This grayscale image has %d samples per pixel. " + "We understand only 1.", spp); + + *formatP = bps == 1 ? PBM_TYPE : PGM_TYPE; + + *maxvalP = pm_bitstomaxval(MIN(bps, 16)); + + if (headerdump) + pm_message("grayscale image, (min=%s) output maxval %u ", + photomet == PHOTOMETRIC_MINISBLACK ? + "black" : "white", + *maxvalP + ); + break; - case PHOTOMETRIC_PALETTE: { - int i; - int numcolors; - unsigned short* redcolormap; - unsigned short* greencolormap; - unsigned short* bluecolormap; - - if (headerdump) - pm_message("colormapped"); - - if (spp != 1) - pm_error("This paletted image has %d samples per pixel. " - "We understand only 1.", spp); - - if (!TIFFGetField(tif, TIFFTAG_COLORMAP, - &redcolormap, &greencolormap, &bluecolormap)) - pm_error("error getting colormaps"); - - numcolors = 1 << bps; - if (numcolors > MAXCOLORS) - pm_error("too many colors"); - *maxvalP = PNM_MAXMAXVAL; - grayscale = FALSE; - for (i = 0; i < numcolors; ++i) { - xelval r, g, b; - r = (long) redcolormap[i] * PNM_MAXMAXVAL / 65535L; - g = (long) greencolormap[i] * PNM_MAXMAXVAL / 65535L; - b = (long) bluecolormap[i] * PNM_MAXMAXVAL / 65535L; - PPM_ASSIGN(colormap[i], r, g, b); - } + case PHOTOMETRIC_PALETTE: { + int fldPresent; + int i; + int numcolors; + unsigned short* redcolormap; + unsigned short* greencolormap; + unsigned short* bluecolormap; + + if (headerdump) + pm_message("colormapped"); + + if (spp != 1) + pm_error("This paletted image has %d samples per pixel. " + "We understand only 1.", spp); + + fldPresent = TIFFGetField( + tiffP, TIFFTAG_COLORMAP, + &redcolormap, &greencolormap, &bluecolormap); + + if (!fldPresent) + pm_error("error getting colormaps"); + + numcolors = 1 << bps; + if (numcolors > MAXCOLORS) + pm_error("too many colors"); + + *formatP = PPM_TYPE; + + *maxvalP = PNM_MAXMAXVAL; + + for (i = 0; i < numcolors; ++i) { + xelval r, g, b; + r = (long) redcolormap[i] * PNM_MAXMAXVAL / 65535L; + g = (long) greencolormap[i] * PNM_MAXMAXVAL / 65535L; + b = (long) bluecolormap[i] * PNM_MAXMAXVAL / 65535L; + PPM_ASSIGN(colormap[i], r, g, b); } + } break; - case PHOTOMETRIC_SEPARATED: { - unsigned short inkset; - - if (headerdump) - pm_message("color separation"); - if (TIFFGetField(tif, TIFFTAG_INKNAMES, &inkset) == 1 - && inkset != INKSET_CMYK) - if (inkset != INKSET_CMYK) - pm_error("This color separation file uses an inkset (%d) " - "we can't handle. We handle only CMYK.", inkset); - if (spp != 4) - pm_error("This CMYK color separation file is %d samples per " - "pixel. " - "We need 4 samples, though: C, M, Y, and K. ", - spp); - grayscale = FALSE; - *maxvalP = (1 << bps) - 1; - } + case PHOTOMETRIC_SEPARATED: { + unsigned short inkset; + int fldPresent; + + if (headerdump) + pm_message("color separation"); + + fldPresent = TIFFGetField(tiffP, TIFFTAG_INKNAMES, &inkset); + if (fldPresent && inkset != INKSET_CMYK) + pm_error("This color separation file uses an inkset (%d) " + "we can't handle. We handle only CMYK.", inkset); + if (spp != 4) + pm_error("This CMYK color separation file is %d samples per " + "pixel. " + "We need 4 samples, though: C, M, Y, and K. ", + spp); + + *formatP = PPM_TYPE; + + *maxvalP = (1 << bps) - 1; + } break; - case PHOTOMETRIC_RGB: - if (headerdump) - pm_message("RGB truecolor"); - grayscale = FALSE; + case PHOTOMETRIC_RGB: + if (headerdump) + pm_message("RGB truecolor"); - if (spp != 3 && spp != 4) - pm_error("This RGB image has %d samples per pixel. " - "We understand only 3 or 4.", spp); + if (spp != 3 && spp != 4) + pm_error("This RGB image has %d samples per pixel. " + "We understand only 3 or 4.", spp); - *maxvalP = (1 << bps) - 1; - break; + *formatP = PPM_TYPE; + + *maxvalP = (1 << bps) - 1; + break; - case PHOTOMETRIC_MASK: - pm_error("don't know how to handle PHOTOMETRIC_MASK"); + case PHOTOMETRIC_MASK: + pm_error("don't know how to handle PHOTOMETRIC_MASK"); - case PHOTOMETRIC_DEPTH: - pm_error("don't know how to handle PHOTOMETRIC_DEPTH"); + case PHOTOMETRIC_DEPTH: + pm_error("don't know how to handle PHOTOMETRIC_DEPTH"); - case PHOTOMETRIC_YCBCR: - pm_error("don't know how to handle PHOTOMETRIC_YCBCR"); + case PHOTOMETRIC_YCBCR: + pm_error("don't know how to handle PHOTOMETRIC_YCBCR"); - case PHOTOMETRIC_CIELAB: - pm_error("don't know how to handle PHOTOMETRIC_CIELAB"); + case PHOTOMETRIC_CIELAB: + pm_error("don't know how to handle PHOTOMETRIC_CIELAB"); - case PHOTOMETRIC_LOGL: - pm_error("don't know how to handle PHOTOMETRIC_LOGL"); + case PHOTOMETRIC_LOGL: + pm_error("don't know how to handle PHOTOMETRIC_LOGL"); - case PHOTOMETRIC_LOGLUV: - pm_error("don't know how to handle PHOTOMETRIC_LOGLUV"); + case PHOTOMETRIC_LOGLUV: + pm_error("don't know how to handle PHOTOMETRIC_LOGLUV"); - default: - pm_error("unknown photometric: %d", photomet); - } + default: + pm_error("unknown photometric: %d", photomet); + } if (*maxvalP > PNM_OVERALLMAXVAL) - pm_error("bits/sample (%d) in the input image is too large.", - bps); - if (grayscale) { - if (*maxvalP == 1) { - *formatP = PBM_TYPE; - pm_message("writing PBM file"); - } else { - *formatP = PGM_TYPE; - pm_message("writing PGM file"); - } - } else { - *formatP = PPM_TYPE; - pm_message("writing PPM file"); + pm_error("bits/sample (%u) in the input image is too large.", bps); +} + + + +static void +reportOutputFormat(int const format) { + + const char * formatDesc; + + switch (format) { + case PBM_TYPE: formatDesc = "PBM"; break; + case PGM_TYPE: formatDesc = "PGM"; break; + case PPM_TYPE: formatDesc = "PPM"; break; + default: assert(false); } + + pm_message("writing %s file", formatDesc); } @@ -1374,9 +1434,9 @@ warnBrokenTiffLibrary(TIFF * const tiffP) { */ unsigned short tiffOrientation; - int present; - present = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); - if (present) { + int fldPresent; + fldPresent = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); + if (fldPresent) { switch (tiffOrientation) { case ORIENTATION_LEFTTOP: case ORIENTATION_RIGHTTOP: @@ -1448,16 +1508,47 @@ enum convertDisp {CONV_DONE, CONV_FAILED, CONV_NOTATTEMPTED}; + +static void +convertRasterIntoProvidedMemory(pnmOut * const pnmOutP, + unsigned int const cols, + unsigned int const rows, + xelval const maxval, + TIFF * const tif, + bool const verbose, + uint32 * const raster, + enum convertDisp * const statusP) { + + int const stopOnErrorFalse = false; + + TIFFRGBAImage img; + char emsg[1024]; + int ok; + + ok = TIFFRGBAImageBegin(&img, tif, stopOnErrorFalse, emsg); + if (!ok) { + pm_message("%s", emsg); + *statusP = CONV_FAILED; + } else { + int ok; + ok = TIFFRGBAImageGet(&img, raster, cols, rows); + TIFFRGBAImageEnd(&img) ; + if (!ok) { + pm_message("%s", emsg); + *statusP = CONV_FAILED; + } else { + *statusP = CONV_DONE; + convertTiffRaster(raster, cols, rows, maxval, pnmOutP); + } + } +} + + + static void convertRasterInMemory(pnmOut * const pnmOutP, xelval const maxval, TIFF * const tif, - unsigned short const photomet, - unsigned short const planarconfig, - unsigned short const bps, - unsigned short const spp, - unsigned short const fillorder, - xel const colormap[], bool const verbose, enum convertDisp * const statusP) { /*---------------------------------------------------------------------------- @@ -1477,64 +1568,49 @@ convertRasterInMemory(pnmOut * const pnmOutP, programs, we simply abort the program if we are unable to allocate memory for other things. -----------------------------------------------------------------------------*/ - unsigned int cols, rows; /* Dimensions of output image */ + char emsg[1024]; + int ok; if (verbose) pm_message("Converting in memory ..."); warnBrokenTiffLibrary(tif); - getTiffDimensions(tif, &cols, &rows); - - if (rows == 0 || cols == 0) - *statusP = CONV_DONE; - else { - char emsg[1024]; - int ok; - ok = TIFFRGBAImageOK(tif, emsg); - if (!ok) { - pm_message("%s", emsg); - *statusP = CONV_UNABLE; - } else { - uint32 * raster; + ok = TIFFRGBAImageOK(tif, emsg); + if (!ok) { + pm_message("%s", emsg); + *statusP = CONV_UNABLE; + } else { + unsigned int cols, rows; /* Dimensions of output image */ + getTiffDimensions(tif, &cols, &rows); - /* Note that TIFFRGBAImageGet() converts any bits per sample - to 8. Maxval of the raster it returns is always 255. - */ + if (rows == 0 || cols == 0) + *statusP = CONV_DONE; + else { if (cols > UINT_MAX/rows) { pm_message("%u rows of %u columns is too large to compute", rows, cols); *statusP = CONV_OOM; - return; - } - - MALLOCARRAY(raster, cols * rows); - if (raster == NULL) { - pm_message("Unable to allocate space for a raster of %u " - "pixels.", cols * rows); - *statusP = CONV_OOM; } else { - int const stopOnErrorFalse = FALSE; - TIFFRGBAImage img; - int ok; - - ok = TIFFRGBAImageBegin(&img, tif, stopOnErrorFalse, emsg); - if (!ok) { - pm_message("%s", emsg); - *statusP = CONV_FAILED; + unsigned int const pixelCt = rows * cols; + + uint32 * raster; + + /* Note that TIFFRGBAImageGet() converts any bits per sample + to 8. Maxval of the raster it returns is always 255. + */ + MALLOCARRAY(raster, pixelCt); + if (raster == NULL) { + pm_message("Unable to allocate space for a raster of %u " + "pixels.", pixelCt); + *statusP = CONV_OOM; } else { - int ok; - ok = TIFFRGBAImageGet(&img, raster, cols, rows); - TIFFRGBAImageEnd(&img) ; - if (!ok) { - pm_message("%s", emsg); - *statusP = CONV_FAILED; - } else { - *statusP = CONV_DONE; - convertTiffRaster(raster, cols, rows, maxval, pnmOutP); - } - } - free(raster); + convertRasterIntoProvidedMemory( + pnmOutP, cols, rows, maxval, tif, verbose, + raster, statusP); + + free(raster); + } } } } @@ -1559,11 +1635,7 @@ convertRaster(pnmOut * const pnmOutP, if (byrow || !flipOk) status = CONV_NOTATTEMPTED; else { - convertRasterInMemory( - pnmOutP, maxval, - tifP, tiffDir.photomet, tiffDir.planarconfig, - tiffDir.bps, tiffDir.spp, fillorder, - colormap, verbose, &status); + convertRasterInMemory(pnmOutP, maxval, tifP, verbose, &status); } if (status == CONV_DONE) { if (tiffDir.bps > 8) @@ -1612,6 +1684,8 @@ convertImage(TIFF * const tifP, analyzeImageType(tifP, tiffDir.bps, tiffDir.spp, tiffDir.photomet, &maxval, &format, colormap, cmdline.headerdump, cmdline); + reportOutputFormat(format); + pnmOut_init(imageoutFileP, alphaFileP, tiffDir.width, tiffDir.height, tiffDir.orientation, maxval, format, maxval, cmdline.byrow, cmdline.orientraw, |