diff options
Diffstat (limited to 'converter/ppm/ppmtobmp.c')
-rw-r--r-- | converter/ppm/ppmtobmp.c | 509 |
1 files changed, 329 insertions, 180 deletions
diff --git a/converter/ppm/ppmtobmp.c b/converter/ppm/ppmtobmp.c index b9ac063e..0e7a8328 100644 --- a/converter/ppm/ppmtobmp.c +++ b/converter/ppm/ppmtobmp.c @@ -18,15 +18,23 @@ #include <assert.h> #include <string.h> -#include "bmp.h" -#include "ppm.h" + +#include "mallocvar.h" #include "shhopt.h" +#include "bmp.h" #include "bitio.h" +#include "ppm.h" #define MAXCOLORS 256 enum colortype {TRUECOLOR, PALETTE}; +struct rgb { + unsigned char red; + unsigned char grn; + unsigned char blu; +}; + typedef struct { /*---------------------------------------------------------------------------- A color map for a BMP file. @@ -34,13 +42,13 @@ typedef struct { unsigned int count; /* Number of colors in the map. The first 'count' elements of these arrays are defined; all others are not. + + At most MAXCOLORS. */ colorhash_table cht; - /* Indices in the following arrays are the same as in 'cht', above. */ - unsigned char red[MAXCOLORS]; - unsigned char grn[MAXCOLORS]; - unsigned char blu[MAXCOLORS]; + /* Indices in the following array are the same as in 'cht', above. */ + struct rgb bmpMap[MAXCOLORS]; } colorMap; @@ -54,7 +62,7 @@ freeColorMap(const colorMap * const colorMapP) { -static struct cmdline_info { +struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -62,63 +70,71 @@ static struct cmdline_info { int class; /* C_WIN or C_OS2 */ unsigned int bppSpec; unsigned int bpp; -} cmdline; + const char * mapfile; +}; static void -parse_command_line(int argc, char ** argv, - struct cmdline_info *cmdline_p) { +parseCommandLine(int argc, const char ** argv, + struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that many of the strings that this function returns in the *cmdline_p structure are actually in the supplied argv array. And sometimes, one of these strings is actually just a suffix of an entry in argv! -----------------------------------------------------------------------------*/ - optEntry *option_def = malloc(100*sizeof(optEntry)); + optEntry * option_def; /* Instructions to OptParseOptions3 on how to parse our options. */ optStruct3 opt; - unsigned int windowsSpec, os2Spec; + unsigned int windowsSpec, os2Spec, mapfileSpec; unsigned int option_def_index; + + MALLOCARRAY(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3('w', "windows", OPT_FLAG, NULL, &windowsSpec, 0); OPTENT3('o', "os2", OPT_FLAG, NULL, &os2Spec, 0); - OPTENT3(0, "bpp", OPT_UINT, &cmdline_p->bpp, - &cmdline_p->bppSpec, 0); + OPTENT3(0, "bpp", OPT_UINT, &cmdlineP->bpp, + &cmdlineP->bppSpec, 0); + OPTENT3(0, "mapfile", OPT_STRING, &cmdlineP->mapfile, + &mapfileSpec, 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 */ - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); if (windowsSpec && os2Spec) pm_error("Can't specify both -windows and -os2 options."); else if (windowsSpec) - cmdline_p->class = C_WIN; + cmdlineP->class = C_WIN; else if (os2Spec) - cmdline_p->class = C_OS2; + cmdlineP->class = C_OS2; else - cmdline_p->class = C_WIN; + cmdlineP->class = C_WIN; - if (cmdline_p->bppSpec) { - if (cmdline_p->bpp != 1 && cmdline_p->bpp != 4 && - cmdline_p->bpp != 8 && cmdline_p->bpp != 24) - pm_error("Invalid -bpp value specified: %u. The only values valid\n" + if (cmdlineP->bppSpec) { + if (cmdlineP->bpp != 1 && cmdlineP->bpp != 4 && + cmdlineP->bpp != 8 && cmdlineP->bpp != 24) + pm_error("Invalid -bpp value specified: %u. The only values valid " "in the BMP format are 1, 4, 8, and 24 bits per pixel", - cmdline_p->bpp); + cmdlineP->bpp); } + if (!mapfileSpec) + cmdlineP->mapfile = NULL; + if (argc - 1 == 0) - cmdline_p->input_filename = strdup("-"); /* he wants stdin */ + cmdlineP->input_filename = strdup("-"); /* he wants stdin */ else if (argc - 1 == 1) - cmdline_p->input_filename = strdup(argv[1]); + cmdlineP->input_filename = strdup(argv[1]); else - pm_error("Too many arguments. The only argument accepted\n" + pm_error("Too many arguments. The only argument accepted " "is the input file specificaton"); } @@ -243,7 +259,7 @@ BMPwriteinfoheader(FILE * const fp, static int -BMPwritergb(FILE * const fp, +BMPwriteRgb(FILE * const fp, int const class, pixval const R, pixval const G, @@ -264,7 +280,7 @@ BMPwritergb(FILE * const fp, PutByte(fp, R); return 3; default: - pm_error(er_internal, "BMPwritergb"); + pm_error(er_internal, "BMPwriteRgb"); } return -1; } @@ -272,101 +288,118 @@ BMPwritergb(FILE * const fp, static int -BMPwritecolormap(FILE * const ifP, +BMPwriteColormap(FILE * const ifP, int const class, int const bpp, const colorMap * const colorMapP) { /*---------------------------------------------------------------------------- Return the number of bytes written, or -1 on error. -----------------------------------------------------------------------------*/ - long const ncolors = (1 << bpp); + unsigned int const ncolors = (1 << bpp); - unsigned int nbyte; - unsigned int i; + unsigned int nbyte; + unsigned int i; - nbyte = 0; - for (i = 0; i < colorMapP->count; ++i) - nbyte += BMPwritergb(ifP, class, - colorMapP->red[i], - colorMapP->grn[i], - colorMapP->blu[i]); + assert(ncolors <= MAXCOLORS); + assert(ncolors <= ARRAY_SIZE(colorMapP->bmpMap)); + nbyte = 0; + for (i = 0; i < colorMapP->count; ++i) { + const struct rgb * const mapEntryP = &colorMapP->bmpMap[i]; + nbyte += BMPwriteRgb(ifP, class, + mapEntryP->red, mapEntryP->grn, mapEntryP->blu); + } for (; i < ncolors; ++i) - nbyte += BMPwritergb(ifP, class, 0, 0, 0); + nbyte += BMPwriteRgb(ifP, class, 0, 0, 0); return nbyte; } -static int -BMPwriterow_palette(FILE * const fp, +static void +lookupColor(colorhash_table const cht, + pixel const color, + unsigned int * const colorIndexP) { + + int rc; + + rc = ppm_lookupcolor(cht, &color); + + if (rc < 0) + pm_error("Color (%u,%u,%u) is not in the provided palette", + PPM_GETR(color), PPM_GETG(color), PPM_GETB(color)); + else + *colorIndexP = rc; +} + + + +static void +bmpWriteRow_palette(FILE * const fp, const pixel * const row, - unsigned long const cx, + unsigned int const cols, unsigned short const bpp, - colorhash_table const cht) { + colorhash_table const cht, + unsigned int * const nBytesP) { /*---------------------------------------------------------------------------- - Return the number of bytes written, or -1 on error. + Write a row to the raster in paletted format. + + Return the number of bytes written as *nBytesP. -----------------------------------------------------------------------------*/ - BITSTREAM b; - int retval; + BITSTREAM b; b = pm_bitinit(fp, "w"); if (b == NULL) - retval = -1; + pm_error("Failed to initialize output file for output"); else { + int rc; unsigned int nbyte; - unsigned int x; - bool error; + unsigned int col; nbyte = 0; /* initial value */ - error = FALSE; /* initial value */ - for (x = 0; x < cx && !error; ++x) { + for (col = 0; col < cols; ++col) { + unsigned int colorIndex; int rc; - rc = pm_bitwrite(b, bpp, ppm_lookupcolor(cht, &row[x])); + + lookupColor(cht, row[col], &colorIndex); + + rc = pm_bitwrite(b, bpp, colorIndex); if (rc == -1) - error = TRUE; + pm_error("Failed in writing a pixel " + "to the raster in the output file"); else nbyte += rc; } - if (error) - retval = -1; - else { - int rc; - rc = pm_bitfini(b); - if (rc == -1) - retval = -1; - else { - nbyte += rc; + rc = pm_bitfini(b); + + nbyte += rc; - /* Make sure we write a multiple of 4 bytes. */ - while (nbyte % 4 != 0) { - PutByte(fp, 0); - ++nbyte; - } - retval = nbyte; - } + /* Make sure we write a multiple of 4 bytes. */ + while (nbyte % 4 != 0) { + PutByte(fp, 0); + ++nbyte; } + *nBytesP = nbyte; } - return retval; } -static int -BMPwriterow_truecolor(FILE * const fp, - const pixel * const row, - unsigned long const cols, - pixval const maxval) { +static void +bmpWriteRow_truecolor(FILE * const fp, + const pixel * const row, + unsigned long const cols, + pixval const maxval, + unsigned int * const nBytesP) { /*---------------------------------------------------------------------------- Write a row of a truecolor BMP image to the file 'fp'. The row is 'row', which is 'cols' columns long. - Return the number of bytes written. - On error, issue error message and exit program. + Return the number of bytes written as *nBytesP. -----------------------------------------------------------------------------*/ /* This works only for 24 bits per pixel. To implement this for the general case (which is only hypothetical -- this program doesn't @@ -380,7 +413,7 @@ BMPwriterow_truecolor(FILE * const fp, int col; nbyte = 0; /* initial value */ - for (col = 0; col < cols; col++) { + for (col = 0; col < cols; ++col) { /* We scale to the BMP maxval, which is always 255. */ PutByte(fp, PPM_GETB(row[col]) * 255 / maxval); PutByte(fp, PPM_GETG(row[col]) * 255 / maxval); @@ -393,18 +426,18 @@ BMPwriterow_truecolor(FILE * const fp, */ while (nbyte % 4) { PutByte(fp, 0); - nbyte++; + ++nbyte; } - return nbyte; + *nBytesP = nbyte; } static int BMPwritebits(FILE * const fp, - unsigned long const cx, - unsigned long const cy, + unsigned long const cols, + unsigned long const rows, enum colortype const colortype, unsigned short const cBitCount, const pixel ** const pixels, @@ -413,29 +446,29 @@ BMPwritebits(FILE * const fp, /*---------------------------------------------------------------------------- Return the number of bytes written, or -1 on error. -----------------------------------------------------------------------------*/ - int nbyte; - long y; + unsigned int nbyte; + int row; if (cBitCount > 24) - pm_error("cannot handle cBitCount: %d", cBitCount); + pm_error("cannot handle cBitCount: %hu", cBitCount); nbyte = 0; /* initial value */ /* The picture is stored bottom line first, top line last */ - for (y = cy - 1; y >= 0; --y) { - int rc; + for (row = rows - 1; row >= 0; --row) { + unsigned int nBytesThisRow; + if (colortype == PALETTE) - rc = BMPwriterow_palette(fp, pixels[y], cx, - cBitCount, cht); + bmpWriteRow_palette(fp, pixels[row], cols, + cBitCount, cht, &nBytesThisRow); else - rc = BMPwriterow_truecolor(fp, pixels[y], cx, maxval); + bmpWriteRow_truecolor(fp, pixels[row], cols, maxval, + &nBytesThisRow); - if (rc == -1) - pm_error("couldn't write row %ld", y); - if (rc % 4 != 0) - pm_error("row had bad number of bytes: %d", rc); - nbyte += rc; + if (nBytesThisRow % 4 != 0) + pm_error("row had bad number of bytes: %u", nBytesThisRow); + nbyte += nBytesThisRow; } return nbyte; @@ -444,10 +477,10 @@ BMPwritebits(FILE * const fp, static void -BMPEncode(FILE * const ifP, +bmpEncode(FILE * const ifP, int const class, enum colortype const colortype, - int const bpp, + unsigned int const bpp, int const x, int const y, const pixel ** const pixels, @@ -459,25 +492,25 @@ BMPEncode(FILE * const ifP, unsigned long nbyte; if (colortype == PALETTE) - pm_message("Writing %d bits per pixel with a color palette", bpp); + pm_message("Writing %u bits per pixel with a color palette", bpp); else - pm_message("Writing %d bits per pixel truecolor (no palette)", bpp); + pm_message("Writing %u bits per pixel truecolor (no palette)", bpp); nbyte = 0; /* initial value */ nbyte += BMPwritefileheader(ifP, class, bpp, x, y); nbyte += BMPwriteinfoheader(ifP, class, bpp, x, y); if (colortype == PALETTE) - nbyte += BMPwritecolormap(ifP, class, bpp, colorMapP); + nbyte += BMPwriteColormap(ifP, class, bpp, colorMapP); if (nbyte != (BMPlenfileheader(class) + BMPleninfoheader(class) + BMPlencolormap(class, bpp, -1))) - pm_error(er_internal, "BMPEncode 1"); + pm_error(er_internal, "BmpEncode 1"); nbyte += BMPwritebits(ifP, x, y, colortype, bpp, pixels, maxval, colorMapP->cht); if (nbyte != BMPlenfile(class, bpp, -1, x, y)) - pm_error(er_internal, "BMPEncode 2"); + pm_error(er_internal, "BmpEncode 2"); } @@ -487,18 +520,18 @@ makeBilevelColorMap(colorMap * const colorMapP) { colorMapP->count = 2; colorMapP->cht = NULL; - colorMapP->red[0] = 0; - colorMapP->grn[0] = 0; - colorMapP->blu[0] = 0; - colorMapP->red[1] = 255; - colorMapP->grn[1] = 255; - colorMapP->blu[1] = 255; + colorMapP->bmpMap[0].red = 0; + colorMapP->bmpMap[0].grn = 0; + colorMapP->bmpMap[0].blu = 0; + colorMapP->bmpMap[1].red = 255; + colorMapP->bmpMap[1].grn = 255; + colorMapP->bmpMap[1].blu = 255; } static void -BMPEncodePBM(FILE * const ifP, +bmpEncodePbm(FILE * const ifP, int const class, int const cols, int const rows, @@ -508,7 +541,7 @@ BMPEncodePBM(FILE * const ifP, -----------------------------------------------------------------------------*/ /* Note: Only PBM input uses this routine. Color images represented by 1 bpp via - color palette use the general BMPEncode(). + color palette use the general bmpEncode(). */ unsigned int const adjustedCols = (cols + 31) / 32 * 32; unsigned int const packedBytes = adjustedCols / 8; @@ -526,12 +559,12 @@ BMPEncodePBM(FILE * const ifP, makeBilevelColorMap(&bilevelColorMap); - nbyte += BMPwritecolormap(ifP, class, 1, &bilevelColorMap); + nbyte += BMPwriteColormap(ifP, class, 1, &bilevelColorMap); if (nbyte != (BMPlenfileheader(class) + BMPleninfoheader(class) + BMPlencolormap(class, 1, -1))) - pm_error(er_internal, "BMPEncodePBM 1"); + pm_error(er_internal, "bmpEncodePBM 1"); for (row = 0; row < rows; ++row){ size_t bytesWritten; @@ -548,23 +581,129 @@ BMPEncodePBM(FILE * const ifP, } if (nbyte != BMPlenfile(class, 1, -1, cols, rows)) - pm_error(er_internal, "BMPEncodePBM 2"); + pm_error(er_internal, "bmpEncodePbm 2"); } static void -analyze_colors(const pixel ** const pixels, - int const cols, - int const rows, - pixval const maxval, - int * const minimum_bpp_p, - colorMap * const colorMapP) { +makeHashFromBmpMap(const struct rgb * const bmpMap, + unsigned int const nColors, + colorhash_table * const chtP) { + + colorhist_vector chv; + unsigned int i; + + MALLOCARRAY_NOFAIL(chv, nColors); + + for (i = 0; i < nColors; ++i) { + const struct rgb * const mapEntryP = &bmpMap[i]; + + PPM_ASSIGN(chv[i].color, + mapEntryP->red, mapEntryP->grn, mapEntryP->blu); + } + + *chtP = ppm_colorhisttocolorhash(chv, nColors); + + ppm_freecolorhist(chv); +} + + + +static unsigned int +minBmpBitsForColorCount(unsigned int const colorCount) { + + unsigned int const minbits = pm_maxvaltobits(colorCount - 1); + + /* Only 1, 4, 8, and 24 are defined in the BMP spec we + implement and other bpp's have in fact been seen to confuse + viewers. There is an extended BMP format that has 16 bpp + too, but this program doesn't know how to generate that + (see Bmptopnm.c, though). + */ + if (minbits == 1) + return 1; + else if (minbits <= 4) + return 4; + else if (minbits <= 8) + return 8; + else + return 24; +} + + + +static void +getMapFile(const char * const mapFileName, + unsigned int * const minimumBppP, + colorMap * const colorMapP) { +/*---------------------------------------------------------------------------- + Get the color map (palette) for the BMP from file 'mapFileName'. + + Return the color map as *colormapP. + + Return as *minimumBppP the minimum number of bits per pixel it will + take to represent all the colors in the map in the BMP format. +-----------------------------------------------------------------------------*/ + + FILE * mapFileP; + int cols, rows; + pixval maxval; + pixel ** pixels; + unsigned int row; + unsigned int count; + + mapFileP = pm_openr(mapFileName); + + pixels = ppm_readppm(mapFileP, &cols, &rows, &maxval); + + if (cols * rows > MAXCOLORS) + pm_error("The colormap file you gave (-mapfile) has too " + "many entries for a BMP. A BMP can have at most " + "%u colors; the file has %u pixels, each of which " + "represents an entry in the color map.", + MAXCOLORS, cols * rows); + + count = 0; /* initial value */ + + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + pixel const color = pixels[row][col]; + struct rgb * const mapEntryP = &colorMapP->bmpMap[count++]; + + assert(count <= ARRAY_SIZE(colorMapP->bmpMap)); + + mapEntryP->red = PPM_GETR(color) * 255 / maxval; + mapEntryP->grn = PPM_GETG(color) * 255 / maxval; + mapEntryP->blu = PPM_GETB(color) * 255 / maxval; + } + } + ppm_freearray(pixels, rows); + + colorMapP->count = count; + + makeHashFromBmpMap(colorMapP->bmpMap, colorMapP->count, &colorMapP->cht); + + *minimumBppP = minBmpBitsForColorCount(count); + + pm_close(mapFileP); +} + + + +static void +analyzeColors(const pixel ** const pixels, + int const cols, + int const rows, + pixval const maxval, + unsigned int * const minimumBppP, + colorMap * const colorMapP) { /*---------------------------------------------------------------------------- Look at the colors in the image 'pixels' and compute values to use in representing those colors in a BMP image. - First of all, count the distinct colors. Return as *minimum_bpp_p + First of all, count the distinct colors. Return as *minimumBppP the minimum number of bits per pixel it will take to represent all the colors in BMP format. @@ -589,37 +728,23 @@ analyze_colors(const pixel ** const pixels, colorMapP->count = colorCount; if (chv == NULL) { pm_message("More than %u colors found", MAXCOLORS); - *minimum_bpp_p = 24; + *minimumBppP = 24; colorMapP->cht = NULL; } else { - unsigned int const minbits = pm_maxvaltobits(colorMapP->count - 1); - unsigned int i; pm_message("%u colors found", colorMapP->count); - /* Only 1, 4, 8, and 24 are defined in the BMP spec we - implement and other bpp's have in fact been seen to confuse - viewers. There is an extended BMP format that has 16 bpp - too, but this program doesn't know how to generate that - (see Bmptopnm.c, though). - */ - if (minbits == 1) - *minimum_bpp_p = 1; - else if (minbits <= 4) - *minimum_bpp_p = 4; - else if (minbits <= 8) - *minimum_bpp_p = 8; - else - *minimum_bpp_p = 24; + *minimumBppP = minBmpBitsForColorCount(colorMapP->count); /* * Now scale the maxval to 255 as required by BMP format. */ for (i = 0; i < colorMapP->count; ++i) { - colorMapP->red[i] = (pixval) PPM_GETR(chv[i].color) * 255 / maxval; - colorMapP->grn[i] = (pixval) PPM_GETG(chv[i].color) * 255 / maxval; - colorMapP->blu[i] = (pixval) PPM_GETB(chv[i].color) * 255 / maxval; + struct rgb * const mapEntryP = &colorMapP->bmpMap[i]; + mapEntryP->red = (pixval) PPM_GETR(chv[i].color) * 255 / maxval; + mapEntryP->grn = (pixval) PPM_GETG(chv[i].color) * 255 / maxval; + mapEntryP->blu = (pixval) PPM_GETB(chv[i].color) * 255 / maxval; } /* And make a hash table for fast lookup. */ @@ -631,38 +756,52 @@ analyze_colors(const pixel ** const pixels, static void -choose_colortype_bpp(struct cmdline_info const cmdline, - unsigned int const colors, - unsigned int const minimum_bpp, - enum colortype * const colortype_p, - unsigned int * const bits_per_pixel_p) { +chooseColortypeBpp(bool const userRequestsBpp, + unsigned int const requestedBpp, + unsigned int const minimumBpp, + enum colortype * const colortypeP, + unsigned int * const bitsPerPixelP) { +/*---------------------------------------------------------------------------- + Determine whether the BMP raster should contain RGB values or palette + indices and how many bits is should have for each pixel. - if (!cmdline.bppSpec) { + 'userRequestsBpp' says the user has requested a particular number of + bits per pixel. 'requestedBpp' is his request, and we assume it's a + valid value for a BMP. + + 'colors' is how many colors are in the image. + + 'minimumBpp' is the minimum number of bits it takes to represent all + the colors in the image. We assume it is valid for a BMP. + + We return our choices as *colortypeP and *bitsPerPixelP. +-----------------------------------------------------------------------------*/ + if (!userRequestsBpp) { /* User has no preference as to bits per pixel. Choose the smallest number possible for this image. */ - *bits_per_pixel_p = minimum_bpp; + *bitsPerPixelP = minimumBpp; } else { - if (cmdline.bpp < minimum_bpp) + if (requestedBpp < minimumBpp) pm_error("There are too many colors in the image to " - "represent in the\n" - "number of bits per pixel you requested: %d.\n" + "represent in the " + "number of bits per pixel you requested: %d. " "You may use Pnmquant to reduce the number of " "colors in the image.", - cmdline.bpp); + requestedBpp); else - *bits_per_pixel_p = cmdline.bpp; + *bitsPerPixelP = requestedBpp; } - assert(*bits_per_pixel_p == 1 || - *bits_per_pixel_p == 4 || - *bits_per_pixel_p == 8 || - *bits_per_pixel_p == 24); + assert(*bitsPerPixelP == 1 || + *bitsPerPixelP == 4 || + *bitsPerPixelP == 8 || + *bitsPerPixelP == 24); - if (*bits_per_pixel_p > 8) - *colortype_p = TRUECOLOR; + if (*bitsPerPixelP > 8) + *colortypeP = TRUECOLOR; else { - *colortype_p = PALETTE; + *colortypeP = PALETTE; } } @@ -676,12 +815,12 @@ doPbm(FILE * const ifP, int const class, FILE * const ofP) { - /* In the PBM case the raster is read directly from the input by - pbm_readpbmrow_packed. The raster format is almost identical, - except that BMP specifies rows to be zero-filled to 32 bit borders - and that in BMP the bottom row comes first in order. + /* We read the raster directly from the input with + pbm_readpbmrow_packed(). The raster format is almost + identical, except that BMP specifies rows to be zero-filled to + 32 bit borders and that in BMP the bottom row comes first in + order. */ - int const CHARBITS = (sizeof(unsigned char)*8); int const colChars = pbm_packed_bytes(cols); int const adjustedCols = (cols+31) /32 * 32; @@ -709,7 +848,7 @@ doPbm(FILE * const ifP, thisRow[i] = ~thisRow[i]; /* flip all pixels */ } /* This may seem unnecessary, because the color palette - (RGB[] in BMPEncodePBM) can be inverted for the same effect. + (RGB[] in bmpEncodePbm) can be inverted for the same effect. However we take this precaution, for there is indication that some BMP viewers may get confused with that. */ @@ -721,25 +860,28 @@ doPbm(FILE * const ifP, } } - BMPEncodePBM(ofP, class, cols, rows, bitrow); + bmpEncodePbm(ofP, class, cols, rows, bitrow); } static void -doPgmPpm(FILE * const ifP, +doPgmPpm(FILE * const ifP, unsigned int const cols, unsigned int const rows, pixval const maxval, int const ppmFormat, int const class, + bool const userRequestsBpp, + unsigned int const requestedBpp, + const char * const mapFileName, FILE * const ofP) { - /* PGM and PPM. The input image is read into a PPM array, scanned - for color analysis and converted to a BMP raster. - Logic works for PBM. + /* PGM and PPM. We read the input image into a PPM array, scan it + to analyze the colors, and convert it to a BMP raster. Logic + works for PBM. */ - int minimumBpp; + unsigned int minimumBpp; unsigned int bitsPerPixel; enum colortype colortype; unsigned int row; @@ -752,13 +894,16 @@ doPgmPpm(FILE * const ifP, for (row = 0; row < rows; ++row) ppm_readppmrow(ifP, pixels[row], cols, maxval, ppmFormat); - analyze_colors((const pixel**)pixels, cols, rows, maxval, - &minimumBpp, &colorMap); + if (mapFileName) + getMapFile(mapFileName, &minimumBpp, &colorMap); + else + analyzeColors((const pixel**)pixels, cols, rows, maxval, + &minimumBpp, &colorMap); - choose_colortype_bpp(cmdline, colorMap.count, minimumBpp, &colortype, - &bitsPerPixel); + chooseColortypeBpp(userRequestsBpp, requestedBpp, minimumBpp, + &colortype, &bitsPerPixel); - BMPEncode(stdout, class, colortype, bitsPerPixel, + bmpEncode(ofP, class, colortype, bitsPerPixel, cols, rows, (const pixel**)pixels, maxval, &colorMap); freeColorMap(&colorMap); @@ -767,17 +912,19 @@ doPgmPpm(FILE * const ifP, int -main(int argc, char **argv) { +main(int argc, + const char ** argv) { + struct cmdlineInfo cmdline; FILE * ifP; int rows; int cols; pixval maxval; int ppmFormat; - ppm_init(&argc, argv); + pm_proginit(&argc, argv); - parse_command_line(argc, argv, &cmdline); + parseCommandLine(argc, argv, &cmdline); ifP = pm_openr(cmdline.input_filename); @@ -786,7 +933,9 @@ main(int argc, char **argv) { if (PPM_FORMAT_TYPE(ppmFormat) == PBM_TYPE) doPbm(ifP, cols, rows, ppmFormat, cmdline.class, stdout); else - doPgmPpm(ifP, cols, rows, maxval, ppmFormat, cmdline.class, stdout); + doPgmPpm(ifP, cols, rows, maxval, ppmFormat, + cmdline.class, cmdline.bppSpec, cmdline.bpp, cmdline.mapfile, + stdout); pm_close(ifP); pm_close(stdout); |