diff options
Diffstat (limited to 'converter')
-rw-r--r-- | converter/other/Makefile | 4 | ||||
-rw-r--r-- | converter/other/pamtodjvurle.c | 2 | ||||
-rw-r--r-- | converter/other/pamtosvg/fit.c | 2 | ||||
-rw-r--r-- | converter/other/pngtopam.c | 1265 | ||||
-rw-r--r-- | converter/other/pngtopnm.c | 464 | ||||
-rw-r--r-- | converter/other/pnmtopng.c | 10 | ||||
-rw-r--r-- | converter/other/x11wd.h | 8 | ||||
-rw-r--r-- | converter/pbm/g3topbm.c | 128 | ||||
-rw-r--r-- | converter/pbm/pbmtodjvurle.c | 166 | ||||
-rw-r--r-- | converter/ppm/ilbmtoppm.c | 18 | ||||
-rw-r--r-- | converter/ppm/picttoppm.c | 66 | ||||
-rw-r--r-- | converter/ppm/ppmtoarbtxt.c | 4 | ||||
-rw-r--r-- | converter/ppm/ppmtoilbm.c | 24 | ||||
-rw-r--r-- | converter/ppm/ppmtompeg/headers/param.h | 97 | ||||
-rw-r--r-- | converter/ppm/ppmtompeg/param.c | 31 | ||||
-rw-r--r-- | converter/ppm/ppmtompeg/ppmtompeg.c | 159 | ||||
-rw-r--r-- | converter/ppm/ppmtoyuvsplit.c | 277 |
17 files changed, 2014 insertions, 711 deletions
diff --git a/converter/other/Makefile b/converter/other/Makefile index 3a6bb2af..592eaac2 100644 --- a/converter/other/Makefile +++ b/converter/other/Makefile @@ -96,7 +96,7 @@ endif BINARIES = $(PORTBINARIES) pnmtorast rasttopnm ifeq ($(HAVE_PNGLIB),Y) - BINARIES += pnmtopng pngtopnm pamrgbatopng + BINARIES += pnmtopng pngtopnm pngtopam pamrgbatopng endif ifneq ($(JPEGLIB),NONE) BINARIES += jpegtopnm pnmtojpeg @@ -155,7 +155,7 @@ else PNGLIB_LIBOPTS = $(shell libpng-config --ldflags) endif -pngtopnm: %: %.o $(NETPBMLIB) $(LIBOPT) +pngtopnm pngtopam: %: %.o $(NETPBMLIB) $(LIBOPT) $(LD) $(LDFLAGS) -o $@ $@.o \ $(shell $(LIBOPT) $(NETPBMLIB)) \ $(PNGLIB_LIBOPTS) $(MATHLIB) $(LDLIBS) $(RPATH) $(LADD) diff --git a/converter/other/pamtodjvurle.c b/converter/other/pamtodjvurle.c index ae35e81d..fecf410e 100644 --- a/converter/other/pamtodjvurle.c +++ b/converter/other/pamtodjvurle.c @@ -179,7 +179,7 @@ writeRleRun(FILE * const ofP, 'transcolor' is a 3-deep tuple with the same maxval as the image. -----------------------------------------------------------------------------*/ - uint32n rlevalue; /* RLE-encoded color/valuex */ + uint32_t rlevalue; /* RLE-encoded color/valuex */ int index; if (count > 0) { diff --git a/converter/other/pamtosvg/fit.c b/converter/other/pamtosvg/fit.c index ab73e439..5ba7a2f6 100644 --- a/converter/other/pamtosvg/fit.c +++ b/converter/other/pamtosvg/fit.c @@ -292,7 +292,7 @@ remove_adjacent_corners(index_list_type * const list, pixel. We need this for checking the adjacency of the last corner. We need to do this because the adjacent corners turn into - two-pixel-long curves, which can only be fit by straight lines. + two-pixel-long curves, which can be fit only by straight lines. -----------------------------------------------------------------------------*/ unsigned int j; unsigned int last; diff --git a/converter/other/pngtopam.c b/converter/other/pngtopam.c new file mode 100644 index 00000000..3039c769 --- /dev/null +++ b/converter/other/pngtopam.c @@ -0,0 +1,1265 @@ +/* +** Copyright (C) 1995,1998 by Alexander Lehmann <alex@hal.rhein-main.de> +** and Willem van Schaik <willem@schaik.com> +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** modeled after giftopnm by David Koblas and +** with lots of bits pasted from libpng.txt by Guy Eric Schalnat +*/ + +#ifndef PNMTOPNG_WARNING_LEVEL +# define PNMTOPNG_WARNING_LEVEL 0 /* use 0 for backward compatibility, */ +#endif /* 2 for warnings (1 == error) */ + + +#include <assert.h> +#include <math.h> +#include <float.h> +#include <png.h> /* includes zlib.h and setjmp.h */ +#define VERSION "2.37.4 (5 December 1999) +netpbm" + +#include "mallocvar.h" +#include "nstring.h" +#include "shhopt.h" +#include "pam.h" + +typedef struct _jmpbuf_wrapper { + jmp_buf jmpbuf; +} jmpbuf_wrapper; + +enum alpha_handling {ALPHA_NONE, ALPHA_ONLY, ALPHA_MIX, ALPHA_IN}; + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char *inputFilespec; /* '-' if stdin */ + unsigned int verbose; + enum alpha_handling alpha; + const char * background; + float gamma; /* -1.0 means unspecified */ + const char * text; + unsigned int time; +}; + + +typedef struct { +/*---------------------------------------------------------------------------- + A color in a format compatible with the PNG library. + + Note that the PNG library declares types png_color and png_color_16 + which are similar. +-----------------------------------------------------------------------------*/ + png_uint_16 r; + png_uint_16 g; + png_uint_16 b; +} pngcolor; + + +static png_uint_16 maxval; +static bool verbose; +static jmpbuf_wrapper pngtopnm_jmpbuf_struct; + + +static void +parseCommandLine(int argc, + const char ** argv, + struct cmdlineInfo * cmdlineP ) { +/*---------------------------------------------------------------------------- + Parse program command line described in Unix standard form by argc + and argv. Return the information in the options as *cmdlineP. + + If command line is internally inconsistent (invalid options, etc.), + issue error message to stderr and abort program. + + Note that the strings we return are stored in the storage that + was passed to us as the argv array. We also trash *argv. +-----------------------------------------------------------------------------*/ + optEntry * option_def; + /* Instructions to optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + + unsigned int alphaSpec, alphapamSpec, mixSpec, + backgroundSpec, gammaSpec, textSpec; + + MALLOCARRAY(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "verbose", OPT_FLAG, NULL, + &cmdlineP->verbose, 0); + OPTENT3(0, "alpha", OPT_FLAG, NULL, + &alphaSpec, 0); + OPTENT3(0, "alphapam", OPT_FLAG, NULL, + &alphapamSpec, 0); + OPTENT3(0, "mix", OPT_FLAG, NULL, + &mixSpec, 0); + OPTENT3(0, "background", OPT_STRING, &cmdlineP->background, + &backgroundSpec, 0); + OPTENT3(0, "gamma", OPT_FLOAT, &cmdlineP->gamma, + &gammaSpec, 0); + OPTENT3(0, "text", OPT_STRING, &cmdlineP->text, + &textSpec, 0); + OPTENT3(0, "time", OPT_FLAG, NULL, + &cmdlineP->time, 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, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + + if (alphaSpec + mixSpec + alphapamSpec > 1) + pm_error("You cannot specify more than one of -alpha -alphapam -mix"); + else if (alphaSpec) + cmdlineP->alpha = ALPHA_ONLY; + else if (mixSpec) + cmdlineP->alpha = ALPHA_MIX; + else if (alphapamSpec) + cmdlineP->alpha = ALPHA_IN; + else + cmdlineP->alpha = ALPHA_NONE; + + if (backgroundSpec && !mixSpec) + pm_error("-background is useless without -mix"); + + if (!backgroundSpec) + cmdlineP->background = NULL; + + if (!gammaSpec) + cmdlineP->gamma = -1.0; + + if (!textSpec) + cmdlineP->text = NULL; + + if (argc-1 < 1) + cmdlineP->inputFilespec = "-"; + else if (argc-1 == 1) + cmdlineP->inputFilespec = argv[1]; + else + pm_error("Program takes at most one argument: input file name. " + "you specified %d", argc-1); +} + + + +static png_uint_16 +get_png_val(const png_byte ** const pp, + int const bit_depth) { + + png_uint_16 c; + + if (bit_depth == 16) + c = (*((*pp)++)) << 8; + else + c = 0; + + c |= (*((*pp)++)); + + return c; +} + + + +static bool +isGrayscale(pngcolor const color) { + + return color.r == color.g && color.r == color.b; +} + + + +static sample +alphaMix(png_uint_16 const foreground, + png_uint_16 const background, + png_uint_16 const alpha, + sample const maxval) { + + double const opacity = (double)alpha / maxval; + double const transparency = 1.0 - opacity; + + return ROUNDU(foreground * opacity + background * transparency); +} + + + +static void +setTuple(const struct pam * const pamP, + tuple const tuple, + pngcolor const foreground, + pngcolor const background, + enum alpha_handling const alphaHandling, + png_uint_16 const alpha) { + + if (alphaHandling == ALPHA_ONLY) + tuple[0] = alpha; + else if (alphaHandling == ALPHA_NONE || + (alphaHandling == ALPHA_MIX && alpha == maxval)) { + if (pamP->depth < 3) + tuple[0] = foreground.r; + else { + tuple[PAM_RED_PLANE] = foreground.r; + tuple[PAM_GRN_PLANE] = foreground.g; + tuple[PAM_BLU_PLANE] = foreground.b; + } + } else if (alphaHandling == ALPHA_IN) { + if (pamP->depth < 4) { + tuple[0] = foreground.r; + tuple[PAM_GRAY_TRN_PLANE] = alpha; + } else { + tuple[PAM_RED_PLANE] = foreground.r; + tuple[PAM_GRN_PLANE] = foreground.g; + tuple[PAM_BLU_PLANE] = foreground.b; + tuple[PAM_TRN_PLANE] = alpha; + } + } else { + assert(alphaHandling == ALPHA_MIX); + + if (pamP->depth < 3) + tuple[0] = + alphaMix(foreground.r, background.r, alpha, maxval); + else { + tuple[PAM_RED_PLANE] = + alphaMix(foreground.r, background.r, alpha, maxval); + tuple[PAM_GRN_PLANE] = + alphaMix(foreground.g, background.g, alpha, maxval); + tuple[PAM_BLU_PLANE] = + alphaMix(foreground.b, background.b, alpha, maxval); + } + } +} + + + +static png_uint_16 +gamma_correct(png_uint_16 const v, + float const g) { + + if (g != -1.0) + return (png_uint_16) ROUNDU(pow((double) v / maxval, (1.0 / g)) * + maxval); + else + return v; +} + + + +static int iscolor (png_color c) +{ + return c.red != c.green || c.green != c.blue; +} + +static void save_text (png_info *info_ptr, FILE *tfp) +{ + int i, j, k; + + for (i = 0 ; i < info_ptr->num_text ; i++) { + j = 0; + while (info_ptr->text[i].key[j] != '\0' && info_ptr->text[i].key[j] != ' ') + j++; + if (info_ptr->text[i].key[j] != ' ') { + fprintf (tfp, "%s", info_ptr->text[i].key); + for (j = strlen (info_ptr->text[i].key) ; j < 15 ; j++) + putc (' ', tfp); + } else { + fprintf (tfp, "\"%s\"", info_ptr->text[i].key); + for (j = strlen (info_ptr->text[i].key) ; j < 13 ; j++) + putc (' ', tfp); + } + putc (' ', tfp); /* at least one space between key and text */ + + for (j = 0 ; j < info_ptr->text[i].text_length ; j++) { + putc (info_ptr->text[i].text[j], tfp); + if (info_ptr->text[i].text[j] == '\n') + for (k = 0 ; k < 16 ; k++) + putc ((int)' ', tfp); + } + putc ((int)'\n', tfp); + } +} + +static void show_time (png_info *info_ptr) +{ + static const char * const month[] = { + "", "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" + }; + + if (info_ptr->valid & PNG_INFO_tIME) { + pm_message ("modification time: %02d %s %d %02d:%02d:%02d", + info_ptr->mod_time.day, month[info_ptr->mod_time.month], + info_ptr->mod_time.year, info_ptr->mod_time.hour, + info_ptr->mod_time.minute, info_ptr->mod_time.second); + } +} + +static void pngtopnm_error_handler (png_structp png_ptr, png_const_charp msg) +{ + jmpbuf_wrapper *jmpbuf_ptr; + + /* this function, aside from the extra step of retrieving the "error + * pointer" (below) and the fact that it exists within the application + * rather than within libpng, is essentially identical to libpng's + * default error handler. The second point is critical: since both + * setjmp() and longjmp() are called from the same code, they are + * guaranteed to have compatible notions of how big a jmp_buf is, + * regardless of whether _BSD_SOURCE or anything else has (or has not) + * been defined. */ + + pm_message("fatal libpng error: %s", msg); + + jmpbuf_ptr = png_get_error_ptr(png_ptr); + if (jmpbuf_ptr == NULL) { + /* we are completely hosed now */ + pm_error("EXTREMELY fatal error: jmpbuf unrecoverable; terminating."); + } + + longjmp(jmpbuf_ptr->jmpbuf, 1); +} + + + +static void +dump_png_info(png_info *info_ptr) { + + const char *type_string; + const char *filter_string; + + switch (info_ptr->color_type) { + case PNG_COLOR_TYPE_GRAY: + type_string = "gray"; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + type_string = "gray+alpha"; + break; + + case PNG_COLOR_TYPE_PALETTE: + type_string = "palette"; + break; + + case PNG_COLOR_TYPE_RGB: + type_string = "truecolor"; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + type_string = "truecolor+alpha"; + break; + } + + switch (info_ptr->filter_type) { + case PNG_FILTER_TYPE_BASE: + asprintfN(&filter_string, "base filter"); + break; + default: + asprintfN(&filter_string, "unknown filter type %d", + info_ptr->filter_type); + } + + pm_message("reading a %ldw x %ldh image, %d bit%s", + info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->bit_depth > 1 ? "s" : ""); + pm_message("%s, %s, %s", + type_string, + info_ptr->interlace_type ? + "Adam7 interlaced" : "not interlaced", + filter_string); + pm_message("background {index, gray, red, green, blue} = " + "{%d, %d, %d, %d, %d}", + info_ptr->background.index, + info_ptr->background.gray, + info_ptr->background.red, + info_ptr->background.green, + info_ptr->background.blue); + + strfree(filter_string); + + if (info_ptr->valid & PNG_INFO_tRNS) + pm_message("tRNS chunk (transparency): %u entries", + info_ptr->num_trans); + else + pm_message("tRNS chunk (transparency): not present"); + + if (info_ptr->valid & PNG_INFO_gAMA) + pm_message("gAMA chunk (image gamma): gamma = %4.2f", info_ptr->gamma); + else + pm_message("gAMA chunk (image gamma): not present"); + + if (info_ptr->valid & PNG_INFO_sBIT) + pm_message("sBIT chunk: present"); + else + pm_message("sBIT chunk: not present"); + + if (info_ptr->valid & PNG_INFO_cHRM) + pm_message("cHRM chunk: present"); + else + pm_message("cHRM chunk: not present"); + + if (info_ptr->valid & PNG_INFO_PLTE) + pm_message("PLTE chunk: %d entries", info_ptr->num_palette); + else + pm_message("PLTE chunk: not present"); + + if (info_ptr->valid & PNG_INFO_bKGD) + pm_message("bKGD chunk: present"); + else + pm_message("bKGD chunk: not present"); + + if (info_ptr->valid & PNG_INFO_PLTE) + pm_message("hIST chunk: present"); + else + pm_message("hIST chunk: not present"); + + if (info_ptr->valid & PNG_INFO_pHYs) + pm_message("pHYs chunk: present"); + else + pm_message("pHYs chunk: not present"); + + if (info_ptr->valid & PNG_INFO_oFFs) + pm_message("oFFs chunk: present"); + else + pm_message("oFFs chunk: not present"); + + if (info_ptr->valid & PNG_INFO_tIME) + pm_message("tIME chunk: present"); + else + pm_message("tIME chunk: not present"); + + if (info_ptr->valid & PNG_INFO_pCAL) + pm_message("pCAL chunk: present"); + else + pm_message("pCAL chunk: not present"); + + if (info_ptr->valid & PNG_INFO_sRGB) + pm_message("sRGB chunk: present"); + else + pm_message("sRGB chunk: not present"); +} + + + +static unsigned int +computePngLineSize(png_info * const pngInfoP) { + + unsigned int const bytesPerSample = pngInfoP->bit_depth == 16 ? 2 : 1; + + unsigned int samplesPerPixel; + + switch (pngInfoP->color_type) { + case PNG_COLOR_TYPE_GRAY_ALPHA: samplesPerPixel = 2; break; + case PNG_COLOR_TYPE_RGB: samplesPerPixel = 3; break; + case PNG_COLOR_TYPE_RGB_ALPHA: samplesPerPixel = 4; break; + default: samplesPerPixel = 1; + } + + if (UINT_MAX / bytesPerSample / samplesPerPixel < pngInfoP->width) + pm_error("Width %u of PNG is uncomputably large", + (unsigned int)pngInfoP->width); + + return pngInfoP->width * bytesPerSample * samplesPerPixel; +} + + + +static void +allocPngRaster(png_info * const pngInfoP, + png_byte *** const pngImageP) { + + unsigned int const lineSize = computePngLineSize(pngInfoP); + + png_byte ** pngImage; + unsigned int row; + + MALLOCARRAY(pngImage, pngInfoP->height); + + if (pngImage == NULL) + pm_error("couldn't allocate space for %u PNG raster rows", + (unsigned int)pngInfoP->height); + + for (row = 0; row < pngInfoP->height; ++row) { + MALLOCARRAY(pngImage[row], lineSize); + if (pngImage[row] == NULL) + pm_error("couldn't allocate space for %uth row of PNG raster", + row); + } + *pngImageP = pngImage; +} + + + +static void +freePngRaster(png_byte ** const pngRaster, + png_info * const pngInfoP) { + + unsigned int row; + + for (row = 0; row < pngInfoP->height; ++row) + free(pngRaster[row]); + + free(pngRaster); +} + + + +static bool +isTransparentColor(pngcolor const color, + png_info * const pngInfoP, + double const totalgamma) { +/*---------------------------------------------------------------------------- + Return TRUE iff pixels of color 'color' are supposed to be transparent + everywhere they occur. Assume it's an RGB image. + + 'color' has been gamma-corrected. +-----------------------------------------------------------------------------*/ + bool retval; + + if (pngInfoP->valid & PNG_INFO_tRNS) { + const png_color_16 * const transColorP = &pngInfoP->trans_values; + + /* It seems odd that libpng lets you get gamma-corrected pixel + values, but not gamma-corrected transparency or background + values. But as that is the case, we have to gamma-correct + the transparency values. + + Note that because we compare the gamma-corrected values and + there may be many-to-one mapping of uncorrected to corrected + values, more pixels may be transparent than what the user + intended. + + We could fix this by not letting libpng gamma-correct the + pixels, and just do it ourselves. + */ + + switch (pngInfoP->color_type) { + case PNG_COLOR_TYPE_GRAY: + retval = color.r == gamma_correct(transColorP->gray, totalgamma); + break; + default: + retval = + color.r == gamma_correct(transColorP->red, totalgamma) && + color.g == gamma_correct(transColorP->green, totalgamma) && + color.b == gamma_correct(transColorP->blue, totalgamma); + } + } else + retval = FALSE; + + return retval; +} + + + +#define SIG_CHECK_SIZE 4 + +static void +read_sig_buf(FILE * const ifP) { + + unsigned char sig_buf[SIG_CHECK_SIZE]; + size_t bytesRead; + + bytesRead = fread(sig_buf, 1, SIG_CHECK_SIZE, ifP); + if (bytesRead != SIG_CHECK_SIZE) + pm_error ("input file is empty or too short"); + + if (png_sig_cmp(sig_buf, (png_size_t) 0, (png_size_t) SIG_CHECK_SIZE) + != 0) + pm_error ("input file is not a PNG file"); +} + + + +static void +setupGammaCorrection(png_struct * const png_ptr, + png_info * const info_ptr, + float const displaygamma, + float * const totalgammaP) { + + if (displaygamma == -1.0) + *totalgammaP = -1.0; + else { + float imageGamma; + if (info_ptr->valid & PNG_INFO_gAMA) + imageGamma = info_ptr->gamma; + else { + if (verbose) + pm_message("PNG doesn't specify image gamma. Assuming 1.0"); + imageGamma = 1.0; + } + + if (fabs(displaygamma * imageGamma - 1.0) < .01) { + *totalgammaP = -1.0; + if (verbose) + pm_message("image gamma %4.2f matches " + "display gamma %4.2f. No conversion.", + imageGamma, displaygamma); + } else { + png_set_gamma(png_ptr, displaygamma, imageGamma); + *totalgammaP = imageGamma * displaygamma; + /* in case of gamma-corrections, sBIT's as in the + PNG-file are not valid anymore + */ + info_ptr->valid &= ~PNG_INFO_sBIT; + if (verbose) + pm_message("image gamma is %4.2f, " + "converted for display gamma of %4.2f", + imageGamma, displaygamma); + } + } +} + + + +static bool +paletteHasPartialTransparency(png_info * const info_ptr) { + + bool retval; + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { + if (info_ptr->valid & PNG_INFO_tRNS) { + bool foundGray; + unsigned int i; + + for (i = 0, foundGray = FALSE; + i < info_ptr->num_trans && !foundGray; + ++i) { + if (info_ptr->trans[i] != 0 && + info_ptr->trans[i] != maxval) { + foundGray = TRUE; + } + } + retval = foundGray; + } else + retval = FALSE; + } else + retval = FALSE; + + return retval; +} + + + +static void +getComponentSbitFg(png_info * const pngInfoP, + png_byte * const fgSbitP, + bool * const notUniformP) { + + if (pngInfoP->color_type == PNG_COLOR_TYPE_RGB || + pngInfoP->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + pngInfoP->color_type == PNG_COLOR_TYPE_PALETTE) { + if (pngInfoP->sig_bit.red == pngInfoP->sig_bit.blue && + pngInfoP->sig_bit.red == pngInfoP->sig_bit.green) { + *notUniformP = false; + *fgSbitP = pngInfoP->sig_bit.red; + } else + *notUniformP = true; + } else { + /* It has only a gray channel so it's obviously uniform */ + *notUniformP = false; + *fgSbitP = pngInfoP->sig_bit.gray; + } +} + + + +static void +getComponentSbit(png_info * const pngInfoP, + enum alpha_handling const alphaHandling, + png_byte * const componentSbitP, + bool * const notUniformP) { + + switch (alphaHandling) { + + case ALPHA_ONLY: + /* We care only about the alpha channel, so the uniform Sbit is + the alpha Sbit + */ + *notUniformP = false; + *componentSbitP = pngInfoP->sig_bit.alpha; + break; + case ALPHA_NONE: + case ALPHA_MIX: + /* We aren't going to produce an alpha channel, so we care only + about the uniformity of the foreground channels. + */ + getComponentSbitFg(pngInfoP, componentSbitP, notUniformP); + break; + case ALPHA_IN: { + /* We care about both the foreground and the alpha */ + bool fgNotUniform; + png_byte fgSbit; + + getComponentSbitFg(pngInfoP, &fgSbit, &fgNotUniform); + + if (fgNotUniform) + *notUniformP = true; + else { + if (fgSbit == pngInfoP->sig_bit.alpha) { + *notUniformP = false; + *componentSbitP = fgSbit; + } else + *notUniformP = true; + } + } break; + } +} + + + +static void +shiftPalette(png_info * const pngInfoP, + unsigned int const shift) { +/*---------------------------------------------------------------------------- + Shift every component of every color in the PNG palette right by + 'shift' bits because sBIT chunk says only those are significant. +-----------------------------------------------------------------------------*/ + if (shift > 7) + pm_error("Invalid PNG: paletted image can't have " + "more than 8 significant bits per component, " + "but sBIT chunk says %u bits", + shift); + else { + unsigned int i; + + for (i = 0; i < pngInfoP->num_palette; ++i) { + pngInfoP->palette[i].red >>= (8 - shift); + pngInfoP->palette[i].green >>= (8 - shift); + pngInfoP->palette[i].blue >>= (8 - shift); + } + } +} + + + +static void +computeMaxvalFromSbit(png_struct * const pngP, + png_info * const pngInfoP, + enum alpha_handling const alphaHandling, + png_uint_16 * const maxvalP, + bool * const succeededP, + int * const errorlevelP) { + + /* sBIT handling is very tricky. If we are extracting only the + image, we can use the sBIT info for grayscale and color images, + if the three values agree. If we extract the transparency/alpha + mask, sBIT is irrelevant for trans and valid for alpha. If we + mix both, the multiplication may result in values that require + the normal bit depth, so we will use the sBIT info only for + transparency, if we know that only solid and fully transparent + is used + */ + + bool notUniform; + /* The sBIT chunk says the number of significant high-order bits + in each component varies among the components we care about. + */ + png_byte componentSigBit; + /* The number of high-order significant bits in each RGB component. + Meaningless if they aren't all the same (i.e. 'notUniform') + */ + + getComponentSbit(pngInfoP, alphaHandling, &componentSigBit, ¬Uniform); + + if (notUniform) { + pm_message("This program cannot handle " + "different bit depths for color channels"); + pm_message("writing file with %u bit resolution", pngInfoP->bit_depth); + *succeededP = false; + *errorlevelP = PNMTOPNG_WARNING_LEVEL; + } else if (componentSigBit > 15) { + pm_message("Invalid PNG: says %u significant bits for a component; " + "max possible is 16. Ignoring sBIT chunk.", + componentSigBit); + *succeededP = false; + *errorlevelP = PNMTOPNG_WARNING_LEVEL; + } else { + if (alphaHandling == ALPHA_MIX && + (pngInfoP->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + pngInfoP->color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + paletteHasPartialTransparency(pngInfoP))) + *succeededP = false; + else { + if (componentSigBit < pngInfoP->bit_depth) { + pm_message("Image has fewer significant bits, " + "writing file with %u bits", componentSigBit); + *maxvalP = (1l << componentSigBit) - 1; + *succeededP = true; + + if (pngInfoP->color_type == PNG_COLOR_TYPE_PALETTE) + shiftPalette(pngInfoP, componentSigBit); + else + png_set_shift(pngP, &pngInfoP->sig_bit); + } else + *succeededP = false; + } + } +} + + + +static void +setupSignificantBits(png_struct * const pngP, + png_info * const pngInfoP, + enum alpha_handling const alphaHandling, + png_uint_16 * const maxvalP, + int * const errorlevelP) { +/*---------------------------------------------------------------------------- + Figure out what maxval would best express the information in the PNG + described by *pngP and *pngInfoP, with 'alpha' telling which + information in the PNG we care about (image or alpha mask). + + Return the result as *maxvalP. + + Also set up *pngP for the corresponding significant bits. +-----------------------------------------------------------------------------*/ + bool gotItFromSbit; + + if (pngInfoP->valid & PNG_INFO_sBIT) + computeMaxvalFromSbit(pngP, pngInfoP, alphaHandling, + maxvalP, &gotItFromSbit, errorlevelP); + else + gotItFromSbit = false; + + if (!gotItFromSbit) { + if (pngInfoP->color_type == PNG_COLOR_TYPE_PALETTE) { + if (alphaHandling == ALPHA_ONLY) { + if (pngInfoP->color_type == PNG_COLOR_TYPE_GRAY || + pngInfoP->color_type == PNG_COLOR_TYPE_RGB) + /* The alpha mask will be all opaque, so maxval 1 + is plenty + */ + *maxvalP = 1; + else if (paletteHasPartialTransparency(pngInfoP)) + /* Use same maxval as PNG transparency palette for + simplicity + */ + *maxvalP = 255; + else + /* A common case, so we conserve bits */ + *maxvalP = 1; + } else + /* Use same maxval as PNG palette for simplicity */ + *maxvalP = 255; + } else { + *maxvalP = (1l << pngInfoP->bit_depth) - 1; + } + } +} + + + +static bool +imageHasColor(png_info * const info_ptr) { + + bool retval; + + if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || + info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + + retval = FALSE; + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { + bool foundColor; + unsigned int i; + + for (i = 0, foundColor = FALSE; + i < info_ptr->num_palette && !foundColor; + ++i) { + if (iscolor(info_ptr->palette[i])) + foundColor = TRUE; + } + retval = foundColor; + } else + retval = TRUE; + + return retval; +} + + + +static void +determineOutputType(png_info * const pngInfoP, + enum alpha_handling const alphaHandling, + pngcolor const bgColor, + xelval const maxval, + int * const formatP, + unsigned int * const depthP, + char * const tupleType) { + + if (alphaHandling == ALPHA_ONLY) { + /* The output is a old style pseudo-PNM transparency image */ + *depthP = 1; + *formatP = maxval > 1 ? PGM_FORMAT : PBM_FORMAT; + } else { + /* The output is a normal Netpbm image */ + bool const outputIsColor = + imageHasColor(pngInfoP) || !isGrayscale(bgColor); + + if (alphaHandling == ALPHA_IN) { + *formatP = PAM_FORMAT; + if (outputIsColor) { + *depthP = 4; + strcpy(tupleType, "RGB_ALPHA"); + } else { + *depthP = 1; + strcpy(tupleType, "GRAYSCALE_ALPHA"); + } + } else { + if (outputIsColor) { + *formatP = PPM_FORMAT; + *depthP = 3; + } else { + *depthP = 1; + *formatP = maxval > 1 ? PGM_FORMAT : PBM_FORMAT; + } + } + } +} + + + +static void +getBackgroundColor(png_info * const info_ptr, + const char * const requestedColor, + float const totalgamma, + xelval const maxval, + pngcolor * const bgColorP) { +/*---------------------------------------------------------------------------- + Figure out what the background color should be. If the user requested + a particular color ('requestedColor' not null), that's the one. + Otherwise, if the PNG specifies a background color, that's the one. + And otherwise, it's white. +-----------------------------------------------------------------------------*/ + if (requestedColor) { + /* Background was specified from the command-line; we always + use that. I chose to do no gamma-correction in this case; + which is a bit arbitrary. + */ + pixel const backcolor = ppm_parsecolor(requestedColor, maxval); + + bgColorP->r = PPM_GETR(backcolor); + bgColorP->g = PPM_GETG(backcolor); + bgColorP->b = PPM_GETB(backcolor); + + } else if (info_ptr->valid & PNG_INFO_bKGD) { + /* didn't manage to get libpng to work (bugs?) concerning background + processing, therefore we do our own. + */ + switch (info_ptr->color_type) { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_GRAY_ALPHA: + bgColorP->r = bgColorP->g = bgColorP->b = + gamma_correct(info_ptr->background.gray, totalgamma); + break; + case PNG_COLOR_TYPE_PALETTE: { + png_color const rawBgcolor = + info_ptr->palette[info_ptr->background.index]; + bgColorP->r = gamma_correct(rawBgcolor.red, totalgamma); + bgColorP->g = gamma_correct(rawBgcolor.green, totalgamma); + bgColorP->b = gamma_correct(rawBgcolor.blue, totalgamma); + } + break; + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: { + png_color_16 const rawBgcolor = info_ptr->background; + + bgColorP->r = gamma_correct(rawBgcolor.red, totalgamma); + bgColorP->g = gamma_correct(rawBgcolor.green, totalgamma); + bgColorP->b = gamma_correct(rawBgcolor.blue, totalgamma); + } + break; + } + } else + /* when no background given, we use white [from version 2.37] */ + bgColorP->r = bgColorP->g = bgColorP->b = maxval; +} + + + +#define GET_PNG_VAL(p) get_png_val(&(p), pngInfoP->bit_depth) + + + +static void +makeTupleRow(const struct pam * const pamP, + const tuple * const tuplerow, + png_info * const pngInfoP, + const png_byte * const pngRasterRow, + pngcolor const bgColor, + enum alpha_handling const alphaHandling, + double const totalgamma) { + + const png_byte * pngPixelP; + unsigned int col; + + pngPixelP = &pngRasterRow[0]; /* initial value */ + for (col = 0; col < pngInfoP->width; ++col) { + switch (pngInfoP->color_type) { + case PNG_COLOR_TYPE_GRAY: { + pngcolor fgColor; + fgColor.r = fgColor.g = fgColor.b = GET_PNG_VAL(pngPixelP); + setTuple(pamP, tuplerow[col], fgColor, bgColor, alphaHandling, + isTransparentColor(fgColor, pngInfoP, totalgamma) ? + 0 : maxval); + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: { + pngcolor fgColor; + png_uint_16 alpha; + + fgColor.r = fgColor.g = fgColor.b = GET_PNG_VAL(pngPixelP); + alpha = GET_PNG_VAL(pngPixelP); + setTuple(pamP, tuplerow[col], fgColor, bgColor, + alphaHandling, alpha); + } + break; + + case PNG_COLOR_TYPE_PALETTE: { + png_uint_16 const index = GET_PNG_VAL(pngPixelP); + png_color const paletteColor = pngInfoP->palette[index]; + + pngcolor fgColor; + + fgColor.r = paletteColor.red; + fgColor.g = paletteColor.green; + fgColor.b = paletteColor.blue; + + setTuple(pamP, tuplerow[col], fgColor, bgColor, alphaHandling, + (pngInfoP->valid & PNG_INFO_tRNS) && + index < pngInfoP->num_trans ? + pngInfoP->trans[index] : maxval); + } + break; + + case PNG_COLOR_TYPE_RGB: { + pngcolor fgColor; + + fgColor.r = GET_PNG_VAL(pngPixelP); + fgColor.g = GET_PNG_VAL(pngPixelP); + fgColor.b = GET_PNG_VAL(pngPixelP); + setTuple(pamP, tuplerow[col], fgColor, bgColor, alphaHandling, + isTransparentColor(fgColor, pngInfoP, totalgamma) ? + 0 : maxval); + } + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: { + pngcolor fgColor; + png_uint_16 alpha; + + fgColor.r = GET_PNG_VAL(pngPixelP); + fgColor.g = GET_PNG_VAL(pngPixelP); + fgColor.b = GET_PNG_VAL(pngPixelP); + alpha = GET_PNG_VAL(pngPixelP); + setTuple(pamP, tuplerow[col], fgColor, bgColor, + alphaHandling, alpha); + } + break; + + default: + pm_error("unknown PNG color type: %d", pngInfoP->color_type); + } + } +} + + + +static void +reportOutputFormat(const struct pam * const pamP) { + + switch (pamP->format) { + + case PBM_FORMAT: + pm_message("Writing a PBM file"); + break; + case PGM_FORMAT: + pm_message("Writing a PGM file with maxval %lu", pamP->maxval); + break; + case PPM_FORMAT: + pm_message("Writing a PPM file with maxval %lu", pamP->maxval); + break; + case PAM_FORMAT: + pm_message("Writing a PAM file with tuple type %s, maxval %u", + pamP->tuple_type, maxval); + break; + default: + assert(false); /* Every possible value handled above */ + } +} + + + +static void +writeNetpbm(struct pam * const pamP, + png_info * const pngInfoP, + png_byte ** const pngRaster, + pngcolor const bgColor, + enum alpha_handling const alphaHandling, + double const totalgamma) { +/*---------------------------------------------------------------------------- + Write a Netpbm image of either the image or the alpha mask, according to + 'alphaHandling' that is in the PNG image described by 'pngInfoP' and + pngRaster. + + *pamP describes the required output image and is consistent with + *pngInfoP. + + Use background color 'bgColor' in the output if the PNG is such that a + background color is needed. +-----------------------------------------------------------------------------*/ + tuple * tuplerow; + unsigned int row; + + if (verbose) + reportOutputFormat(pamP); + + pnm_writepaminit(pamP); + + tuplerow = pnm_allocpamrow(pamP); + + for (row = 0; row < pngInfoP->height; ++row) { + makeTupleRow(pamP, tuplerow, pngInfoP, pngRaster[row], bgColor, + alphaHandling, totalgamma); + + pnm_writepamrow(pamP, tuplerow); + } + pnm_freepamrow(tuplerow); +} + + + +static void +convertpng(FILE * const ifp, + FILE * const tfp, + struct cmdlineInfo const cmdline, + int * const errorlevelP) { + + png_struct * png_ptr; + png_info * info_ptr; + png_byte ** png_image; + pngcolor bgColor; + float totalgamma; + struct pam pam; + + *errorlevelP = 0; + + read_sig_buf(ifp); + + png_ptr = png_create_read_struct( + PNG_LIBPNG_VER_STRING, + &pngtopnm_jmpbuf_struct, pngtopnm_error_handler, NULL); + if (png_ptr == NULL) + pm_error("cannot allocate main libpng structure (png_ptr)"); + + info_ptr = png_create_info_struct (png_ptr); + if (info_ptr == NULL) + pm_error("cannot allocate LIBPNG structures"); + + if (setjmp(pngtopnm_jmpbuf_struct.jmpbuf)) + pm_error ("setjmp returns error condition"); + + png_init_io (png_ptr, ifp); + png_set_sig_bytes (png_ptr, SIG_CHECK_SIZE); + png_read_info (png_ptr, info_ptr); + + allocPngRaster(info_ptr, &png_image); + + if (info_ptr->bit_depth < 8) + png_set_packing (png_ptr); + + setupGammaCorrection(png_ptr, info_ptr, cmdline.gamma, &totalgamma); + + setupSignificantBits(png_ptr, info_ptr, cmdline.alpha, + &maxval, errorlevelP); + + getBackgroundColor(info_ptr, cmdline.background, totalgamma, maxval, + &bgColor); + + png_read_image(png_ptr, png_image); + png_read_end(png_ptr, info_ptr); + + if (verbose) + /* 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. + */ + dump_png_info(info_ptr); + + if (cmdline.time) + show_time(info_ptr); + if (tfp) + save_text(info_ptr, tfp); + + if (info_ptr->valid & PNG_INFO_pHYs) { + float const r = + (float)info_ptr->x_pixels_per_unit / info_ptr->y_pixels_per_unit; + if (r != 1.0) { + pm_message ("warning - non-square pixels; " + "to fix do a 'pamscale -%cscale %g'", + r < 1.0 ? 'x' : 'y', + r < 1.0 ? 1.0 / r : r ); + *errorlevelP = PNMTOPNG_WARNING_LEVEL; + } + } + + pam.size = sizeof(pam); + pam.len = PAM_STRUCT_SIZE(maxval); + pam.file = stdout; + pam.plainformat = 0; + pam.height = info_ptr->height; + pam.width = info_ptr->width; + pam.maxval = maxval; + + determineOutputType(info_ptr, cmdline.alpha, bgColor, maxval, + &pam.format, &pam.depth, pam.tuple_type); + + writeNetpbm(&pam, info_ptr, png_image, bgColor, cmdline.alpha, totalgamma); + + fflush(stdout); + + freePngRaster(png_image, info_ptr); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); +} + + + +int +main(int argc, const char *argv[]) { + + struct cmdlineInfo cmdline; + FILE * ifP; + FILE * tfP; + int errorlevel; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + verbose = cmdline.verbose; + + ifP = pm_openr(cmdline.inputFilespec); + + if (cmdline.text) + tfP = pm_openw(cmdline.text); + else + tfP = NULL; + + convertpng(ifP, tfP, cmdline, &errorlevel); + + if (tfP) + pm_close(tfP); + + pm_close(ifP); + pm_close(stdout); + + return errorlevel; +} diff --git a/converter/other/pngtopnm.c b/converter/other/pngtopnm.c index c7a39df1..8ffff617 100644 --- a/converter/other/pngtopnm.c +++ b/converter/other/pngtopnm.c @@ -16,20 +16,6 @@ ** with lots of bits pasted from libpng.txt by Guy Eric Schalnat */ -/* - BJH 20000408: rename PPM_MAXMAXVAL to PPM_OVERALLMAXVAL - BJH 20000303: fix include statement so dependencies work out right. -*/ -/* GRR 19991203: moved VERSION to new version.h header file */ - -/* GRR 19990713: fixed redundant freeing of png_ptr and info_ptr in setjmp() - * blocks and added "pm_close(ifp)" in each. */ - -/* GRR 19990317: declared "clobberable" automatic variables in convertpng() - * static to fix Solaris/gcc stack-corruption bug. Also installed custom - * error-handler to avoid jmp_buf size-related problems (i.e., jmp_buf - * compiled with one size in libpng and another size here). */ - #ifndef PNMTOPNG_WARNING_LEVEL # define PNMTOPNG_WARNING_LEVEL 0 /* use 0 for backward compatibility, */ #endif /* 2 for warnings (1 == error) */ @@ -39,33 +25,15 @@ #include <png.h> /* includes zlib.h and setjmp.h */ #define VERSION "2.37.4 (5 December 1999) +netpbm" -#include "pnm.h" #include "mallocvar.h" #include "nstring.h" #include "shhopt.h" +#include "pnm.h" typedef struct _jmpbuf_wrapper { jmp_buf jmpbuf; } jmpbuf_wrapper; -/* GRR 19991205: this is used as a test for pre-1999 versions of netpbm and - * pbmplus vs. 1999 or later (in which pm_close was split into two) - */ -#ifdef PBMPLUS_RAWBITS -# define pm_closer pm_close -# define pm_closew pm_close -#endif - -#ifndef TRUE -# define TRUE 1 -#endif -#ifndef FALSE -# define FALSE 0 -#endif -#ifndef NONE -# define NONE 0 -#endif - enum alpha_handling {ALPHA_NONE, ALPHA_ONLY, ALPHA_MIX}; struct cmdlineInfo { @@ -82,7 +50,7 @@ struct cmdlineInfo { }; -typedef struct pngcolor { +typedef struct { /*---------------------------------------------------------------------------- A color in a format compatible with the PNG library. @@ -96,15 +64,14 @@ typedef struct pngcolor { static png_uint_16 maxval; -static int verbose = FALSE; -static int mtime; +static bool verbose; static jmpbuf_wrapper pngtopnm_jmpbuf_struct; static void -parseCommandLine(int argc, - char ** argv, - struct cmdlineInfo *cmdlineP ) { +parseCommandLine(int argc, + const char ** argv, + struct cmdlineInfo * cmdlineP ) { /*---------------------------------------------------------------------------- Parse program command line described in Unix standard form by argc and argv. Return the information in the options as *cmdlineP. @@ -115,7 +82,7 @@ parseCommandLine(int argc, Note that the strings we return are stored in the storage that was passed to us as the argv array. We also trash *argv. -----------------------------------------------------------------------------*/ - optEntry *option_def = malloc(100*sizeof(optEntry)); + optEntry * option_def; /* Instructions to optParseOptions3 on how to parse our options. */ optStruct3 opt; @@ -124,6 +91,8 @@ parseCommandLine(int argc, unsigned int alphaSpec, mixSpec, backgroundSpec, gammaSpec, textSpec; + MALLOCARRAY(option_def, 100); + option_def_index = 0; /* incremented by OPTENT3 */ OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); @@ -144,7 +113,7 @@ parseCommandLine(int argc, 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); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ @@ -180,12 +149,9 @@ parseCommandLine(int argc, - -#define get_png_val(p) _get_png_val (&(p), info_ptr->bit_depth) - static png_uint_16 -_get_png_val (png_byte ** const pp, - int const bit_depth) { +get_png_val(const png_byte ** const pp, + int const bit_depth) { png_uint_16 c; @@ -241,8 +207,8 @@ gamma_correct(png_uint_16 const v, float const g) { if (g != -1.0) - return (png_uint_16) (pow ((double) v / maxval, - (1.0 / g)) * maxval + 0.5); + return (png_uint_16) ROUNDU(pow((double) v / maxval, (1.0 / g)) * + maxval); else return v; } @@ -443,29 +409,108 @@ dump_png_info(png_info *info_ptr) { +static unsigned int +computePngLineSize(png_info * const pngInfoP) { + + unsigned int const bytesPerSample = pngInfoP->bit_depth == 16 ? 2 : 1; + + unsigned int samplesPerPixel; + + switch (pngInfoP->color_type) { + case PNG_COLOR_TYPE_GRAY_ALPHA: samplesPerPixel = 2; break; + case PNG_COLOR_TYPE_RGB: samplesPerPixel = 3; break; + case PNG_COLOR_TYPE_RGB_ALPHA: samplesPerPixel = 4; break; + default: samplesPerPixel = 1; + } + + if (UINT_MAX / bytesPerSample / samplesPerPixel < pngInfoP->width) + pm_error("Width %u of PNG is uncomputably large", + (unsigned int)pngInfoP->width); + + return pngInfoP->width * bytesPerSample * samplesPerPixel; +} + + + +static void +allocPngRaster(png_info * const pngInfoP, + png_byte *** const pngImageP) { + + unsigned int const lineSize = computePngLineSize(pngInfoP); + + png_byte ** pngImage; + unsigned int row; + + MALLOCARRAY(pngImage, pngInfoP->height); + + if (pngImage == NULL) + pm_error("couldn't allocate space for %u PNG raster rows", + (unsigned int)pngInfoP->height); + + for (row = 0; row < pngInfoP->height; ++row) { + MALLOCARRAY(pngImage[row], lineSize); + if (pngImage[row] == NULL) + pm_error("couldn't allocate space for %uth row of PNG raster", + row); + } + *pngImageP = pngImage; +} + + + +static void +freePngRaster(png_byte ** const pngRaster, + png_info * const pngInfoP) { + + unsigned int row; + + for (row = 0; row < pngInfoP->height; ++row) + free(pngRaster[row]); + + free(pngRaster); +} + + + static bool isTransparentColor(pngcolor const color, - png_info * const info_ptr, + png_info * const pngInfoP, double const totalgamma) { /*---------------------------------------------------------------------------- Return TRUE iff pixels of color 'color' are supposed to be transparent everywhere they occur. Assume it's an RGB image. + + 'color' has been gamma-corrected. -----------------------------------------------------------------------------*/ bool retval; - if (info_ptr->valid & PNG_INFO_tRNS) { - const png_color_16 * const transColorP = &info_ptr->trans_values; - + if (pngInfoP->valid & PNG_INFO_tRNS) { + const png_color_16 * const transColorP = &pngInfoP->trans_values; - /* There seems to be a problem here: you can't compare real - numbers for equality. Also, I'm not sure the gamma - corrected/uncorrected color spaces are right here. - */ + /* It seems odd that libpng lets you get gamma-corrected pixel + values, but not gamma-corrected transparency or background + values. But as that is the case, we have to gamma-correct + the transparency values. + + Note that because we compare the gamma-corrected values and + there may be many-to-one mapping of uncorrected to corrected + values, more pixels may be transparent than what the user + intended. - retval = - color.r == gamma_correct(transColorP->red, totalgamma) && - color.g == gamma_correct(transColorP->green, totalgamma) && - color.b == gamma_correct(transColorP->blue, totalgamma); + We could fix this by not letting libpng gamma-correct the + pixels, and just do it ourselves. + */ + + switch (pngInfoP->color_type) { + case PNG_COLOR_TYPE_GRAY: + retval = color.r == gamma_correct(transColorP->gray, totalgamma); + break; + default: + retval = + color.r == gamma_correct(transColorP->red, totalgamma) && + color.g == gamma_correct(transColorP->green, totalgamma) && + color.b == gamma_correct(transColorP->blue, totalgamma); + } } else retval = FALSE; @@ -752,11 +797,11 @@ determineOutputType(png_info * const info_ptr, static void -getBackgroundColor(png_info * const info_ptr, - const char * const requestedColor, - float const totalgamma, - xelval const maxval, - struct pngcolor * const bgColorP) { +getBackgroundColor(png_info * const info_ptr, + const char * const requestedColor, + float const totalgamma, + xelval const maxval, + pngcolor * const bgColorP) { /*---------------------------------------------------------------------------- Figure out what the background color should be. If the user requested a particular color ('requestedColor' not null), that's the one. @@ -809,21 +854,109 @@ getBackgroundColor(png_info * const info_ptr, +#define GET_PNG_VAL(p) get_png_val(&(p), pngInfoP->bit_depth) + + + +static void +makeXelRow(xel * const xelrow, + xelval const maxval, + int const pnmType, + png_info * const pngInfoP, + const png_byte * const pngRasterRow, + pngcolor const bgColor, + enum alpha_handling const alphaHandling, + double const totalgamma) { + + const png_byte * pngPixelP; + unsigned int col; + + pngPixelP = &pngRasterRow[0]; /* initial value */ + for (col = 0; col < pngInfoP->width; ++col) { + switch (pngInfoP->color_type) { + case PNG_COLOR_TYPE_GRAY: { + pngcolor fgColor; + fgColor.r = fgColor.g = fgColor.b = GET_PNG_VAL(pngPixelP); + setXel(&xelrow[col], fgColor, bgColor, alphaHandling, + isTransparentColor(fgColor, pngInfoP, totalgamma) ? + 0 : maxval); + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: { + pngcolor fgColor; + png_uint_16 alpha; + + fgColor.r = fgColor.g = fgColor.b = GET_PNG_VAL(pngPixelP); + alpha = GET_PNG_VAL(pngPixelP); + setXel(&xelrow[col], fgColor, bgColor, alphaHandling, alpha); + } + break; + + case PNG_COLOR_TYPE_PALETTE: { + png_uint_16 const index = GET_PNG_VAL(pngPixelP); + png_color const paletteColor = pngInfoP->palette[index]; + + pngcolor fgColor; + + fgColor.r = paletteColor.red; + fgColor.g = paletteColor.green; + fgColor.b = paletteColor.blue; + + setXel(&xelrow[col], fgColor, bgColor, alphaHandling, + (pngInfoP->valid & PNG_INFO_tRNS) && + index < pngInfoP->num_trans ? + pngInfoP->trans[index] : maxval); + } + break; + + case PNG_COLOR_TYPE_RGB: { + pngcolor fgColor; + + fgColor.r = GET_PNG_VAL(pngPixelP); + fgColor.g = GET_PNG_VAL(pngPixelP); + fgColor.b = GET_PNG_VAL(pngPixelP); + setXel(&xelrow[col], fgColor, bgColor, alphaHandling, + isTransparentColor(fgColor, pngInfoP, totalgamma) ? + 0 : maxval); + } + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: { + pngcolor fgColor; + png_uint_16 alpha; + + fgColor.r = GET_PNG_VAL(pngPixelP); + fgColor.g = GET_PNG_VAL(pngPixelP); + fgColor.b = GET_PNG_VAL(pngPixelP); + alpha = GET_PNG_VAL(pngPixelP); + setXel(&xelrow[col], fgColor, bgColor, alphaHandling, alpha); + } + break; + + default: + pm_error("unknown PNG color type: %d", pngInfoP->color_type); + } + } +} + + + static void writePnm(FILE * const ofP, xelval const maxval, - int const pnm_type, - png_info * const info_ptr, - png_byte ** const png_image, + int const pnmType, + png_info * const pngInfoP, + png_byte ** const pngRaster, pngcolor const bgColor, - enum alpha_handling const alpha_handling, + enum alpha_handling const alphaHandling, double const totalgamma) { /*---------------------------------------------------------------------------- Write a PNM of either the image or the alpha mask, according to - 'alpha_handling' that is in the PNG image described by 'info_ptr' and - png_image. + 'alphaHandling' that is in the PNG image described by 'pngInfoP' and + pngRaster. - 'pnm_type' and 'maxval' are of the output image. + 'pnmType' and 'maxval' are of the output image. Use background color 'bgColor' in the output if the PNG is such that a background color is needed. @@ -832,93 +965,23 @@ writePnm(FILE * const ofP, unsigned int row; if (verbose) - pm_message ("writing a %s file (maxval=%u)", - pnm_type == PBM_TYPE ? "PBM" : - pnm_type == PGM_TYPE ? "PGM" : - pnm_type == PPM_TYPE ? "PPM" : - "UNKNOWN!", - maxval); + pm_message("writing a %s file (maxval=%u)", + pnmType == PBM_TYPE ? "PBM" : + pnmType == PGM_TYPE ? "PGM" : + pnmType == PPM_TYPE ? "PPM" : + "UNKNOWN!", + maxval); - xelrow = pnm_allocrow(info_ptr->width); - - pnm_writepnminit(stdout, info_ptr->width, info_ptr->height, maxval, - pnm_type, FALSE); - - for (row = 0; row < info_ptr->height; ++row) { - png_byte * png_pixelP; - int col; - - png_pixelP = &png_image[row][0]; /* initial value */ - for (col = 0; col < info_ptr->width; ++col) { - switch (info_ptr->color_type) { - case PNG_COLOR_TYPE_GRAY: { - pngcolor fgColor; - fgColor.r = fgColor.g = fgColor.b = get_png_val(png_pixelP); - setXel(&xelrow[col], fgColor, bgColor, alpha_handling, - ((info_ptr->valid & PNG_INFO_tRNS) && - (fgColor.r == - gamma_correct(info_ptr->trans_values.gray, - totalgamma))) ? - 0 : maxval); - } - break; - - case PNG_COLOR_TYPE_GRAY_ALPHA: { - pngcolor fgColor; - png_uint_16 alpha; - - fgColor.r = fgColor.g = fgColor.b = get_png_val(png_pixelP); - alpha = get_png_val(png_pixelP); - setXel(&xelrow[col], fgColor, bgColor, alpha_handling, alpha); - } - break; - - case PNG_COLOR_TYPE_PALETTE: { - png_uint_16 const index = get_png_val(png_pixelP); - png_color const paletteColor = info_ptr->palette[index]; - - pngcolor fgColor; - - fgColor.r = paletteColor.red; - fgColor.g = paletteColor.green; - fgColor.b = paletteColor.blue; - - setXel(&xelrow[col], fgColor, bgColor, alpha_handling, - (info_ptr->valid & PNG_INFO_tRNS) && - index < info_ptr->num_trans ? - info_ptr->trans[index] : maxval); - } - break; - - case PNG_COLOR_TYPE_RGB: { - pngcolor fgColor; - - fgColor.r = get_png_val(png_pixelP); - fgColor.g = get_png_val(png_pixelP); - fgColor.b = get_png_val(png_pixelP); - setXel(&xelrow[col], fgColor, bgColor, alpha_handling, - isTransparentColor(fgColor, info_ptr, totalgamma) ? - 0 : maxval); - } - break; + xelrow = pnm_allocrow(pngInfoP->width); - case PNG_COLOR_TYPE_RGB_ALPHA: { - pngcolor fgColor; - png_uint_16 alpha; + pnm_writepnminit(stdout, pngInfoP->width, pngInfoP->height, maxval, + pnmType, FALSE); - fgColor.r = get_png_val(png_pixelP); - fgColor.g = get_png_val(png_pixelP); - fgColor.b = get_png_val(png_pixelP); - alpha = get_png_val(png_pixelP); - setXel(&xelrow[col], fgColor, bgColor, alpha_handling, alpha); - } - break; + for (row = 0; row < pngInfoP->height; ++row) { + makeXelRow(xelrow, maxval, pnmType, pngInfoP, pngRaster[row], bgColor, + alphaHandling, totalgamma); - default: - pm_error ("unknown PNG color type: %d", info_ptr->color_type); - } - } - pnm_writepnmrow(ofP, xelrow, info_ptr->width, maxval, pnm_type, FALSE); + pnm_writepnmrow(ofP, xelrow, pngInfoP->width, maxval, pnmType, FALSE); } pnm_freerow (xelrow); } @@ -931,11 +994,9 @@ convertpng(FILE * const ifp, struct cmdlineInfo const cmdline, int * const errorlevelP) { - png_struct *png_ptr; - png_info *info_ptr; - png_byte **png_image; - int x, y; - int linesize; + png_struct * png_ptr; + png_info * info_ptr; + png_byte ** png_image; int pnm_type; pngcolor bgColor; float totalgamma; @@ -961,38 +1022,7 @@ convertpng(FILE * const ifp, png_set_sig_bytes (png_ptr, SIG_CHECK_SIZE); png_read_info (png_ptr, info_ptr); - MALLOCARRAY(png_image, info_ptr->height); - if (png_image == NULL) { - png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); - pm_closer (ifp); - pm_error ("couldn't allocate space for image"); - } - - if (info_ptr->bit_depth == 16) - linesize = 2 * info_ptr->width; - else - linesize = info_ptr->width; - - if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - linesize *= 2; - else - if (info_ptr->color_type == PNG_COLOR_TYPE_RGB) - linesize *= 3; - else - if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - linesize *= 4; - - for (y = 0 ; y < info_ptr->height ; y++) { - png_image[y] = malloc (linesize); - if (png_image[y] == NULL) { - for (x = 0 ; x < y ; x++) - free (png_image[x]); - free (png_image); - png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); - pm_closer (ifp); - pm_error ("couldn't allocate space for image"); - } - } + allocPngRaster(info_ptr, &png_image); if (info_ptr->bit_depth < 8) png_set_packing (png_ptr); @@ -1005,24 +1035,24 @@ convertpng(FILE * const ifp, getBackgroundColor(info_ptr, cmdline.background, totalgamma, maxval, &bgColor); - png_read_image (png_ptr, png_image); - png_read_end (png_ptr, info_ptr); + png_read_image(png_ptr, png_image); + png_read_end(png_ptr, info_ptr); if (verbose) /* 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. - */ + completes. That's because it comes from chunks that are at the + end of the stream. + */ dump_png_info(info_ptr); - if (mtime) - show_time (info_ptr); + if (cmdline.time) + show_time(info_ptr); if (tfp) - save_text (info_ptr, tfp); + save_text(info_ptr, tfp); if (info_ptr->valid & PNG_INFO_pHYs) { - float r; - r = (float)info_ptr->x_pixels_per_unit / info_ptr->y_pixels_per_unit; + float const r = + (float)info_ptr->x_pixels_per_unit / info_ptr->y_pixels_per_unit; if (r != 1.0) { pm_message ("warning - non-square pixels; " "to fix do a 'pamscale -%cscale %g'", @@ -1038,41 +1068,41 @@ convertpng(FILE * const ifp, cmdline.alpha, totalgamma); fflush(stdout); - for (y = 0 ; y < info_ptr->height ; y++) - free (png_image[y]); - free (png_image); - png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); + + freePngRaster(png_image, info_ptr); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); } int -main(int argc, char *argv[]) { +main(int argc, const char *argv[]) { struct cmdlineInfo cmdline; - FILE *ifp, *tfp; + FILE * ifP; + FILE * tfP; int errorlevel; - pnm_init (&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); verbose = cmdline.verbose; - mtime = cmdline.time; - ifp = pm_openr(cmdline.inputFilespec); + ifP = pm_openr(cmdline.inputFilespec); if (cmdline.text) - tfp = pm_openw(cmdline.text); + tfP = pm_openw(cmdline.text); else - tfp = NULL; + tfP = NULL; - convertpng (ifp, tfp, cmdline, &errorlevel); + convertpng(ifP, tfP, cmdline, &errorlevel); - if (tfp) - pm_close(tfp); + if (tfP) + pm_close(tfP); - pm_close(ifp); + pm_close(ifP); pm_close(stdout); return errorlevel; diff --git a/converter/other/pnmtopng.c b/converter/other/pnmtopng.c index b339a1fe..72177507 100644 --- a/converter/other/pnmtopng.c +++ b/converter/other/pnmtopng.c @@ -1032,7 +1032,7 @@ findRedundantBits(FILE * const ifp, /*---------------------------------------------------------------------------- Find out if we can use just a subset of the bits from each input sample. Often, people create an image with e.g. 8 bit samples from - one that has e.g. only 4 bit samples by scaling by 256/16, which is + one that has e.g. only 4 bit samples by scaling by 255/15, which is the same as repeating the bits. E.g. 1011 becomes 10111011. We detect this case. We return as *meaningfulBitsP the minimum number of bits, starting from the least significant end, that contain @@ -2014,7 +2014,7 @@ createPngPalette(pixel palette_pnm[], for (i = 0; i < transSize; ++i) { unsigned int const newmv = PALETTEMAXVAL; unsigned int const oldmv = alpha_maxval; - trans[i] = (trans_pnm[i] * newmv + (oldmv/2)) / oldmv; + trans[i] = ROUNDDIV(trans_pnm[i] * newmv, oldmv); } } @@ -2369,7 +2369,7 @@ convertpnm(struct cmdlineInfo const cmdline, */ unsigned int fulldepth; /* The total number of bits per pixel in the (uncompressed) png - raster, including all channels + raster, including all channels. */ pm_filepos rasterPos; /* file position in input image file of start of image (i.e. after @@ -2442,8 +2442,8 @@ convertpnm(struct cmdlineInfo const cmdline, to ppm_parsecolor() because ppm_parsecolor() does a cheap maxval scaling, and this is more precise. */ - PPM_DEPTH (transcolor, ppm_parsecolor(transstring2, maxmaxval), - maxmaxval, maxval); + PPM_DEPTH(transcolor, ppm_parsecolor(transstring2, maxmaxval), + maxmaxval, maxval); } if (cmdline.alpha) { pixel alpha_transcolor; diff --git a/converter/other/x11wd.h b/converter/other/x11wd.h index 711248f5..7161260b 100644 --- a/converter/other/x11wd.h +++ b/converter/other/x11wd.h @@ -27,7 +27,7 @@ enum visualclass {StaticGray=0,GrayScale=1,StaticColor=2,PseudoColor=3, #define DirectColor 5 */ -typedef uint32n xwdval; +typedef uint32_t xwdval; #define XWDVAL_MAX ((xwdval)(-1)) #define X11WD_FILE_VERSION 7 typedef struct { @@ -67,13 +67,13 @@ typedef struct { */ xwdval window_width; /* Window width */ xwdval window_height; /* Window height */ - int32n window_x; /* Window upper left X coordinate */ - int32n window_y; /* Window upper left Y coordinate */ + int32_t window_x; /* Window upper left X coordinate */ + int32_t window_y; /* Window upper left Y coordinate */ xwdval window_bdrwidth; /* Window border width */ } X11WDFileHeader; typedef struct { - uint32n num; + uint32_t num; unsigned short red, green, blue; char flags; /* do_red, do_green, do_blue */ char pad; diff --git a/converter/pbm/g3topbm.c b/converter/pbm/g3topbm.c index 261b6c39..2d2c6a42 100644 --- a/converter/pbm/g3topbm.c +++ b/converter/pbm/g3topbm.c @@ -26,6 +26,10 @@ #include "mallocvar.h" #include "g3.h" #include "bitreverse.h" +#include "bitarith.h" + +#define LEFTBITS pm_byteLeftBits +#define RIGHTBITS pm_byteRightBits #define MAXCOLS 10800 #define MAXROWS 14400 /* this allows up to two pages of image */ @@ -297,12 +301,12 @@ buildHashes(g3TableEntry * (*whashP)[HASHSIZE], static void -makeRowWhite(bit * const bitrow, - unsigned int const cols) { +makeRowWhite(unsigned char * const packedBitrow, + unsigned int const cols) { - unsigned int col; - for (col = 0; col < MAXCOLS; ++col) - bitrow[col] = PBM_WHITE; + unsigned int colByte; + for (colByte = 0; colByte < pbm_packed_bytes(cols); ++colByte) + packedBitrow[colByte] = PBM_WHITE * 0xff; } @@ -335,16 +339,45 @@ g3code(unsigned int const curcode, -enum g3tableId {TERMWHITE, TERMBLACK, MKUPWHITE, MKUPBLACK}; +static void +writeBlackBitSpan(unsigned char * const packedBitrow, + int const cols, + int const offset) { +/*---------------------------------------------------------------------------- + Write black (="1") bits into packedBitrow[], starting at 'offset', + length 'cols'. +-----------------------------------------------------------------------------*/ + unsigned char * const dest = & packedBitrow[offset/8]; + unsigned int const rs = offset % 8; + unsigned int const trs = (cols + rs) % 8; + unsigned int const colBytes = pbm_packed_bytes(cols + rs); + unsigned int const last = colBytes - 1; + + unsigned char const origHead = dest[0]; + unsigned char const origEnd = 0x00; + unsigned int i; + for( i = 0; i < colBytes; ++i) + dest[i] = PBM_BLACK * 0xff; + + if (rs > 0) + dest[0] = LEFTBITS(origHead, rs) | RIGHTBITS(dest[0], 8-rs); + + if (trs > 0) + dest[last] = LEFTBITS(dest[last], trs) | RIGHTBITS(origEnd, 8-trs); +} + + + +enum g3tableId {TERMWHITE, TERMBLACK, MKUPWHITE, MKUPBLACK}; static void -processG3Code(g3TableEntry * const teP, - bit * const bitrow, - unsigned int * const colP, - bit * const colorP, - unsigned int * const countP) { +processG3Code(const g3TableEntry * const teP, + unsigned char * const packedBitrow, + unsigned int * const colP, + bit * const colorP, + unsigned int * const countP) { enum g3tableId const teId = (teP > mtable ? 2 : 0) + (teP - ttable) % 2; @@ -368,14 +401,10 @@ processG3Code(g3TableEntry * const teP, runLengthSoFar = MIN(*countP + teCount, MAXCOLS - col); if (runLengthSoFar > 0) { - if (*colorP == PBM_WHITE) { - /* Row was initialized to white, so we just skip */ - col += runLengthSoFar; - } else { - unsigned int i; - for (i = 0; i < runLengthSoFar; ++i) - bitrow[col++] = PBM_BLACK; - } + if (*colorP == PBM_BLACK) + writeBlackBitSpan(packedBitrow, runLengthSoFar, col); + /* else : Row was initialized to white, so we just skip */ + col += runLengthSoFar; } *colorP = !*colorP; *countP = 0; @@ -410,13 +439,13 @@ formatBadCodeException(const char ** const exceptionP, static void readFaxRow(struct bitStream * const bitStreamP, - bit * const bitrow, + unsigned char * const packedBitrow, unsigned int * const lineLengthP, const char ** const exceptionP, const char ** const errorP) { /*---------------------------------------------------------------------------- Read one line of G3 fax from the bit stream *bitStreamP into - bitrow[]. Return the length of the line, in pixels, as *lineLengthP. + packedBitrow[]. Return the length of the line, in pixels, as *lineLengthP. If there's a problem with the line, return as much of it as we can, advance the input stream past the next EOL mark, and put a text @@ -440,11 +469,9 @@ readFaxRow(struct bitStream * const bitStreamP, /* Number of consecutive pixels of the same color */ bit currentColor; /* The color of the current run of pixels */ - g3TableEntry * te; - /* Address of structure that describes the current G3 code */ bool done; - makeRowWhite(bitrow, MAXCOLS); /* initialize row */ + makeRowWhite(packedBitrow, MAXCOLS); /* initialize row */ col = 0; curlen = 0; @@ -485,10 +512,14 @@ readFaxRow(struct bitStream * const bitStreamP, formatBadCodeException(exceptionP, col, curlen, curcode); done = TRUE; } else if (curcode != 0) { - te = g3code(curcode, curlen, currentColor); - - if (te) { - processG3Code(te, bitrow, &col, ¤tColor, &count); + const g3TableEntry * const teP = + g3code(curcode, curlen, currentColor); + /* Address of structure that describes the + current G3 code + */ + if (teP) { + processG3Code(teP, packedBitrow, + &col, ¤tColor, &count); curcode = 0; curlen = 0; @@ -506,9 +537,9 @@ readFaxRow(struct bitStream * const bitStreamP, static void -freeBits(bit ** const bits, - unsigned int const rows, - bool const stretched) { +freeBits(unsigned char ** const packedBits, + unsigned int const rows, + bool const stretched) { unsigned int row; @@ -518,9 +549,9 @@ freeBits(bit ** const bits, free it twice. */ } else - pbm_freerow(bits[row]); + pbm_freerow_packed(packedBits[row]); } - free(bits); + free(packedBits); } @@ -638,17 +669,17 @@ readFax(struct bitStream * const bitStreamP, bool const stretch, unsigned int const expectedLineSize, bool const tolerateErrors, - bit *** const bitsP, + unsigned char *** const packedBitsP, unsigned int * const colsP, unsigned int * const rowsP) { lineSizeAnalyzer lineSizeAnalyzer; - bit ** bits; + unsigned char ** packedBits; const char * error; bool eof; unsigned int row; - MALLOCARRAY_NOFAIL(bits, MAXROWS); + MALLOCARRAY_NOFAIL(packedBits, MAXROWS); initializeLineSizeAnalyzer(&lineSizeAnalyzer, expectedLineSize, tolerateErrors); @@ -666,8 +697,9 @@ readFax(struct bitStream * const bitStreamP, else { const char * exception; - bits[row] = pbm_allocrow(MAXCOLS); - readFaxRow(bitStreamP, bits[row], &lineSize, &exception, &error); + packedBits[row] = pbm_allocrow_packed(MAXCOLS); + readFaxRow(bitStreamP, packedBits[row], + &lineSize, &exception, &error); handleRowException(exception, error, row, tolerateErrors); @@ -685,16 +717,16 @@ readFax(struct bitStream * const bitStreamP, "program can handle at most %u rows " "after stretching", MAXROWS); else - bits[row] = bits[row-1]; + packedBits[row] = packedBits[row-1]; } ++row; } } } } - *rowsP = row; - *colsP = lineSizeAnalyzer.maxLineSize; - *bitsP = bits; + *rowsP = row; + *colsP = lineSizeAnalyzer.maxLineSize; + *packedBitsP = packedBits; } @@ -706,7 +738,8 @@ main(int argc, char * argv[]) { FILE * ifP; struct bitStream bitStream; unsigned int rows, cols; - bit ** bits; + unsigned char ** packedBits; + int row; pbm_init(&argc, argv); @@ -728,14 +761,17 @@ main(int argc, char * argv[]) { readFax(&bitStream, cmdline.stretch, cmdline.expectedLineSize, !cmdline.stop_error, - &bits, &cols, &rows); + &packedBits, &cols, &rows); pm_close(ifP); - pbm_writepbm(stdout, bits, cols, rows, 0); + pbm_writepbminit(stdout, cols, rows, 0); + for (row = 0; row < rows; ++row) + pbm_writepbmrow_packed(stdout, packedBits[row], cols, 0); + pm_close(stdout); - freeBits(bits, rows, cmdline.stretch); + freeBits(packedBits, rows, cmdline.stretch); return 0; } diff --git a/converter/pbm/pbmtodjvurle.c b/converter/pbm/pbmtodjvurle.c index dbe96f31..83e99ec4 100644 --- a/converter/pbm/pbmtodjvurle.c +++ b/converter/pbm/pbmtodjvurle.c @@ -50,91 +50,97 @@ writebyte(FILE * const ofP, /* Write a run length to the RLE file. */ static void -write_rle (FILE *rlefile, uint32n tally) -{ - do { - /* Output a single run. */ - if (tally < 192) { - /* Single-byte runs */ - writebyte (rlefile, tally); - tally >>= 8; +write_rle(FILE * const rlefile, + uint32_t const tallyArg) { + + uint32_t remainingTally; + + remainingTally = tallyArg; /* initial value */ + + do { + /* Output a single run. */ + if (remainingTally < 192) { + /* Single-byte runs */ + writebyte (rlefile, remainingTally); + remainingTally >>= 8; + } + else { + /* Two-byte runs */ + writebyte (rlefile, ((remainingTally>>8) & 0x3F) + 0xC0); + writebyte (rlefile, remainingTally & 0xFF); + remainingTally >>= 14; + } + + /* Very large runs need to be split into smaller runs. We + therefore need to toggle back to the same color we had for the + previous smaller run. + */ + if (remainingTally > 0) + writebyte (rlefile, 0); } - else { - /* Two-byte runs */ - writebyte (rlefile, ((tally>>8)&0x3F) + 0xC0); - writebyte (rlefile, tally&0xFF); - tally >>= 14; - } - - /* Very large runs need to be split into smaller runs. We - * therefore need to toggle back to the same color we had for the - * previous smaller run. */ - if (tally > 0) - writebyte (rlefile, 0); - } - while (tally > 0); + while (remainingTally > 0); } int -main (int argc, char *argv[]) -{ - FILE * const rlefile = stdout; /* Generated Bitonal RLE file */ - - FILE *pbmfile; /* PBM file to convert */ - int numcols, numrows; /* Width and height in pixels of the PBM file */ - int format; /* Original image type before conversion to PBM */ - bit *pbmrow; /* One row of the PBM file */ - uint32n pixeltally = 0; /* Run length of the current color */ - int row, col; /* Row and column loop variables */ - const char * pbmfilename; /* Name of input file */ - - /* Parse the command line. */ - pbm_init (&argc, argv); - - if (argc-1 < 1) - pbmfilename = "-"; - else if (argc-1 == 1) - pbmfilename = argv[1]; - else - pm_error("Program takes at most 1 argument -- the input file name. " - "You specified %d", argc-1); - - pbmfile = pm_openr(pbmfilename); - - /* Write an RLE header. */ - pbm_readpbminit (pbmfile, &numcols, &numrows, &format); - fprintf (rlefile, "R4\n"); - fprintf (rlefile, "%d %d\n", numcols, numrows); - - /* Write the RLE data. */ - pbmrow = pbm_allocrow (numcols); - for (row=0; row<numrows; row++) { - bit prevpixel; /* Previous pixel seen */ - - pbm_readpbmrow (pbmfile, pbmrow, numcols, format); - prevpixel = PBM_WHITE; /* Bitonal RLE rows always start with white */ - pixeltally = 0; - for (col=0; col<numcols; col++) { - bit newpixel = pbmrow[col]; /* Current pixel color */ - - if (newpixel == prevpixel) - pixeltally++; - else { - write_rle (rlefile, pixeltally); - pixeltally = 1; - prevpixel = newpixel; - } +main (int argc, const char * argv[]) { + + FILE * const rlefile = stdout; /* Generated Bitonal RLE file */ + + FILE * pbmfile; /* PBM file to convert */ + int numcols, numrows; /* Width and height in pixels of the PBM file */ + int format; /* Original image type before conversion to PBM */ + bit * pbmrow; /* One row of the PBM file */ + unsigned int row; + const char * pbmfilename; /* Name of input file */ + + pm_proginit(&argc, argv); + + if (argc-1 < 1) + pbmfilename = "-"; + else if (argc-1 == 1) + pbmfilename = argv[1]; + else + pm_error("Program takes at most 1 argument -- the input file name. " + "You specified %d", argc-1); + + pbmfile = pm_openr(pbmfilename); + + /* Write an RLE header. */ + pbm_readpbminit(pbmfile, &numcols, &numrows, &format); + fprintf(rlefile, "R4\n"); + fprintf(rlefile, "%d %d\n", numcols, numrows); + + /* Write the RLE data. */ + pbmrow = pbm_allocrow(numcols); + for (row = 0; row < numrows; ++row) { + unsigned int col; + uint32_t pixeltally; /* Run length of the current color */ + bit prevpixel; /* Previous pixel seen */ + + pbm_readpbmrow(pbmfile, pbmrow, numcols, format); + prevpixel = PBM_WHITE; /* Bitonal RLE rows always start with white */ + pixeltally = 0; + for (col = 0; col < numcols; ++col) { + bit newpixel = pbmrow[col]; /* Current pixel color */ + + if (newpixel == prevpixel) + ++pixeltally; + else { + write_rle(rlefile, pixeltally); + pixeltally = 1; + prevpixel = newpixel; + } + } + write_rle(rlefile, pixeltally); } - write_rle (rlefile, pixeltally); - } - - /* Finish up cleanly. */ - pbm_freerow (pbmrow); - if (rlefile != stdout) - pm_close (rlefile); - if (pbmfile != stdin) - pm_close (pbmfile); - exit (0); + + pbm_freerow(pbmrow); + if (rlefile != stdout) + pm_close(rlefile); + if (pbmfile != stdin) + pm_close(pbmfile); + + return 0; } diff --git a/converter/ppm/ilbmtoppm.c b/converter/ppm/ilbmtoppm.c index f9f9bac3..8bb72662 100644 --- a/converter/ppm/ilbmtoppm.c +++ b/converter/ppm/ilbmtoppm.c @@ -1252,7 +1252,7 @@ dcol_to_ppm(FILE * const ifP, unsigned int const greenplanes = dcol->g; unsigned int const blueplanes = dcol->b; - int col, row, i; + int col, row; rawtype *Rrow, *Grow, *Brow; pixval maxval, redmaxval, greenmaxval, bluemaxval; pixval *redtable, *greentable, *bluetable; @@ -1298,13 +1298,15 @@ dcol_to_ppm(FILE * const ifP, MALLOCARRAY_NOFAIL(greentable, greenmaxval +1); MALLOCARRAY_NOFAIL(bluetable, bluemaxval +1); - for( i = 0; i <= redmaxval; i++ ) - redtable[i] = (i * maxval + redmaxval/2)/redmaxval; - for( i = 0; i <= greenmaxval; i++ ) - greentable[i] = (i * maxval + greenmaxval/2)/greenmaxval; - for( i = 0; i <= bluemaxval; i++ ) - bluetable[i] = (i * maxval + bluemaxval/2)/bluemaxval; - + { + unsigned int i; + for (i = 0; i <= redmaxval; ++i) + redtable[i] = ROUNDDIV(i * maxval, redmaxval); + for (i = 0; i <= greenmaxval; ++i) + greentable[i] = ROUNDDIV(i * maxval, greenmaxval); + for (i = 0; i <= bluemaxval; ++i) + bluetable[i] = ROUNDDIV(i * maxval, bluemaxval); + } if( transpName ) { MALLOCVAR_NOFAIL(transpColor); *transpColor = ppm_parsecolor(transpName, maxval); diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c index 079f07ca..6f34dae4 100644 --- a/converter/ppm/picttoppm.c +++ b/converter/ppm/picttoppm.c @@ -727,43 +727,39 @@ load_fontdir(const char * const dirfile) { Load the font directory from file named 'dirfile'. Add its contents to the global list of fonts 'fontlist'. -----------------------------------------------------------------------------*/ - int retval; - FILE * fp; + FILE * ifP; + unsigned int nFont; + char line[1024]; - fp = fopen(dirfile, "rb"); - if (!fp) - retval = -1; - else { - unsigned int nFont; - char line[1024]; - - nFont = 0; - while (fgets(line, 1024, fp) && nFont < INT_MAX) { - const char * token[10]; - unsigned int nToken; - - tokenize(line, token, ARRAY_SIZE(token), &nToken); - - if (nToken == 0) { - /* blank line - ignore */ - } else if (token[0][0] == '#') { - /* comment - ignore */ - } else if (nToken != 4) { - /* Unrecognized format - ignore */ - } else { - struct fontinfo * fontinfoP; - - parseFontLine(token, &fontinfoP); - - fontinfoP->next = 0; - *fontlist_ins = fontinfoP; - fontlist_ins = &fontinfoP->next; - ++nFont; - } + ifP = pm_openr(dirfile); + + nFont = 0; + while (fgets(line, 1024, ifP) && nFont < INT_MAX) { + const char * token[10]; + unsigned int nToken; + + tokenize(line, token, ARRAY_SIZE(token), &nToken); + + if (nToken == 0) { + /* blank line - ignore */ + } else if (token[0][0] == '#') { + /* comment - ignore */ + } else if (nToken != 4) { + /* Unrecognized format - ignore */ + } else { + struct fontinfo * fontinfoP; + + parseFontLine(token, &fontinfoP); + + fontinfoP->next = 0; + *fontlist_ins = fontinfoP; + fontlist_ins = &fontinfoP->next; + ++nFont; } - retval = nFont; } - return retval; + pm_close(ifP); + + return nFont; } @@ -1112,7 +1108,7 @@ static pixval redepth(pixval const c, pixval const oldMaxval) { - return (c * PPM_MAXMAXVAL + oldMaxval / 2) / oldMaxval; + return ROUNDDIV(c * PPM_MAXMAXVAL, oldMaxval); } diff --git a/converter/ppm/ppmtoarbtxt.c b/converter/ppm/ppmtoarbtxt.c index 9817f183..df859c84 100644 --- a/converter/ppm/ppmtoarbtxt.c +++ b/converter/ppm/ppmtoarbtxt.c @@ -341,9 +341,7 @@ read_skeleton(const char * const filename, { if (slen > 0 && (skl[nskl] = save_bin_data(slen,line)) != NULL) ++nskl; \ slen = 0; } - sklfile = fopen(filename,"r"); - if (sklfile == NULL) - return -1; + sklfile = pm_openr(filename); /* Parse skeleton file */ nskl = 0; /* initial value */ diff --git a/converter/ppm/ppmtoilbm.c b/converter/ppm/ppmtoilbm.c index c0d58edb..4a1b5cb7 100644 --- a/converter/ppm/ppmtoilbm.c +++ b/converter/ppm/ppmtoilbm.c @@ -433,14 +433,14 @@ compute_ham_cmap(cols, rows, maxval, maxcolors, colorsP, hbits) tmp = hmap[i].b - b; dist += tmp * tmp; if( dist <= maxdist ) { - int sum = hmap[i].count + hmap[col].count; - - hmap[i].r = (hmap[i].r * hmap[i].count + - r * hmap[col].count + sum/2)/sum; - hmap[i].g = (hmap[i].g * hmap[i].count + - g * hmap[col].count + sum/2)/sum; - hmap[i].b = (hmap[i].b * hmap[i].count + - b * hmap[col].count + sum/2)/sum; + unsigned int sum = hmap[i].count + hmap[col].count; + + hmap[i].r = ROUNDDIV(hmap[i].r * hmap[i].count + + r * hmap[col].count, sum); + hmap[i].g = ROUNDDIV(hmap[i].g * hmap[i].count + + g * hmap[col].count, sum); + hmap[i].b = ROUNDDIV(hmap[i].b * hmap[i].count + + b * hmap[col].count, sum); hmap[i].count = sum; hmap[col] = hmap[i]; /* temp store */ @@ -1776,12 +1776,12 @@ static int * make_val_table(oldmaxval, newmaxval) int oldmaxval, newmaxval; { - int i; - int *table; + unsigned int i; + int * table; MALLOCARRAY_NOFAIL(table, oldmaxval + 1); - for(i = 0; i <= oldmaxval; i++ ) - table[i] = (i * newmaxval + oldmaxval/2) / oldmaxval; + for (i = 0; i <= oldmaxval; ++i) + table[i] = ROUNDDIV(i * newmaxval, oldmaxval); return table; } diff --git a/converter/ppm/ppmtompeg/headers/param.h b/converter/ppm/ppmtompeg/headers/param.h index 31be61ee..c7f57b44 100644 --- a/converter/ppm/ppmtompeg/headers/param.h +++ b/converter/ppm/ppmtompeg/headers/param.h @@ -1,30 +1,4 @@ -/*===========================================================================* - * param.h * - * * - * reading the parameter file * - * * - *===========================================================================*/ - -/* - * Copyright (c) 1995 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement is - * hereby granted, provided that the above copyright notice and the following - * two paragraphs appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF - * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ +/* COPYRIGHT information is at end of file */ #include "pm_c_util.h" #include "ansi.h" @@ -35,14 +9,21 @@ * CONSTANTS * *===========*/ -#define MAX_MACHINES 256 +#define MAX_MACHINES 256 #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif -#define ENCODE_FRAMES 0 -#define COMBINE_GOPS 1 -#define COMBINE_FRAMES 2 +typedef enum { + ENCODE_FRAMES, + /* The regular, default function: Input is individual single unencoded + frames. + */ + COMBINE_GOPS, + /* Input is pre-encoded GOPs */ + COMBINE_FRAMES + /* Input is pre-encoded individual frames */ +} majorProgramFunction; struct params { @@ -53,9 +34,9 @@ struct params { void -ReadParamFile(const char * const fileName, - int const function, - struct params * const paramP); +ReadParamFile(const char * const fileName, + majorProgramFunction const function, + struct params * const paramP); /*==================* * GLOBAL VARIABLES * @@ -63,25 +44,47 @@ ReadParamFile(const char * const fileName, /* All this stuff ought to be in a struct param instead */ -extern char outputFileName[256]; -extern int whichGOP; +extern char outputFileName[256]; +extern int whichGOP; extern int numMachines; -extern char machineName[MAX_MACHINES][256]; -extern char userName[MAX_MACHINES][256]; -extern char executable[MAX_MACHINES][1024]; -extern char remoteParamFile[MAX_MACHINES][1024]; -extern boolean remote[MAX_MACHINES]; -extern char currentPath[MAXPATHLEN]; -extern char currentFramePath[MAXPATHLEN]; -extern char currentGOPPath[MAXPATHLEN]; +extern char machineName[MAX_MACHINES][256]; +extern char userName[MAX_MACHINES][256]; +extern char executable[MAX_MACHINES][1024]; +extern char remoteParamFile[MAX_MACHINES][1024]; +extern boolean remote[MAX_MACHINES]; +extern char currentPath[MAXPATHLEN]; +extern char currentFramePath[MAXPATHLEN]; +extern char currentGOPPath[MAXPATHLEN]; extern char inputConversion[1024]; extern char yuvConversion[256]; -extern int yuvWidth, yuvHeight; -extern int realWidth, realHeight; +extern int yuvWidth, yuvHeight; +extern int realWidth, realHeight; extern char ioConversion[1024]; extern char slaveConversion[1024]; -extern FILE *bitRateFile; +extern FILE * bitRateFile; extern boolean showBitRatePerFrame; extern boolean computeMVHist; extern const double VidRateNum[9]; extern boolean keepTempFiles; + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/converter/ppm/ppmtompeg/param.c b/converter/ppm/ppmtompeg/param.c index 502aee5b..bb5bc79a 100644 --- a/converter/ppm/ppmtompeg/param.c +++ b/converter/ppm/ppmtompeg/param.c @@ -934,26 +934,21 @@ processParamLine(char const input[], -/*===========================================================================* - * - * ReadParamFile - * - * read the parameter file - * function is ENCODE_FRAMES, COMBINE_GOPS, or COMBINE_FRAMES, and - * will slightly modify the procedure's behavior as to what it - * is looking for in the parameter file - * - * SIDE EFFECTS: sets parameters accordingly, as well as machine info for - * parallel execution and input file names - * - *===========================================================================*/ void -ReadParamFile(const char * const fileName, - int const function, - struct params * const paramP) { +ReadParamFile(const char * const fileName, + majorProgramFunction const function, + struct params * const paramP) { +/*---------------------------------------------------------------------------- + Read the parameter file 'fileName' as *paramP. - FILE *fpointer; - char buffer[256]; + 'function' slightly modifies our behavior as to what it is looking for + in the parameter file. + + As a side effect, set machine info for parallel execution and input + file names +-----------------------------------------------------------------------------*/ + FILE * fpointer; + char buffer[256]; bool yuvUsed; struct inputSource * inputSourceP; /* Contents of INPUT section */ diff --git a/converter/ppm/ppmtompeg/ppmtompeg.c b/converter/ppm/ppmtompeg/ppmtompeg.c index f4473e07..f53ffea9 100644 --- a/converter/ppm/ppmtompeg/ppmtompeg.c +++ b/converter/ppm/ppmtompeg/ppmtompeg.c @@ -97,7 +97,7 @@ void init_fdct _ANSI_ARGS_((void)); struct cmdlineInfo { bool childProcess; - int function; + majorProgramFunction function; const char * masterHostname; int masterPortNumber; unsigned int outputFrames; @@ -129,36 +129,33 @@ parseArgs(int const argc, /* parse the arguments */ idx = 1; - while ( idx < argc-1 ) { - if ( argv[idx][0] != '-' ) + while (idx < argc-1) { + if (argv[idx][0] != '-') pm_error("argument '%s', which must be an option because " "it is not the last argument, " "does not start with '-'", argv[idx]); - if ( strcmp(argv[idx], "-stat") == 0 ) { - if ( idx+1 < argc-1 ) { + if (streq(argv[idx], "-stat")) { + if (idx+1 < argc-1) { SetStatFileName(argv[idx+1]); idx += 2; - } else { + } else pm_error("Invalid -stat option"); - } - } else if ( strcmp(argv[idx], "-gop") == 0 ) { - if ((cmdlineP->function != ENCODE_FRAMES) || - (cmdlineP->specificFrames)) + } else if (streq(argv[idx], "-gop")) { + if (cmdlineP->function != ENCODE_FRAMES || + cmdlineP->specificFrames) pm_error("Invalid -gop option"); - if ( idx+1 < argc-1 ) { + if (idx+1 < argc-1) { whichGOP = atoi(argv[idx+1]); idx += 2; - } else { + } else pm_error("Invalid -gop option"); - } - } else if ( strcmp(argv[idx], "-frames") == 0 ) { - if ( (cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) ) { + } else if (streq(argv[idx], "-frames")) { + if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1) pm_error("invalid -frames option"); - } - if ( idx+2 < argc-1 ) { + if (idx+2 < argc-1) { int const frameStart = atoi(argv[idx+1]); int const frameEnd = atoi(argv[idx+2]); @@ -176,23 +173,23 @@ parseArgs(int const argc, idx += 3; } else pm_error("-frames needs to be followed by two values"); - } else if (strcmp(argv[idx], "-combine_gops") == 0) { - if ((cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) || - (cmdlineP->specificFrames)) { + } else if (streq(argv[idx], "-combine_gops")) { + if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1 || + cmdlineP->specificFrames) { pm_error("Invalid -combine_gops option"); } cmdlineP->function = COMBINE_GOPS; - idx++; - } else if (strcmp(argv[idx], "-combine_frames") == 0) { - if ((cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) || - (cmdlineP->specificFrames)) + ++idx; + } else if (streq(argv[idx], "-combine_frames")) { + if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1 || + cmdlineP->specificFrames) pm_error("Invalid -combine_frames option"); cmdlineP->function = COMBINE_FRAMES; - idx++; - } else if ( strcmp(argv[idx], "-child") == 0 ) { - if ( idx+7 < argc-1 ) { + ++idx; + } else if (streq(argv[idx], "-child")) { + if (idx+7 < argc-1) { int combinePortNumber; /* This used to be important information, when the child notified the combine server. Now the master notifies @@ -214,104 +211,94 @@ parseArgs(int const argc, cmdlineP->childProcess = TRUE; idx += 8; - } else if ( strcmp(argv[idx], "-io_server") == 0 ) { - if ( idx+2 < argc-1 ) { - cmdlineP->masterHostname = argv[idx+1]; + } else if (streq(argv[idx], "-io_server")) { + if (idx+2 < argc-1) { + cmdlineP->masterHostname = argv[idx+1]; cmdlineP->masterPortNumber = atoi(argv[idx+2]); - } else { + } else pm_error("Invalid -io_server option"); - } ioServer = TRUE; idx += 3; - } else if ( strcmp(argv[idx], "-output_server") == 0 ) { - if ( idx+3 < argc-1 ) { - cmdlineP->masterHostname = argv[idx+1]; + } else if (streq(argv[idx], "-output_server")) { + if (idx+3 < argc-1) { + cmdlineP->masterHostname = argv[idx+1]; cmdlineP->masterPortNumber = atoi(argv[idx+2]); - cmdlineP->outputFrames = atoi(argv[idx+3]); - } else { + cmdlineP->outputFrames = atoi(argv[idx+3]); + } else pm_error("-output_server option requires 3 option values. " - "You specified %d", argc-1 - idx); - } + "You specified %u", argc-1 - idx); outputServer = TRUE; idx += 4; - } else if ( strcmp(argv[idx], "-decode_server") == 0 ) { - if ( idx+3 < argc-1 ) { - cmdlineP->masterHostname = argv[idx+1]; + } else if (streq(argv[idx], "-decode_server")) { + if (idx+3 < argc-1) { + cmdlineP->masterHostname = argv[idx+1]; cmdlineP->masterPortNumber = atoi(argv[idx+2]); - cmdlineP->outputFrames = atoi(argv[idx+3]); - } else { + cmdlineP->outputFrames = atoi(argv[idx+3]); + } else pm_error("Invalid -decode_server option"); - } cmdlineP->function = COMBINE_FRAMES; decodeServer = TRUE; idx += 4; - } else if ( strcmp(argv[idx], "-nice") == 0 ) { + } else if (streq(argv[idx], "-nice")) { niceProcesses = TRUE; idx++; - } else if ( strcmp(argv[idx], "-max_machines") == 0 ) { - if ( idx+1 < argc-1 ) { + } else if (streq(argv[idx], "-max_machines")) { + if (idx+1 < argc-1) { cmdlineP->maxMachines = atoi(argv[idx+1]); - } else { + } else pm_error("Invalid -max_machines option"); - } idx += 2; - } else if ( strcmp(argv[idx], "-quiet") == 0 ) { - if ( idx+1 < argc-1 ) { + } else if (streq(argv[idx], "-quiet")) { + if (idx+1 < argc-1) quietTime = atoi(argv[idx+1]); - } else { + else pm_error("Invalid -quiet option"); - } idx += 2; - } else if ( strcmp(argv[idx], "-realquiet") == 0 ) { + } else if (streq(argv[idx], "-realquiet")) { realQuiet = TRUE; - idx++; - } else if (( strcmp(argv[idx], "-float_dct") == 0 ) || - ( strcmp(argv[idx], "-float-dct") == 0 )) { + ++idx; + } else if (streq(argv[idx], "-float_dct") || + streq(argv[idx], "-float-dct")) { pureDCT = TRUE; init_idctref(); init_fdct(); - idx++; - } else if ( strcmp(argv[idx], "-no_frame_summary") == 0 ) { - if ( idx < argc-1 ) { + ++idx; + } else if (streq(argv[idx], "-no_frame_summary")) { + if (idx < argc-1) noFrameSummaryOption = TRUE; - } else { + else pm_error("Invalid -no_frame_summary option"); - } - - idx++; - } else if ( strcmp(argv[idx], "-snr") == 0 ) { + ++idx; + } else if (streq(argv[idx], "-snr")) { printSNR = TRUE; - idx++; - } else if ( strcmp(argv[idx], "-mse") == 0 ) { - printSNR = printMSE = TRUE; - idx++; - } else if ( strcmp(argv[idx], "-debug_sockets") == 0 ) { + ++idx; + } else if (streq(argv[idx], "-mse")) { + printSNR = printMSE = TRUE; + ++idx; + } else if (streq(argv[idx], "-debug_sockets")) { debugSockets = TRUE; - idx++; - } else if ( strcmp(argv[idx], "-debug_machines") == 0 ) { + ++idx; + } else if (streq(argv[idx], "-debug_machines")) { debugMachines = TRUE; - idx++; - } else if ( strcmp(argv[idx], "-bit_rate_info") == 0 ) { - if ( idx+1 < argc-1 ) { + ++idx; + } else if (streq(argv[idx], "-bit_rate_info")) { + if (idx+1 < argc-1) { bitRateInfoOption = TRUE; SetBitRateFileName(argv[idx+1]); idx += 2; - } else { + } else pm_error("Invalid -bit_rate_info option"); - } - } else if ( strcmp(argv[idx], "-mv_histogram") == 0 ) { + } else if (streq(argv[idx], "-mv_histogram")) { computeMVHist = TRUE; - idx++; - } else { + ++idx; + } else pm_error("Unrecognized option: '%s'", argv[idx]); - } } - cmdlineP->paramFileName = argv[argc-1]; } @@ -685,8 +672,8 @@ main(int argc, char **argv) { DecodeServer(cmdline.outputFrames, outputFileName, cmdline.masterHostname, cmdline.masterPortNumber); } else { - if ((!cmdline.specificFrames) && - ((numMachines == 0) || (cmdline.function != ENCODE_FRAMES)) ) { + if (!cmdline.specificFrames && + (numMachines == 0 || cmdline.function != ENCODE_FRAMES) ) { ofP = fopen(outputFileName, "wb"); if (ofP == NULL) pm_error("Could not open output file!"); @@ -694,7 +681,7 @@ main(int argc, char **argv) { ofP = NULL; if (cmdline.function == ENCODE_FRAMES) { - if ((numMachines == 0) || (cmdline.specificFrames)) { + if (numMachines == 0 || cmdline.specificFrames) { encodeFrames(params.inputSourceP, cmdline.childProcess, cmdline.masterHostname, cmdline.masterPortNumber, diff --git a/converter/ppm/ppmtoyuvsplit.c b/converter/ppm/ppmtoyuvsplit.c index 2dddebfc..e4ffaa3a 100644 --- a/converter/ppm/ppmtoyuvsplit.c +++ b/converter/ppm/ppmtoyuvsplit.c @@ -4,7 +4,7 @@ ** - basename.V : The Chrominance chunk V at 1/4 ** The subsampled U and V values are made by arithmetic mean. ** -** If CCIR601 is defined, the produced YUV triples are scaled again +** The produced YUV triples are scaled again ** to fit into the smaller range of values for this standard. ** ** by A.Beck @@ -20,12 +20,6 @@ ** implied warranty. */ -/* Wether to create YUV in JFIF(JPEG) or CCIR.601(MPEG) scale */ -#define CCIR601 - -/* Wether to use pm_close() or fake it -- don't ask me why */ -/* #define ORIGINAL */ - /* ALPHA Kludge by Franky */ #ifdef __alpha @@ -38,160 +32,151 @@ #include "ppm.h" int -main(argc, argv) -char **argv; -{ - FILE *ifp,*vf,*uf,*yf; - pixel *pixelrow1,*pixelrow2; - register pixel *pP1,*pP2; - int rows, cols, format, row; - register int col; - pixval maxval; - myLONG u,v,y0,y1,y2,y3,u0,u1,u2,u3,v0,v1,v2,v3; - unsigned char *y1buf,*y2buf,*ubuf,*vbuf; - char ufname[256],vfname[256],yfname[256]; - - - ppm_init(&argc, argv); - - if ((argc>3)||(argc<2)) pm_usage("basename [ppmfile]"); - - if (argc == 3) ifp = pm_openr(argv[2]); - else ifp = stdin; - - strcpy(ufname,argv[1]); - strcpy(vfname,argv[1]); - strcpy(yfname,argv[1]); - - strcat(ufname,".U"); - strcat(vfname,".V"); - strcat(yfname,".Y"); - - uf = fopen(ufname,"wb"); - vf = fopen(vfname,"wb"); - yf = fopen(yfname,"wb"); - - if(!(uf && vf && yf)) { - perror("error opening output files"); - exit(0); - } - ppm_readppminit(ifp, &cols, &rows, &maxval, &format); - - if(cols & 1) fprintf(stderr, - "%s: Warning: odd columns count, exceed ignored\n", - argv[0]); - if(rows & 1) fprintf(stderr, - "%s: Warning: odd rows count, exceed ignored\n", - argv[0]); - - pixelrow1 = ((pixel*) pm_allocrow( cols, sizeof(pixel) )); - pixelrow2 = ((pixel*) pm_allocrow( cols, sizeof(pixel) )); - - y1buf = (unsigned char *) pm_allocrow( cols, 1 ); - y2buf = (unsigned char *) pm_allocrow( cols, 1 ); - ubuf = (unsigned char *) pm_allocrow( cols, 1 ); - vbuf = (unsigned char *) pm_allocrow( cols, 1 ); - - for (row = 0; row < (rows & ~1); row += 2) { - unsigned char *y1ptr,*y2ptr,*uptr,*vptr; - - ppm_readppmrow(ifp, pixelrow1, cols, maxval, format); - ppm_readppmrow(ifp, pixelrow2, cols, maxval, format); - - pP1 = pixelrow1; pP2 = pixelrow2; - y1ptr = y1buf; y2ptr = y2buf; vptr = vbuf; uptr = ubuf; - - for (col = 0 ; col < (cols & ~1); col += 2) { - pixval r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3; - - /* first pixel */ - r0 = PPM_GETR(*pP1); - g0 = PPM_GETG(*pP1); - b0 = PPM_GETB(*pP1); - pP1++; - /* 2nd pixel */ - r1 = PPM_GETR(*pP1); - g1 = PPM_GETG(*pP1); - b1 = PPM_GETB(*pP1); - pP1++; - /* 3rd pixel */ - r2 = PPM_GETR(*pP2); - g2 = PPM_GETG(*pP2); - b2 = PPM_GETB(*pP2); - pP2++; - /* 4th pixel */ - r3 = PPM_GETR(*pP2); - g3 = PPM_GETG(*pP2); - b3 = PPM_GETB(*pP2); - pP2++; - - -/* The JFIF RGB to YUV Matrix for $00010000 = 1.0 - -[Y] [19595 38469 7471][R] -[U] = [-11056 -21712 32768][G] -[V] [32768 -27440 -5328][B] +main(int argc, const char ** argv) { + + FILE * ifP; + FILE *vf, *uf, *yf; + pixel *pixelrow1, *pixelrow2; + int rows, cols; + int format; + unsigned int row; + pixval maxval; + unsigned char *y1buf, *y2buf, *ubuf, *vbuf; + char ufname[256], vfname[256], yfname[256]; + + pm_proginit(&argc, argv); + + if ((argc-1 > 2) || (argc-1 < 1)) + pm_error("Wrong number of arguments: %u. " + "Arguments are basename for output files " + "and optional input file name", argc-1); + + if (argc-1 == 2) + ifP = pm_openr(argv[2]); + else + ifP = stdin; + + strcpy(ufname,argv[1]); + strcpy(vfname,argv[1]); + strcpy(yfname,argv[1]); + + strcat(ufname,".U"); + strcat(vfname,".V"); + strcat(yfname,".Y"); + + uf = pm_openw(ufname); + vf = pm_openw(vfname); + yf = pm_openw(yfname); -*/ + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); - y0 = 19595 * r0 + 38469 * g0 + 7471 * b0; - u0 = -11056 * r0 - 21712 * g0 + 32768 * b0; - v0 = 32768 * r0 - 27440 * g0 - 5328 * b0; + if (cols % 2 == 1) + pm_message("Warning: odd columns count %u, excess ignored", cols); - y1 = 19595 * r1 + 38469 * g1 + 7471 * b1; - u1 = -11056 * r1 - 21712 * g1 + 32768 * b1; - v1 = 32768 * r1 - 27440 * g1 - 5328 * b1; + if (rows % 2 == 1) + pm_message("Warning: odd rows count %u, excess ignored", rows); - y2 = 19595 * r2 + 38469 * g2 + 7471 * b2; - u2 = -11056 * r2 - 21712 * g2 + 32768 * b2; - v2 = 32768 * r2 - 27440 * g2 - 5328 * b2; + pixelrow1 = ((pixel*) pm_allocrow(cols, sizeof(pixel))); + pixelrow2 = ((pixel*) pm_allocrow(cols, sizeof(pixel))); - y3 = 19595 * r3 + 38469 * g3 + 7471 * b3; - u3 = -11056 * r3 - 21712 * g3 + 32768 * b3; - v3 = 32768 * r3 - 27440 * g3 - 5328 * b3; + y1buf = (unsigned char *) pm_allocrow(cols, 1); + y2buf = (unsigned char *) pm_allocrow(cols, 1); + ubuf = (unsigned char *) pm_allocrow(cols, 1); + vbuf = (unsigned char *) pm_allocrow(cols, 1); - /* mean the chroma for subsampling */ + for (row = 0; row < (rows & ~1); row += 2) { + unsigned char *y1ptr, *y2ptr, *uptr, *vptr; + pixel *pP1, *pP2; + unsigned int col; - u = (u0+u1+u2+u3)>>2; - v = (v0+v1+v2+v3)>>2; + ppm_readppmrow(ifP, pixelrow1, cols, maxval, format); + ppm_readppmrow(ifP, pixelrow2, cols, maxval, format); -#ifdef CCIR601 + pP1 = &pixelrow1[0]; pP2 = &pixelrow2[0]; + y1ptr = y1buf; y2ptr = y2buf; vptr = vbuf; uptr = ubuf; - y0 = (y0 * 219)/255 + 1048576; - y1 = (y1 * 219)/255 + 1048576; - y2 = (y2 * 219)/255 + 1048576; - y3 = (y3 * 219)/255 + 1048576; + for (col = 0 ; col < (cols & ~1); col += 2) { + pixval r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3; + myLONG u, v, y0, y1, y2, y3, u0, u1, u2, u3, v0, v1, v2, v3; - u = (u * 224)/255 ; - v = (v * 224)/255 ; -#endif + /* first pixel */ + r0 = PPM_GETR(*pP1); + g0 = PPM_GETG(*pP1); + b0 = PPM_GETB(*pP1); + pP1++; + /* 2nd pixel */ + r1 = PPM_GETR(*pP1); + g1 = PPM_GETG(*pP1); + b1 = PPM_GETB(*pP1); + pP1++; + /* 3rd pixel */ + r2 = PPM_GETR(*pP2); + g2 = PPM_GETG(*pP2); + b2 = PPM_GETB(*pP2); + pP2++; + /* 4th pixel */ + r3 = PPM_GETR(*pP2); + g3 = PPM_GETG(*pP2); + b3 = PPM_GETB(*pP2); + pP2++; - *y1ptr++ = (y0 >> 16) ; - *y1ptr++ = (y1 >> 16) ; - *y2ptr++ = (y2 >> 16) ; - *y2ptr++ = (y3 >> 16) ; + /* The JFIF RGB to YUV Matrix for $00010000 = 1.0 + [Y] [19595 38469 7471][R] + [U] = [-11056 -21712 32768][G] + [V] [32768 -27440 -5328][B] - *uptr++ = (u >> 16)+128 ; - *vptr++ = (v >> 16)+128 ; + */ - } - fwrite(y1buf, (cols & ~1), 1, yf); - fwrite(y2buf, (cols & ~1), 1, yf); - fwrite(ubuf, cols/2, 1, uf); - fwrite(vbuf, cols/2, 1, vf); - } + y0 = 19595 * r0 + 38469 * g0 + 7471 * b0; + u0 = -11056 * r0 - 21712 * g0 + 32768 * b0; + v0 = 32768 * r0 - 27440 * g0 - 5328 * b0; -/* I dunno why pm_close sees an error... get rid of it */ + y1 = 19595 * r1 + 38469 * g1 + 7471 * b1; + u1 = -11056 * r1 - 21712 * g1 + 32768 * b1; + v1 = 32768 * r1 - 27440 * g1 - 5328 * b1; -#ifdef ORIGINAL - pm_close(ifp); -#else - if(ifp != stdin) fclose(ifp); -#endif - fclose(yf); - fclose(uf); - fclose(vf); - exit(0); + y2 = 19595 * r2 + 38469 * g2 + 7471 * b2; + u2 = -11056 * r2 - 21712 * g2 + 32768 * b2; + v2 = 32768 * r2 - 27440 * g2 - 5328 * b2; + + y3 = 19595 * r3 + 38469 * g3 + 7471 * b3; + u3 = -11056 * r3 - 21712 * g3 + 32768 * b3; + v3 = 32768 * r3 - 27440 * g3 - 5328 * b3; + + /* mean the chroma for subsampling */ + + u = (u0+u1+u2+u3)>>2; + v = (v0+v1+v2+v3)>>2; + + y0 = (y0 * 219)/255 + 1048576; + y1 = (y1 * 219)/255 + 1048576; + y2 = (y2 * 219)/255 + 1048576; + y3 = (y3 * 219)/255 + 1048576; + + u = (u * 224)/255 ; + v = (v * 224)/255 ; + + *y1ptr++ = (y0 >> 16) ; + *y1ptr++ = (y1 >> 16) ; + *y2ptr++ = (y2 >> 16) ; + *y2ptr++ = (y3 >> 16) ; + + + *uptr++ = (u >> 16)+128 ; + *vptr++ = (v >> 16)+128 ; + + } + fwrite(y1buf, (cols & ~1), 1, yf); + fwrite(y2buf, (cols & ~1), 1, yf); + fwrite(ubuf, cols/2, 1, uf); + fwrite(vbuf, cols/2, 1, vf); + } + + pm_close(ifP); + fclose(yf); + fclose(uf); + fclose(vf); + return 0; } |