diff options
Diffstat (limited to 'converter/other')
156 files changed, 7076 insertions, 5942 deletions
diff --git a/converter/other/Makefile b/converter/other/Makefile index 6a3d14ed..2be88781 100644 --- a/converter/other/Makefile +++ b/converter/other/Makefile @@ -7,12 +7,12 @@ VPATH=.:$(SRCDIR)/$(SUBDIR) include $(BUILDDIR)/config.mk -TEST_PKGCONFIG_LIBXML2 = if pkg-config libxml-2.0; then echo exists; fi +TEST_PKGCONFIG_LIBXML2 = if $(PKG_CONFIG) libxml-2.0; then echo exists; fi ifneq ($(shell $(TEST_PKGCONFIG_LIBXML2)),) # pkg-config libxml2 works on this system - XML2_LIBS = $(shell pkg-config libxml-2.0 --libs) - XML2_CFLAGS = $(shell pkg-config libxml-2.0 --cflags) + XML2_LIBS = $(shell $(PKG_CONFIG) libxml-2.0 --libs) + XML2_CFLAGS = $(shell $(PKG_CONFIG) libxml-2.0 --cflags) else ifeq ($(shell xml2-config --version),) XML2_LIBS=NONE @@ -34,12 +34,12 @@ ifneq ($(TIFFLIB),NONE) endif endif -TEST_PKGCONFIG_LIBPNG = if pkg-config libpng$(PNGVER); then echo exists; fi +TEST_PKGCONFIG_LIBPNG = if $(PKG_CONFIG) libpng$(PNGVER); then echo exists; fi ifneq ($(shell $(TEST_PKGCONFIG_LIBPNG)),) # pkg-config libpng works on this system HAVE_PNGLIB = Y - EXTERN_INCLUDES += $(shell pkg-config libpng$(PNGVER) --cflags) + EXTERN_INCLUDES += $(shell $(PKG_CONFIG) libpng$(PNGVER) --cflags) else ifneq ($(shell libpng$(PNGVER)-config --version),) # No pkg-config, but we have libpng-config on this system @@ -166,6 +166,8 @@ endif OBJECTS = $(BINARIES:%=%.o) $(EXTRA_OBJECTS) MERGE_OBJECTS = $(MERGEBINARIES:%=%.o2) $(EXTRA_OBJECTS) +HAVE_MERGE_COMPAT=YES + pnmtops.o pnmtops.o2: CFLAGS_TARGET=$(PNMTOPS_NOFLATE_OPT) SCRIPTS = anytopnm pnmtoplainpnm @@ -192,7 +194,7 @@ tifftopnm pamtotiff pnmtotiffcmyk: \ ifneq ($(shell $(TEST_PKGCONFIG_LIBPNG)),) # pkg-config libpng works on this system - PNGLIB_LIBOPTS = $(shell pkg-config libpng$(PNGVER) --libs) + PNGLIB_LIBOPTS = $(shell $(PKG_CONFIG) libpng$(PNGVER) --libs) else ifneq ($(shell libpng$(PNGVER)-config --version),) # No pkg-config, but we have libpng-config on this system @@ -248,7 +250,7 @@ bmptopnm.o bmptopnm.o2: bmp.h pamtotga.o pamtotga.o2: tga.h -install.bin: install.bin.local +install.bin install.merge: install.bin.local .PHONY: install.bin.local install.bin.local: $(PKGDIR)/bin # Remember that $(SYMLINK) might just be a copy command. @@ -296,3 +298,25 @@ ifeq ($(HAVE_PNGLIB),Y) cd $(PKGDIR)/bin ; \ $(SYMLINK) pamtopng$(EXE) pamrgbatopng$(EXE) endif + +mergecomptrylist: + cat /dev/null >$@ + echo "TRY(\"bmptoppm\", main_bmptopnm);" >>$@ + echo "TRY(\"gemtopbm\", main_gemtopnm);" >>$@ +ifneq ($(JPEGLIB),NONE) + echo "TRY(\"ppmtojpeg\", main_pnmtojpeg);" >>$@ +endif + echo "TRY(\"ppmtouil\", main_pamtouil);" >>$@ + echo "TRY(\"ppmtotga\", main_pamtotga);" >>$@ + echo "TRY(\"pnmtopnm\", main_pamtopnm);" >>$@ + echo "TRY(\"pnmtofits\", main_pamtofits);" >>$@ +ifneq ($(TIFF_PREREQ_MISSING),Y) + echo "TRY(\"pnmtotiff\", main_pamtotiff);" >>$@ +endif +ifeq ($(HAVE_PNGLIB),Y) + echo "TRY(\"pngtopnm\", main_pngtopam);" >>$@ +endif + echo "TRY(\"icontopbm\", main_sunicontopnm);" >>$@ +ifeq ($(HAVE_PNGLIB),Y) + echo "TRY(\"pamrgbatopng\", main_pamtopng);" >>$@ +endif diff --git a/converter/other/anytopnm b/converter/other/anytopnm index 397faae5..e5de85cc 100755 --- a/converter/other/anytopnm +++ b/converter/other/anytopnm @@ -527,14 +527,18 @@ if [ $# -gt 1 ] ; then "input file name." 1>&2 exit 1 elif [ $# -eq 1 ] ; then - inputFile="$1" + if [ $1 = "--version" -o $1 = "-version" ] ; then + pamtopnm --version ; exit $? + else + inputFile="$1" + fi else - inputFile="-" + inputFile="-" + fi -tempdir="${TMPDIR-/tmp}/anytopnm.$$" -mkdir -m 0700 $tempdir || \ - { echo "Could not create temporary file. Exiting."; exit 1;} +tempdir=$(mktemp -d "${TMPDIR:-/tmp}/anytopnm.XXXXXXXX") || + ( echo "Could not create temporary file. Exiting." 1>&2; exit 1; ) trap 'rm -rf $tempdir' 0 # Take out all spaces diff --git a/converter/other/bmptopnm.c b/converter/other/bmptopnm.c index bf4d10f8..3f66634b 100644 --- a/converter/other/bmptopnm.c +++ b/converter/other/bmptopnm.c @@ -1,7 +1,7 @@ /***************************************************************************** bmptopnm.c ****************************************************************************** - + Bmptopnm - Converts from a Microsoft Windows or OS/2 .BMP file to a PBM, PGM, or PPM file. @@ -9,7 +9,7 @@ The name was changed in March 2002. Copyright (C) 1992 by David W. Sanderson. - + 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 @@ -62,14 +62,14 @@ struct bitPosition { }; struct pixelformat { - /* The format of a pixel representation from the raster. i.e. which - bits apply to red, green, blue, and transparency + /* The format of a pixel representation from the raster. i.e. which + bits apply to red, green, blue, and transparency */ struct bitPosition red; struct bitPosition blu; struct bitPosition grn; struct bitPosition trn; - + bool conventionalBgr; /* This means that the above bit positions are just the conventional BGR format -- one byte Blue, one byte Green, one byte Red, @@ -80,6 +80,19 @@ struct pixelformat { */ }; +typedef struct { + /* These are all encodings of floating point */ + unsigned long x; + unsigned long y; + unsigned long z; +} cieXyz; + +typedef struct { + cieXyz red; + cieXyz grn; + cieXyz blu; +} cieXyzTriple; + struct bmpInfoHeader { enum rowOrder rowOrder; unsigned int cols; @@ -92,17 +105,18 @@ struct bmpInfoHeader { described by the "mask" values in the header, rather than fixed formats. */ - unsigned int cmapsize; + unsigned int cmapSize; /* Size in bytes of the colormap (palette) in the BMP file. Zero means there is no colormap. */ unsigned int imageSize; - /* Size in bytes of the image data. We only reference this - when the image is compressed. */ + /* Size in bytes of the image data. We only reference this + when the image is compressed. */ unsigned short cPlanes; BMPCompType compression; struct pixelformat pixelformat; + cieXyzTriple endPoints; }; @@ -137,7 +151,7 @@ parseCommandLine(int argc, const char ** argv, option_def_index = 0; /* incremented by OPTENT3 */ OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 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 */ @@ -145,7 +159,7 @@ parseCommandLine(int argc, const char ** argv, pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - if (argc-1 == 0) + if (argc-1 == 0) cmdlineP->inputFileName = "-"; else if (argc-1 != 1) pm_error("Program takes zero or one argument (filename). You " @@ -208,27 +222,74 @@ GetLong(FILE * const fp) { -typedef struct { - long dummy[12]; -} cieXyzTriple; +static cieXyz +GetCieXyz(FILE * const ifP) { + + cieXyz retval; + + retval.x = GetLong(ifP); + retval.y = GetLong(ifP); + retval.z = GetLong(ifP); + + return retval; +} + + static cieXyzTriple -GetCieXyzTriple(FILE * const fp) { +GetCieXyzTriple(FILE * const ifP) { - cieXyzTriple v; - unsigned int i; + cieXyzTriple retval; - for (i = 0; i < 12; ++i) - if (pm_readlittlelong(fp, &v.dummy[i]) == -1) - pm_error(er_read, ifname); + retval.red = GetCieXyz(ifP); + retval.grn = GetCieXyz(ifP); + retval.blu = GetCieXyz(ifP); - return v; + return retval; } static struct pixelformat -defaultPixelformat(unsigned int const bitCount); +defaultPixelformat(unsigned int const bitCount) { + + struct pixelformat retval; + + switch (bitCount) { + case 16: + /* This layout is sometimes called "RGB555". A document from + Microsoft says this is the default (when the "compression" + field of the header says COMP_BITFIELDS). + */ + retval.conventionalBgr = FALSE; + retval.red.shift = 10; + retval.grn.shift = 5; + retval.blu.shift = 0; + retval.trn.shift = 0; + retval.red.mask = 0x1f; /* 5 bits */ + retval.grn.mask = 0x1f; /* 5 bits */ + retval.blu.mask = 0x1f; /* 5 bits */ + retval.trn.mask = 0; + break; + case 24: + case 32: + retval.conventionalBgr = TRUE; + retval.red.shift = 16; + retval.grn.shift = 8; + retval.blu.shift = 0; + retval.trn.shift = 0; + retval.red.mask = 0xff; /* 8 bits */ + retval.grn.mask = 0xff; /* 8 bits */ + retval.blu.mask = 0xff; /* 8 bits */ + retval.trn.mask = 0; + break; + default: + /* colormapped - masks are undefined */ + break; + } + + return retval; +} @@ -238,7 +299,7 @@ readOffBytes(FILE * const fp, unsigned int const nbytes) { Read 'nbytes' from file 'fp'. Abort program if read error. -----------------------------------------------------------------------------*/ int i; - + for(i = 0; i < nbytes; ++i) { int rc; rc = getc(fp); @@ -250,15 +311,11 @@ readOffBytes(FILE * const fp, unsigned int const nbytes) { static void -bmpReadfileheader(FILE * const ifP, - unsigned int * const bytesReadP, +bmpReadfileheader(FILE * const ifP, + unsigned int * const bytesReadP, unsigned int * const offBitsP) { - unsigned short xHotSpot; - unsigned short yHotSpot; unsigned long offBits; - unsigned long int fileSize; - if (GetByte(ifP) != 'B') pm_error("'%s' is not a BMP file. (It doesn't start with 'BM')", @@ -268,33 +325,47 @@ bmpReadfileheader(FILE * const ifP, ifname); - fileSize = GetLong(ifP); /* This is not always reliable. */ - xHotSpot = GetShort(ifP); - yHotSpot = GetShort(ifP); + /* fileSize = */ GetLong(ifP); /* This is not always reliable. */ + /* xHotSpot = */ GetShort(ifP); + /* yHotSpot = */ GetShort(ifP); offBits = GetLong(ifP); *offBitsP = offBits; + assert(BMPlenfileheader() == 14); + *bytesReadP = 14; } static void -readOs2InfoHeader(FILE * const ifP, - struct bmpInfoHeader * const headerP) { +readOs2InfoHeaderRest(FILE * const ifP, + struct bmpInfoHeader * const headerP) { +/*---------------------------------------------------------------------------- + Read the rest of the info header, after its size field, of an OS2 BMP from + *ifP. + + Add the information from it to *headerP, in particular these members: + cols + rows + rowOrder + cPlanes + cBitCount + cmapSize + pixelformat + compression +-----------------------------------------------------------------------------*/ unsigned short colsField, rowsField; unsigned short planesField, bitCountField; - headerP->class = C_OS2; - pm_readlittleshortu(ifP, &colsField); if (colsField == 0) pm_error("Invalid BMP file: says width is zero"); else headerP->cols = colsField; - + pm_readlittleshortu(ifP, &rowsField); if (rowsField == 0) pm_error("Invalid BMP file: says height is zero"); @@ -313,22 +384,19 @@ readOs2InfoHeader(FILE * const ifP, same as for Windows. */ if (headerP->cBitCount <= 8) - headerP->cmapsize = 1 << headerP->cBitCount; + headerP->cmapSize = 1 << headerP->cBitCount; else if (headerP->cBitCount == 24) - headerP->cmapsize = 0; + headerP->cmapSize = 0; /* There is a 16 bit truecolor format, but we don't know how the bits are divided among red, green, and blue, so we can't handle it. */ else pm_error("Unrecognized bits per pixel in OS/2 BMP file header: %d", headerP->cBitCount); - + headerP->pixelformat = defaultPixelformat(headerP->cBitCount); headerP->compression = BMPCOMP_RGB; - - pm_message("OS/2 BMP, %dx%dx%d", - headerP->cols, headerP->rows, headerP->cBitCount); } @@ -337,24 +405,24 @@ static void validateCompression(unsigned long const compression, enum rowOrder const rowOrder, unsigned int const cBitCount) { - + if (compression != BMPCOMP_RGB && compression != BMPCOMP_BITFIELDS && - compression != BMPCOMP_RLE4 && compression != BMPCOMP_RLE8) + compression != BMPCOMP_RLE4 && compression != BMPCOMP_RLE8) pm_error("Input has unknown encoding. " "Compression type code = %ld. The only ones we know " "are RGB (%u), BITFIELDS (%u), " "RLE4 (%u), and RLE8 (%u)", compression, BMPCOMP_RGB, BMPCOMP_BITFIELDS, BMPCOMP_RLE4, BMPCOMP_RLE8); - + if ((compression == BMPCOMP_RLE4 || compression == BMPCOMP_RLE8) && - rowOrder == TOPDOWN ) + rowOrder == TOPDOWN ) pm_error("Invalid BMP header. Claims image is top-down and also " "compressed, which is an impossible combination."); if ((compression == BMPCOMP_RLE4 && cBitCount !=4 ) || - (compression == BMPCOMP_RLE8 && cBitCount !=8 )) - pm_error("Invalid BMP header. " + (compression == BMPCOMP_RLE8 && cBitCount !=8 )) + pm_error("Invalid BMP header. " "Compression type (%s) disagrees with " "number of bits per pixel (%u).", compression == BMPCOMP_RLE4 ? "RLE4" : "RLE8", @@ -373,13 +441,10 @@ readWindowsBasic40ByteInfoHeader(FILE * const ifP, Return the information from the info header as *headerP. -----------------------------------------------------------------------------*/ - int colorsimportant; /* ColorsImportant value from header */ int colorsused; /* ColorsUsed value from header */ unsigned short planesField, bitCountField; int32_t colsField; - headerP->class = C_WIN; - pm_readlittlelong2(ifP, &colsField); if (colsField == 0) @@ -388,6 +453,7 @@ readWindowsBasic40ByteInfoHeader(FILE * const ifP, pm_error("Invalid BMP file: says width is negative (%d)", colsField); else headerP->cols = (unsigned int)colsField; + { long const cy = GetLong(ifP); @@ -413,7 +479,7 @@ readWindowsBasic40ByteInfoHeader(FILE * const ifP, headerP->bitFields = (compression == BMPCOMP_BITFIELDS); - headerP->compression = compression; + headerP->compression = compression; } /* And read the rest of the junk in the 40 byte header */ headerP->imageSize = GetLong(ifP); /* ImageSize */ @@ -421,24 +487,30 @@ readWindowsBasic40ByteInfoHeader(FILE * const ifP, GetLong(ifP); /* YpixelsPerMeter */ colorsused = GetLong(ifP); /* ColorsUsed */ /* See comments in bmp.h for info about the definition of the following - word and its relationship to the color map size (headerP->cmapsize). + word and its relationship to the color map size (headerP->cmapSize). */ - colorsimportant = GetLong(ifP); /* ColorsImportant */ + /* colorsimportant = */ GetLong(ifP); /* ColorsImportant */ if (headerP->cBitCount <= 8) { if (colorsused != 0) { if (colorsused > 1 << headerP->cBitCount) pm_error("Invalid BMP header. Says %u bits per pixel, " - "but %d colors used", + "but %d colors used", headerP->cBitCount, colorsused); + else if (colorsused == 1 && headerP->cBitCount == 1) { + pm_message("Abnormal BMP header. Says 1 bit per pixel. " + "Should have 2 colors, but says only 1 color used. " + ); + headerP->cmapSize = colorsused; + } else - headerP->cmapsize = colorsused; - } else - headerP->cmapsize = 1 << headerP->cBitCount; - } else if (headerP->cBitCount == 24 || - headerP->cBitCount == 16 || + headerP->cmapSize = colorsused; + } else + headerP->cmapSize = 1 << headerP->cBitCount; + } else if (headerP->cBitCount == 24 || + headerP->cBitCount == 16 || headerP->cBitCount == 32) - headerP->cmapsize = 0; + headerP->cmapSize = 0; else pm_error("Unrecognized bits per pixel in Windows BMP file header: %d", headerP->cBitCount); @@ -451,18 +523,18 @@ lsbZeroCount(unsigned int const mask) /*---------------------------------------------------------------------------- Return the number of consecutive zeroes in the mask 'mask', starting with the least significant bit and going up. E.g. for 0x20, it would be 5. - + Use GCC built-in when available. -----------------------------------------------------------------------------*/ -#if HAVE_GCC_BITCOUNT +#if HAVE_GCC_BITCOUNT { return ( mask==0 ? sizeof(mask)*8 : __builtin_ctz(mask) ); } #else { unsigned int i=0; - + while (((mask >> i) & 0x1) == 0 && i < sizeof(mask)*8) ++i; @@ -512,52 +584,17 @@ computeConventionalBgr(struct pixelformat * const fP, -static struct pixelformat -defaultPixelformat(unsigned int const bitCount) { - - struct pixelformat retval; - - switch (bitCount) { - case 16: - /* This layout is sometimes called "RGB555". A document from - Microsoft says this is the default (when the "compression" - field of the header says COMP_BITFIELDS). - */ - retval.conventionalBgr = FALSE; - retval.red.shift = 10; - retval.grn.shift = 5; - retval.blu.shift = 0; - retval.trn.shift = 0; - retval.red.mask = 0x1f; /* 5 bits */ - retval.grn.mask = 0x1f; /* 5 bits */ - retval.blu.mask = 0x1f; /* 5 bits */ - retval.trn.mask = 0; - break; - case 24: - case 32: - retval.conventionalBgr = TRUE; - retval.red.shift = 16; - retval.grn.shift = 8; - retval.blu.shift = 0; - retval.trn.shift = 0; - retval.red.mask = 0xff; /* 8 bits */ - retval.grn.mask = 0xff; /* 8 bits */ - retval.blu.mask = 0xff; /* 8 bits */ - retval.trn.mask = 0; - break; - default: - /* colormapped - masks are undefined */ - break; - } - - return retval; -} - +static void +readV4InfoHeaderExtension(FILE * const ifP, + struct bmpInfoHeader * const headerP, + unsigned int * const bytesReadP) { + unsigned long redMsk, grnMsk, bluMsk, trnMsk; -static void -readV4InfoHeaderExtension(FILE * const ifP, - struct bmpInfoHeader * const headerP) { + redMsk = GetLong(ifP); + grnMsk = GetLong(ifP); + bluMsk = GetLong(ifP); + trnMsk = GetLong(ifP); if (headerP->bitFields) { /* A document from Microsoft says on Windows 95 there is no @@ -565,21 +602,40 @@ readV4InfoHeaderExtension(FILE * const ifP, (5,5,5) or (5,6,5) for 16 bit and (8,8,8) for 32 bit. It calls these RGB555, RGB565, RGB888. */ - headerP->pixelformat.red = bitPositionFromMask(GetLong(ifP)); - headerP->pixelformat.grn = bitPositionFromMask(GetLong(ifP)); - headerP->pixelformat.blu = bitPositionFromMask(GetLong(ifP)); - headerP->pixelformat.trn = bitPositionFromMask(GetLong(ifP)); + headerP->pixelformat.red = bitPositionFromMask(redMsk); + headerP->pixelformat.grn = bitPositionFromMask(grnMsk); + headerP->pixelformat.blu = bitPositionFromMask(bluMsk); + headerP->pixelformat.trn = bitPositionFromMask(trnMsk); computeConventionalBgr(&headerP->pixelformat, headerP->cBitCount); } else headerP->pixelformat = defaultPixelformat(headerP->cBitCount); GetLong(ifP); /* Color space */ - GetCieXyzTriple(ifP); /* Endpoints */ + + headerP->endPoints = GetCieXyzTriple(ifP); /* 36 bytes */ + GetLong(ifP); /* GammaRed */ GetLong(ifP); /* GammaGreen */ GetLong(ifP); /* GammaBlue */ -} + + *bytesReadP = 68; +} + + + +static void +readV5InfoHeaderExtension(FILE * const ifP, + struct bmpInfoHeader * const headerP, + unsigned int * const bytesReadP) { + + GetLong(ifP); /* Intent */ + GetLong(ifP); /* ProfileData */ + GetLong(ifP); /* ProfileSize */ + GetLong(ifP); /* Reserved */ + + *bytesReadP = 16; +} @@ -593,117 +649,157 @@ defaultV4InfoHeaderExtension(struct bmpInfoHeader * const headerP) { static void -readWindowsInfoHeader(FILE * const ifP, - unsigned int const cInfoHeaderSize, - struct bmpInfoHeader * const headerP) { - +readWindowsInfoHeaderRest(FILE * const ifP, + unsigned int const cInfoHeaderSize, + struct bmpInfoHeader * const headerP) { +/*---------------------------------------------------------------------------- + Read the rest of the info header, after the length field, of a Windows BMP + from *ifP. + + 'cInfoHeaderSize' is the size of the info header, not counting its size + field. Note that besides telling us how much data to read, this also + implies which of the three major formats the data is in. + + Add the information from it to *headerP, in particular these members: + + cols + rows + rowOrder + cPlanes + cBitCount + bitFields + compression + imageSize + cmapSize + pixelformat + endPoints +-----------------------------------------------------------------------------*/ /* There are 3 major formats of Windows BMP, identified by the 3 info header lengths. The original one is 40 bytes. The "V4 header" is 108 bytes and was new with Windows 95 and NT 4.0. The "V5 header" is 124 bytes and was new with Windows 98 and Windows 2000. */ + unsigned int bytesRead; + readWindowsBasic40ByteInfoHeader(ifP, headerP); - if (cInfoHeaderSize >= 108) - readV4InfoHeaderExtension(ifP, headerP); - else + bytesRead = 40; + + if (cInfoHeaderSize >= BMP_HDRLEN_WIN_V4) { + unsigned int v4BytesRead; + readV4InfoHeaderExtension(ifP, headerP, &v4BytesRead); + bytesRead += v4BytesRead; + + assert(bytesRead == BMP_HDRLEN_WIN_V4); + } else defaultV4InfoHeaderExtension(headerP); - if (cInfoHeaderSize >= 124) { - /* Read off the V5 info header extension. */ - GetLong(ifP); /* Intent */ - GetLong(ifP); /* ProfileData */ - GetLong(ifP); /* ProfileSize */ - GetLong(ifP); /* Reserved */ + if (cInfoHeaderSize >= BMP_HDRLEN_WIN_V5) { + unsigned int v5BytesRead; + readV5InfoHeaderExtension(ifP, headerP, &v5BytesRead); + bytesRead += v5BytesRead; + assert(bytesRead == BMP_HDRLEN_WIN_V5); } - pm_message("Windows BMP, %dx%dx%d", - headerP->cols, headerP->rows, headerP->cBitCount); + for (; bytesRead < cInfoHeaderSize;) { + GetByte(ifP); + ++bytesRead; + } + + assert(bytesRead == cInfoHeaderSize); } static void -bmpReadinfoheader(FILE * const ifP, +bmpReadinfoheader(FILE * const ifP, unsigned int * const bytesReadP, - struct bmpInfoHeader * const headerP) { + struct bmpInfoHeader * const headerP, + const char ** const errorP) { unsigned int const cInfoHeaderSize = GetLong(ifP); - switch (cInfoHeaderSize) { - case 12: - readOs2InfoHeader(ifP, headerP); - break; - case 40: - readWindowsInfoHeader(ifP, cInfoHeaderSize, headerP); - break; - case 108: - pm_error("This is a Version 4 Windows BMP; " - "this program knows only Version 1"); - break; - case 124: - pm_error("This is a Version 5 Windows BMP; " - "this program knows only Version 1"); - break; - default: - pm_error("%s: unknown Info Header size: %u bytes", - ifname, cInfoHeaderSize); - break; + const char * error; + + BMPdetermineclass(cInfoHeaderSize, &headerP->class, &error); + + if (error) { + pm_asprintf(errorP, "Cannot determine the class of BMP from the " + "info header size %u. %s", cInfoHeaderSize, error); + pm_strfree(error); + } else { + switch (headerP->class) { + case BMP_C_WIN_V1: + case BMP_C_WIN_V2: + case BMP_C_WIN_V3: + case BMP_C_WIN_V4: + case BMP_C_WIN_V5: + readWindowsInfoHeaderRest(ifP, cInfoHeaderSize, headerP); + break; + case BMP_C_OS2_1x: + case BMP_C_OS2_2x: + readOs2InfoHeaderRest(ifP, headerP); + break; + } + *errorP = NULL; + *bytesReadP = cInfoHeaderSize; } - *bytesReadP = cInfoHeaderSize; + /* Part of our anti-arithmetic overflow strategy is to make sure height + and width always fit in 16 bits, so they can be multiplied together. + This shouldn't be a problem, since they come from 16 bit fields in + the BMP info header. + */ + assert(headerP->cols < (1<<16)); + assert(headerP->rows < (1<<16)); } static void -bmpReadColormap(FILE * const ifP, - int const class, - xel ** const colormapP, - unsigned int const cmapsize, +bmpReadColormap(FILE * const ifP, + enum bmpClass const class, + xel ** const colormapP, + unsigned int const cmapSize, unsigned int * const bytesReadP) { /*---------------------------------------------------------------------------- Read the color map from the present position in the input BMP file *ifP. - The map has 'cmapsize' entries in it. cmapsize == 0 means there is + The map has 'cmapSize' entries in it. cmapSize == 0 means there is no color map. We return a color map as *colormapP. If there is no color map in the BMP, this is just an arbitrary color map. - + 'class' is the class of BMP image - Windows or OS/2. -----------------------------------------------------------------------------*/ + xel * const colormap = pnm_allocrow(MAX(1, cmapSize)); unsigned int i; - - xel * colormap; unsigned int bytesRead; - colormap = pnm_allocrow(MAX(1,cmapsize)); - - bytesRead = 0; /* initial value */ - - for (i = 0; i < cmapsize; ++i) { + for (i = 0, bytesRead = 0; i < cmapSize; ++i) { /* There is a document that says the bytes are ordered R,G,B,Z, but in practice it appears to be the following instead: */ - unsigned int r, g, b; - - b = GetByte(ifP); - g = GetByte(ifP); - r = GetByte(ifP); + unsigned int const b = GetByte(ifP); + unsigned int const g = GetByte(ifP); + unsigned int const r = GetByte(ifP); + + unsigned int j; PNM_ASSIGN(colormap[i], r, g, b); bytesRead += 3; - if (class == C_WIN) { + for (j = 3; j < BMPlenrgb(class); ++j) { GetByte(ifP); bytesRead += 1; } } - *colormapP = colormap; + + *colormapP = colormap; *bytesReadP = bytesRead; } @@ -718,13 +814,13 @@ extractBitFields(unsigned int const rasterval, pixval * const bP, pixval * const aP) { - unsigned int const rbits = + unsigned int const rbits = (rasterval >> pixelformat.red.shift) & pixelformat.red.mask; - unsigned int const gbits = + unsigned int const gbits = (rasterval >> pixelformat.grn.shift) & pixelformat.grn.mask; - unsigned int const bbits = + unsigned int const bbits = (rasterval >> pixelformat.blu.shift) & pixelformat.blu.mask; - unsigned int const abits = + unsigned int const abits = (rasterval >> pixelformat.trn.shift) & pixelformat.trn.mask; *rP = pixelformat.red.mask > 0 ? @@ -735,7 +831,7 @@ extractBitFields(unsigned int const rasterval, (unsigned int) bbits * maxval / pixelformat.blu.mask : 0; *aP = pixelformat.trn.mask > 0 ? (unsigned int) abits * maxval / pixelformat.trn.mask : 0; -} +} @@ -758,7 +854,7 @@ convertRow16(unsigned char const bmprow[], extractBitFields(rasterval, pixelformat, 255, &r, &g, &b, &a); PNM_ASSIGN(xelrow[col], r, g, b); - + cursor += 2; } } @@ -770,7 +866,7 @@ convertRow24(unsigned char const bmprow[], xel xelrow[], int const cols, struct pixelformat const pixelformat) { - + /* It's truecolor */ /* There is a document that gives a much different format for 24 bit BMPs. But this seems to be the de facto standard, and is, @@ -780,7 +876,7 @@ convertRow24(unsigned char const bmprow[], unsigned int col; unsigned int cursor; - + cursor = 0; for (col = 0; col < cols; ++col) { pixval r, g, b, a; @@ -791,17 +887,17 @@ convertRow24(unsigned char const bmprow[], b = bmprow[cursor+0]; a = 0; } else { - unsigned int const rasterval = + unsigned int const rasterval = (bmprow[cursor+0] << 16) + (bmprow[cursor+1] << 8) + (bmprow[cursor+2] << 0); - + extractBitFields(rasterval, pixelformat, 255, &r, &g, &b, &a); } PNM_ASSIGN(xelrow[col], r, g, b); cursor += 3; } -} +} @@ -810,7 +906,7 @@ convertRow32(unsigned char const bmprow[], xel xelrow[], int const cols, struct pixelformat const pixelformat) { - + /* It's truecolor */ unsigned int col; @@ -826,40 +922,40 @@ convertRow32(unsigned char const bmprow[], b = bmprow[cursor+0]; a = 0; } else { - unsigned int const rasterval = + unsigned int const rasterval = (bmprow[cursor+0] << 24) + (bmprow[cursor+1] << 16) + (bmprow[cursor+2] << 8) + (bmprow[cursor+3] << 0); - + extractBitFields(rasterval, pixelformat, 255, &r, &g, &b, &a); } - PNM_ASSIGN(xelrow[col], + PNM_ASSIGN(xelrow[col], bmprow[cursor+2], bmprow[cursor+1], bmprow[cursor+0]); cursor += 4; } -} +} static void validateIndex(unsigned int const index, - unsigned int const cmapsize ) { + unsigned int const cmapSize ) { - if (index >= cmapsize) + if (index >= cmapSize) pm_error("Error: invalid index to color palette."); } static void -convertRow(unsigned char const bmprow[], +convertRow(unsigned char const bmprow[], xel xelrow[], - int const cols, - unsigned int const cBitCount, + int const cols, + unsigned int const cBitCount, struct pixelformat const pixelformat, xel const colormap[], - unsigned int const cmapsize + unsigned int const cmapSize ) { /*---------------------------------------------------------------------------- Convert a row in raw BMP raster format bmprow[] to a row of xels xelrow[]. @@ -871,20 +967,20 @@ convertRow(unsigned char const bmprow[], If the image is colormapped, colormap[] is the colormap (colormap[i] is the color with color index i). -----------------------------------------------------------------------------*/ - if (cBitCount == 24) + if (cBitCount == 24) convertRow24(bmprow, xelrow, cols, pixelformat); - else if (cBitCount == 16) + else if (cBitCount == 16) convertRow16(bmprow, xelrow, cols, pixelformat); - else if (cBitCount == 32) + else if (cBitCount == 32) convertRow32(bmprow, xelrow, cols, pixelformat); - else if (cBitCount == 8) { + else if (cBitCount == 8) { /* It's a whole byte colormap index */ - unsigned int col; + unsigned int col; for (col = 0; col < cols; ++col) { unsigned int const index = bmprow[col]; - validateIndex(index, cmapsize); + validateIndex(index, cmapSize); xelrow[col] = colormap[index]; - } + } } else if (cBitCount == 1 || cBitCount == 2 || cBitCount == 4) { /* It's a bit field color index */ unsigned char const mask = ( 1 << cBitCount ) - 1; @@ -894,9 +990,9 @@ convertRow(unsigned char const bmprow[], for (col = 0; col < cols; ++col) { unsigned int const cursor = (col*cBitCount)/8; unsigned int const shift = 8 - ((col*cBitCount) % 8) - cBitCount; - unsigned int const index = + unsigned int const index = (bmprow[cursor] & (mask << shift)) >> shift; - validateIndex(index, cmapsize); + validateIndex(index, cmapSize); xelrow[col] = colormap[index]; } } else { @@ -911,8 +1007,8 @@ static unsigned char ** allocBmpRaster(unsigned int const rows, unsigned int const bytesPerRow) { - unsigned int const storageSize = - rows * sizeof(unsigned char *) + rows * bytesPerRow; + unsigned int const storageSize = + rows * sizeof(unsigned char *) + rows * bytesPerRow; unsigned char ** bmpRaster; unsigned int row; unsigned char * startOfRows; @@ -932,7 +1028,7 @@ allocBmpRaster(unsigned int const rows, startOfRows = (unsigned char *)(bmpRaster + rows); - for (row = 0; row < rows; ++row) + for (row = 0; row < rows; ++row) bmpRaster[row] = startOfRows + row * bytesPerRow; return bmpRaster; @@ -950,47 +1046,51 @@ readrow(FILE * const ifP, size_t bytesRead; assert(bytesPerRow > 0); - + bytesRead = fread(bmpRaster[row], 1, bytesPerRow, ifP); if (bytesRead < bytesPerRow) { if (feof(ifP)) pm_error("End of file reading row %u of BMP raster.", row); - else + else pm_error("Error reading BMP raster. Errno=%d (%s)", errno, strerror(errno)); } *bytesReadP += bytesRead; } - + static void -nibbleAlign(unsigned char * const ptr, - unsigned int const nibbles){ +nybbleAlign(unsigned char * const bytes, + unsigned int const nybbleCt){ /*---------------------------------------------------------------------------- - Shift data pointed by ptr one half byte toward the MSB (to the left). - + Shift the 'nybbleCt' nybbles of bytes[], after the first byte, one nybble + toward the left, with the first of those nybble shifting into the right half + of the first byte. Leave the left half of the first byte alone. + Example: - - (Numbers in hex, 8 nibbles) - 5F 13 7E 89 A1 + + (Numbers in hex, 8 nybbles) + 5? 13 7E 89 A1 becomes 51 37 E8 9A 10 -----------------------------------------------------------------------------*/ - unsigned int const fullByteCount = (nibbles-1) / 2; + unsigned int const fullByteCt = (nybbleCt + 1) / 2; unsigned int i; - - ptr[0] = ptr[0] & ptr[1] >> 4; - - for (i = 0; i < fullByteCount; ++i) - ptr[i+1] = ptr[i+1] << 4 & ptr[i+2] >> 4; - - if (nibbles % 2 == 1) /* if there is a final odd nibble */ - ptr[fullByteCount+1] <<= 4; /* shift it a half byte */ + + bytes[0] >>= 4; + + for (i = 0; i < fullByteCt; ++i) + bytes[i] = bytes[i] << 4 | bytes[i+1] >> 4; + + if (nybbleCt % 2 == 0) { + /* There is a final right nybble. Shift it. */ + bytes[fullByteCt] <<= 4; + } } - + enum rleStatus { ABS_MODE, ENC_MODE, END_OF_ROW, END_OF_BMP, DELTA }; static enum rleStatus @@ -1000,9 +1100,9 @@ readRLEcode(FILE * const ifP, unsigned short s; enum rleStatus retval; - + s = GetBigShort(ifP); - + if (s == 0) retval = END_OF_ROW; else if (s == 1) retval = END_OF_BMP; else if (s == 2) retval = DELTA; @@ -1034,16 +1134,18 @@ readrowRLE(FILE * const ifP, bool const rle4 = (compression == BMPCOMP_RLE4); int const pixelsPerRowMargin = rle4 ? cols % 2 : 0; - char const err_decode[] = + char const err_decode[] = "Error while decoding compressed BMP image. " - "%s. Row: %u Pixel: %u" ; - + "%s. Row: %u Pixel: %u" ; + unsigned int totalBytesRead; unsigned int pixelsRead; - /* There are RLE4 images with rows coded up the byte boundary, resulting - in each row one pixel larger than the column length stated in the - BMP info header (header.cols) when the column length is odd. + /* There are RLE4 images with rows coded up to the byte boundary, + resulting in each row one pixel larger than the column length + stated in the BMP info header (header.cols) when the column length + is odd. + pixelsPerRowMargin is a "wart" to provide for this case. */ @@ -1052,7 +1154,7 @@ readrowRLE(FILE * const ifP, while (true) { unsigned int n; - /* decompressed bytes already read; current write point */ + /* decompressed bytes already read; current write point */ unsigned int cnt; unsigned char code; @@ -1061,23 +1163,23 @@ readrowRLE(FILE * const ifP, switch (readRLEcode(ifP, &cnt, &code)) { case ENC_MODE: { unsigned int const byteCnt = rle4 ? (cnt + 1) /2 : cnt; - unsigned int i; + unsigned int i; if (pixelsRead + cnt > cols + pixelsPerRowMargin) pm_error(err_decode, "Too many pixels in encoded mode", - row, pixelsRead ); - + row, pixelsRead ); + for (i = 0; i < byteCnt; ++i) bmpRaster[row][n+i] = code; - + if (rle4 && pixelsRead % 2 == 1) /* previous read ended odd */ - nibbleAlign(&bmpRaster[row][n-1], cnt); - + nybbleAlign(&bmpRaster[row][n-1], cnt); + pixelsRead += cnt; totalBytesRead += 2; } break; - + case ABS_MODE: { unsigned int cmpBytesRead; /* compressed bytes read */ /* align read-end to 16 bit boundary */ @@ -1086,43 +1188,43 @@ readrowRLE(FILE * const ifP, if (pixelsRead + cnt > cols + pixelsPerRowMargin) pm_error(err_decode, "Too many pixels in absolute mode", - row, pixelsRead); + row, pixelsRead); - cmpBytesRead = fread(&bmpRaster[row][n], + cmpBytesRead = fread(&bmpRaster[row][n], sizeof(char), bytesToRead, ifP); if (cmpBytesRead < bytesToRead) { if (feof(ifP)) pm_error("End of file reading row %u " "of compressed BMP raster.", row); - else + else pm_error("Error reading BMP raster. Errno=%d (%s)", errno, strerror(errno)); } if (rle4 && pixelsRead % 2 == 1) /* previous read ended odd */ - nibbleAlign(&bmpRaster[row][n-1], cnt); - + nybbleAlign(&bmpRaster[row][n-1], cnt); + pixelsRead += cnt; totalBytesRead += cmpBytesRead + 2; } break; - + case END_OF_ROW: { if (cols == pixelsRead || cols + pixelsPerRowMargin == pixelsRead) { if (!lastrow) { *bytesReadP += totalBytesRead + 2; return; - } else if (readRLEcode(ifP, NULL, NULL) == END_OF_BMP) { + } else if (readRLEcode(ifP, NULL, NULL) == END_OF_BMP) { *bytesReadP += totalBytesRead +4; return; } else /* lastrow and END_OF_BITMAP not detected */ pm_error(err_decode, "End of bitmap not marked", - row, pixelsRead ); + row, pixelsRead ); } else pm_error(err_decode, "Premature end of row", row, pixelsRead); - } break; + } break; case END_OF_BMP: { if (lastrow && (cols == pixelsRead || @@ -1132,15 +1234,27 @@ readrowRLE(FILE * const ifP, } else pm_error(err_decode, "Premature end of bitmap", row, pixelsRead ); + /* Windows programs do not reject premature end of bitmap. + Rather, they set the remaining pixels of the raster to + an arbitrary value. In practice, images with incomplete + bitmaps are rare. + */ } break; case DELTA: { + /* Delta means "move the point (col,row) by the amount given + in the next two bytes." Like premature end of bitmap, the + official specs do not specify what value the skipped pixels + should be set to. Judging from Windows utilities, there is + no consensus within Microsoft either. + */ pm_error(err_decode, "Delta code in compressed BMP image. " - "This program does not process deltas.", + "This program does not process deltas", row, pixelsRead); + } break; - + default: pm_error("Internal error processing RLE code in row %u", row); } @@ -1150,13 +1264,13 @@ readrowRLE(FILE * const ifP, static void -bmpReadraster(FILE * const ifP, - unsigned int const cols, - unsigned int const rows, +bmpReadraster(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, enum rowOrder const rowOrder, - unsigned int const cBitCount, + unsigned int const cBitCount, BMPCompType const compression, - unsigned char *** const bmpRasterP, + unsigned char *** const bmpRasterP, unsigned int * const bytesReadP) { /*---------------------------------------------------------------------------- Read the raster from the BMP file on *ifP (which is positioned to the @@ -1179,37 +1293,40 @@ bmpReadraster(FILE * const ifP, */ unsigned char ** bmpRaster; + assert(cols < (1<<16)); + assert(bytesPerRow < (1<<16)); + bmpRaster = allocBmpRaster(rows, bytesPerRow); *bytesReadP = 0; - /* row order BOTTOMUP is by far the most common case - the bottom + /* row order BOTTOMUP is by far the most common case - the bottom line is first in the file, the top line last. - + We have never actually seen TOPDOWN, except in a Microsoft spec */ - + switch(compression){ case BMPCOMP_RGB: case BMPCOMP_BITFIELDS: { unsigned int i; for (i = 0; i < rows; ++i) - readrow(ifP, rowOrder == TOPDOWN ? i : rows - i - 1, + readrow(ifP, rowOrder == TOPDOWN ? i : rows - i - 1, bytesPerRow, bmpRaster, bytesReadP); } break; - case BMPCOMP_RLE4: + case BMPCOMP_RLE4: case BMPCOMP_RLE8: { unsigned int i; /* Read all rows except last */ assert(rows >= 1); for (i = 0; i < rows - 1; ++i){ - readrowRLE(ifP, rowOrder == TOPDOWN ? i : rows - i - 1, + readrowRLE(ifP, rowOrder == TOPDOWN ? i : rows - i - 1, cols, FALSE, compression, bmpRaster, bytesReadP); } /* Read last row */ - readrowRLE(ifP, rowOrder == TOPDOWN ? i : rows - i - 1, + readrowRLE(ifP, rowOrder == TOPDOWN ? i : rows - i - 1, cols, TRUE, compression, bmpRaster, bytesReadP); - } break; + } break; case BMPCOMP_JPEG: pm_error("BMP file uses JPEG compression. We don't know how to " "interpret that."); @@ -1226,36 +1343,51 @@ bmpReadraster(FILE * const ifP, static void reportHeader(struct bmpInfoHeader const header, - unsigned int const offBits) { - - pm_message("BMP image header says:"); - pm_message(" Class of BMP: %s", - header.class == C_WIN ? "Windows" : - header.class == C_OS2 ? "OS/2" : - "???"); - pm_message(" Width: %d pixels", header.cols); - pm_message(" Height: %d pixels", header.rows); - pm_message(" Depth: %d planes", header.cPlanes); - pm_message(" Row order: %s", - header.rowOrder == BOTTOMUP ? "bottom up" : "top down"); - pm_message(" Byte offset of raster within file: %u", offBits); - pm_message(" Bits per pixel in raster: %u", header.cBitCount); - pm_message(" Compression: %s", BMPCompTypeName(header.compression)); - pm_message(" Colors in color map: %u", header.cmapsize); -} + unsigned int const offBits, + bool const verbose) { + + if (verbose) { + pm_message("BMP image header says:"); + pm_message(" Class of BMP: %s", BMPClassName(header.class)); + pm_message(" Width: %d pixels", header.cols); + pm_message(" Height: %d pixels", header.rows); + pm_message(" Depth: %d planes", header.cPlanes); + pm_message(" Row order: %s", + header.rowOrder == BOTTOMUP ? "bottom up" : "top down"); + pm_message(" Byte offset of raster within file: %u", offBits); + pm_message(" Bits per pixel in raster: %u", header.cBitCount); + pm_message(" Compression: %s", BMPCompTypeName(header.compression)); + pm_message(" Colors in color map: %u", header.cmapSize); + } else { + pm_message("%s BMP, %ux%ux%u", + BMPClassName(header.class), + header.cols, + header.rows, + header.cBitCount); + } +} + + + +static void +validateCPlanes(unsigned short const cPlanes) { + + if (cPlanes != 1) + pm_error("Error: invalid planes value in BMP header. Must be 1"); +} static void analyzeColors(xel const colormap[], - unsigned int const cmapsize, + unsigned int const cmapSize, xelval const maxval, bool * const grayPresentP, bool * const colorPresentP) { - - if (cmapsize == 0) { + + if (cmapSize == 0) { /* No colormap, and we're not about to search the entire raster, - so we just assume it's full color + so we just assume it's full color */ *colorPresentP = TRUE; *grayPresentP = TRUE; @@ -1264,7 +1396,7 @@ analyzeColors(xel const colormap[], *colorPresentP = FALSE; /* initial assumption */ *grayPresentP = FALSE; /* initial assumption */ - for (i = 0; i < cmapsize; ++i) { + for (i = 0; i < cmapSize; ++i) { if (PPM_ISGRAY(colormap[i])) { if (PPM_GETR(colormap[i]) != 0 && PPM_GETR(colormap[i]) != maxval) @@ -1281,8 +1413,8 @@ static void warnIfOffBitsWrong(struct bmpInfoHeader const bmpHeader, unsigned int const offBits) { - if (offBits != BMPoffbits(bmpHeader.class, bmpHeader.cBitCount, - bmpHeader.cmapsize)) { + if (offBits != BMPoffbits(bmpHeader.class, bmpHeader.cBitCount, + bmpHeader.cmapSize)) { pm_message("warning: the BMP header says the raster starts " "at offset %u bytes into the file (offbits), " @@ -1290,8 +1422,8 @@ warnIfOffBitsWrong(struct bmpInfoHeader const bmpHeader, "the raster. This inconsistency probably means the " "input file is not a legal BMP file and is unusable.", offBits, - BMPoffbits(bmpHeader.class, bmpHeader.cBitCount, - bmpHeader.cmapsize)); + BMPoffbits(bmpHeader.class, bmpHeader.cBitCount, + bmpHeader.cmapSize)); } } @@ -1305,8 +1437,8 @@ readColorMap(FILE * const ifP, unsigned int bytesRead; - bmpReadColormap(ifP, bmpHeader.class, - colorMapP, bmpHeader.cmapsize, &bytesRead); + bmpReadColormap(ifP, bmpHeader.class, + colorMapP, bmpHeader.cmapSize, &bytesRead); *posP += bytesRead; } @@ -1316,7 +1448,7 @@ readColorMap(FILE * const ifP, static void readRaster(FILE * const ifP, struct bmpInfoHeader const bmpHeader, - unsigned char *** const bmpRasterP, + unsigned char *** const bmpRasterP, unsigned int * const posP) { unsigned int bytesRead; @@ -1350,16 +1482,16 @@ isValidBmpBpp(unsigned int const cBitCount) { static void -readBmp(FILE * const ifP, - unsigned char *** const bmpRasterP, - int * const colsP, - int * const rowsP, - bool * const grayPresentP, +readBmp(FILE * const ifP, + unsigned char *** const bmpRasterP, + unsigned int * const colsP, + unsigned int * const rowsP, + bool * const grayPresentP, bool * const colorPresentP, - unsigned int * const cBitCountP, + unsigned int * const cBitCountP, struct pixelformat * const pixelformatP, xel ** const colormapP, - unsigned int * const cmapsizeP, + unsigned int * const cmapSizeP, bool const verbose) { xel * colormap; /* malloc'ed */ @@ -1367,33 +1499,39 @@ readBmp(FILE * const ifP, /* Current byte position in the BMP file */ /* The following are all information from the BMP headers */ - + unsigned int offBits; /* Byte offset into file of raster */ struct bmpInfoHeader bmpHeader; pos = 0; /* Starting at the beginning ... */ - { + { unsigned int bytesRead; bmpReadfileheader(ifP, &bytesRead, &offBits); pos += bytesRead; } { unsigned int bytesRead; - bmpReadinfoheader(ifP, &bytesRead, &bmpHeader); + const char * error; + bmpReadinfoheader(ifP, &bytesRead, &bmpHeader, &error); + if (error) + pm_error("Failed to read the BMP info header. Image may " + "not be a valid BMP. %s", error); + if (verbose) pm_message("Read %u bytes of header", bytesRead); pos += bytesRead; } - if (verbose) - reportHeader(bmpHeader, offBits); + reportHeader(bmpHeader, offBits, verbose); + + validateCPlanes(bmpHeader.cPlanes); warnIfOffBitsWrong(bmpHeader, offBits); readColorMap(ifP, bmpHeader, &colormap, &pos); - analyzeColors(colormap, bmpHeader.cmapsize, bmpMaxval, + analyzeColors(colormap, bmpHeader.cmapSize, bmpMaxval, grayPresentP, colorPresentP); readOffBytes(ifP, offBits - pos); @@ -1404,7 +1542,7 @@ readBmp(FILE * const ifP, if (fgetc(ifP) != EOF) pm_message("warning: some image data remains unread."); - + if (!isValidBmpBpp(bmpHeader.cBitCount)) pm_error("Invalid BMP image: 'cBitCount' field of header " "(number of bits for each pixel in raster) is %u", @@ -1416,23 +1554,23 @@ readBmp(FILE * const ifP, *rowsP = bmpHeader.rows; *pixelformatP = bmpHeader.pixelformat; *colormapP = colormap; - *cmapsizeP = bmpHeader.cmapsize; + *cmapSizeP = bmpHeader.cmapSize; } static void writeRasterGen(unsigned char ** const bmpRaster, - int const cols, - int const rows, + unsigned int const cols, + unsigned int const rows, int const format, - unsigned int const cBitCount, + unsigned int const cBitCount, struct pixelformat const pixelformat, xel const colormap[], - unsigned int const cmapsize) { + unsigned int const cmapSize) { /*---------------------------------------------------------------------------- Write the PNM raster to Standard Output, corresponding to the raw BMP - raster bmpRaster. Write the raster assuming the PNM image has + raster bmpRaster. Write the raster assuming the PNM image has dimensions 'cols' by 'rows' and format 'format', with maxval 255. The BMP image has 'cBitCount' bits per pixel, arranged in format @@ -1440,7 +1578,7 @@ writeRasterGen(unsigned char ** const bmpRaster, If the image is colormapped, colormap[] is the colormap (colormap[i] is the color with color index i). - + writeRasterPbm() is faster for a PBM image. -----------------------------------------------------------------------------*/ xel * xelrow; @@ -1450,7 +1588,7 @@ writeRasterGen(unsigned char ** const bmpRaster, for (row = 0; row < rows; ++row) { convertRow(bmpRaster[row], xelrow, cols, cBitCount, pixelformat, - colormap, cmapsize); + colormap, cmapSize); pnm_writepnmrow(stdout, xelrow, cols, bmpMaxval, format, FALSE); } pnm_freerow(xelrow); @@ -1460,12 +1598,12 @@ writeRasterGen(unsigned char ** const bmpRaster, static void writeRasterPbm(unsigned char ** const bmpRaster, - int const cols, - int const rows, + unsigned int const cols, + unsigned int const rows, xel const colormap[]) { /*---------------------------------------------------------------------------- Write the PBM raster to Standard Output corresponding to the raw BMP - raster bmpRaster. Write the raster assuming the PBM image has + raster bmpRaster. Write the raster assuming the PBM image has dimensions 'cols' by 'rows'. The BMP image has 'cBitCount' bits per pixel, arranged in format @@ -1475,28 +1613,28 @@ writeRasterPbm(unsigned char ** const bmpRaster, (colormap[i] is the color with color index i). We cannot handle the abnormal case in which colormap[0] and colormap[1] have the same value (i.e. both white or both black.) - + We destroy *bmpRaster as a side effect. -----------------------------------------------------------------------------*/ - unsigned int const colChars = pbm_packed_bytes(cols); - - int row; + unsigned int const colCharCt = pbm_packed_bytes(cols); + + unsigned int row; enum colorFormat {BlackWhite, WhiteBlack}; enum colorFormat colorformat; - + if (PPM_GETR(colormap[0]) > 0) colorformat = WhiteBlack; - else + else colorformat = BlackWhite; - - for (row=0; row < rows; ++row){ - unsigned char * const bitrow = bmpRaster[row]; + + for (row = 0; row < rows; ++row){ + unsigned char * const bitrow = bmpRaster[row]; if (colorformat == BlackWhite) { unsigned int i; - for (i = 0; i < colChars; ++i) - bitrow[i] = ~bitrow[i]; /* flip all pixels */ - } + for (i = 0; i < colCharCt; ++i) + bitrow[i] = ~bitrow[i]; /* flip all pixels */ + } pbm_cleanrowend_packed(bitrow, cols); pbm_writepbmrow_packed(stdout, bitrow, cols, FALSE); @@ -1517,8 +1655,8 @@ main(int argc, const char ** argv) { black and white and whether it has colors other than black, white, and gray. */ - int cols, rows; - unsigned char **bmpRaster; + unsigned int cols, rows; + unsigned char ** bmpRaster; /* The raster part of the BMP image, as a row x column array, with each element being a raw byte from the BMP raster. Note that bmpRaster[0] is really Row 0 -- the top row of the image, even @@ -1532,13 +1670,12 @@ main(int argc, const char ** argv) { /* Malloc'ed colormap (palette) from the BMP. Contents of map undefined if not a colormapped BMP. */ - unsigned int cmapsize; - /* Number of colormap entries. Described in the BMP header. - Note that a file may be 8 bits per pixel but have less than - 256 colors. In the 1 bit per pixel case, there should be - 2 entries according to the official specification, but we - allow files with just 1. - */ + unsigned int cmapSize; + /* Number of colormap entries. From BMP header. Note that a file may + be 8 bits per pixel but have fewer than 256 colors. In the 1 bit + per pixel case, there should be 2 entries according to the official + specification, but we allow files with just 1. + */ pm_proginit(&argc, argv); @@ -1547,11 +1684,11 @@ main(int argc, const char ** argv) { ifP = pm_openr(cmdline.inputFileName); if (streq(cmdline.inputFileName, "-")) ifname = "Standard Input"; - else + else ifname = cmdline.inputFileName; - readBmp(ifP, &bmpRaster, &cols, &rows, &grayPresent, &colorPresent, - &cBitCount, &pixelformat, &colormap, &cmapsize, + readBmp(ifP, &bmpRaster, &cols, &rows, &grayPresent, &colorPresent, + &cBitCount, &pixelformat, &colormap, &cmapSize, cmdline.verbose); pm_close(ifP); @@ -1565,14 +1702,14 @@ main(int argc, const char ** argv) { outputType = PBM_TYPE; pm_message("WRITING PBM IMAGE"); } - + if (outputType == PBM_TYPE && cBitCount == 1){ pbm_writepbminit(stdout, cols, rows, FALSE); writeRasterPbm(bmpRaster, cols, rows, colormap); } else { pnm_writepnminit(stdout, cols, rows, bmpMaxval, outputType, FALSE); writeRasterGen(bmpRaster, cols, rows, outputType, cBitCount, - pixelformat, colormap, cmapsize); + pixelformat, colormap, cmapSize); } free(colormap); free(bmpRaster); diff --git a/converter/other/cameratopam/camera.c b/converter/other/cameratopam/camera.c index a1adba95..439c9413 100644 --- a/converter/other/cameratopam/camera.c +++ b/converter/other/cameratopam/camera.c @@ -1,7 +1,6 @@ -#define _BSD_SOURCE - /* Make sure strcasecmp is in string.h */ -#define _XOPEN_SOURCE - /* Make sure putenv is in stdlib.h */ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ +#define _XOPEN_SOURCE 500 + /* Make sure putenv is in stdlib.h, strcaseeq is in nstring.h */ #include <stdlib.h> #include <string.h> @@ -16,6 +15,7 @@ #include "pm.h" #include "mallocvar.h" #include "pm_c_util.h" +#include "nstring.h" #include "global_variables.h" #include "cameratopam.h" @@ -46,8 +46,8 @@ #define FORC3 for (c=0; c < 3; c++) #define FORC4 for (c=0; c < colors; c++) -static void -merror (const void *ptr, const char *where) +static void +merror (const void *ptr, const char *where) { if (ptr == NULL) pm_error ("Out of memory in %s", where); @@ -56,7 +56,7 @@ merror (const void *ptr, const char *where) -static void +static void adobeCopyPixel(Image const image, unsigned int const row, unsigned int const col, @@ -306,7 +306,7 @@ minolta_z2() void nikon_e2100_load_raw(Image const image) { - + unsigned char data[3432], *dp; unsigned short pixel[2288], *pix; int row, col; @@ -383,7 +383,7 @@ fuji_s3_load_raw(Image const image) { } } -static void +static void fuji_common_load_raw(Image const image, unsigned int const ncol, unsigned int const icol, @@ -1022,6 +1022,7 @@ static void sony_decrypt (unsigned *data, int len, int start, int key) { static uint32_t pad[128]; unsigned int p; + unsigned int i; if (start) { for (p=0; p < 4; p++) @@ -1042,12 +1043,13 @@ static void sony_decrypt (unsigned *data, int len, int start, int key) u.bytes[1] = pad[p] >> 16; u.bytes[2] = pad[p] >> 8; u.bytes[3] = pad[p] >> 0; - + pad[p] = u.word; } } - while (len--) - *data++ ^= pad[p++ & 0x7f] = pad[(p+1) & 0x7f] ^ pad[(p+65) & 0x7f]; + for (i = 0, p = 0; i < len; ++i, ++p) { + *data++ ^= pad[p & 0x7f] = pad[(p+1) & 0x7f] ^ pad[(p+65) & 0x7f]; + } } void @@ -1151,9 +1153,9 @@ static void ciff_block_1030() /* Parse a CIFF file, better known as Canon CRW format. */ -void -parse_ciff(FILE * const ifp, - int const offset, +void +parse_ciff(FILE * const ifp, + int const offset, int const length) { int tboff, nrecs, i, type, len, roff, aoff, save, wbi=-1; @@ -1306,7 +1308,7 @@ parse_rollei(FILE * const ifp) void -parse_mos(FILE * const ifp, +parse_mos(FILE * const ifp, int const offset) { char data[40]; @@ -1355,7 +1357,7 @@ static double getrat() -static void +static void parse_makernote(FILE * const ifp) { unsigned base=0, offset=0, entries, tag, type, len, save; @@ -1501,15 +1503,15 @@ get_timestamp(FILE * const ifp) timestamp = ts; } -static void +static void parse_exif(FILE * const ifp, int base) { - int entries, tag, type, len, val, save; + int entries, tag, len, val, save; entries = get2(ifp); while (entries--) { tag = get2(ifp); - type = get2(ifp); + /* type = */ get2(ifp); len = get4(ifp); val = get4(ifp); save = ftell(ifp); @@ -1526,7 +1528,7 @@ parse_exif(FILE * const ifp, int base) } } -static int +static int parse_tiff_ifd(FILE * const ifp, int base, int level) { unsigned entries, tag, type, len, plen=16, save; @@ -1687,7 +1689,7 @@ guess_cfa_pc: case 50723: /* CameraCalibration1 */ case 50724: /* CameraCalibration2 */ for (i=0; i < colors; i++) - FORC4 cc[i][c] = getrat(); + FORC4 cc[i][c] = getrat(); case 50727: /* AnalogBalance */ FORC4 ab[c] = getrat(); break; @@ -1767,7 +1769,7 @@ parse_external_jpeg(const char * const ifname) strcpy (jname, ifname); jfile = jname + (file - ifname); jext = jname + (ext - ifname); - if (strcasecmp (ext, ".jpg")) { + if (!strcaseeq (ext, ".jpg")) { strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg"); memcpy (jfile, file+4, 4); memcpy (jfile+4, file, 4); diff --git a/converter/other/cameratopam/cameratopam.c b/converter/other/cameratopam/cameratopam.c index ec33dd31..2c832714 100644 --- a/converter/other/cameratopam/cameratopam.c +++ b/converter/other/cameratopam/cameratopam.c @@ -7,6 +7,7 @@ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure string.h contains strdup() */ #define _XOPEN_SOURCE 500 /* Make sure unistd.h contains swab(), string.h constains strdup() */ diff --git a/converter/other/cameratopam/foveon.c b/converter/other/cameratopam/foveon.c index a3e5449a..992f3883 100644 --- a/converter/other/cameratopam/foveon.c +++ b/converter/other/cameratopam/foveon.c @@ -1,6 +1,6 @@ /* This code is licensed to the public by its copyright owners under GPL. */ -#define _XOPEN_SOURCE /* get M_PI */ +#define _XOPEN_SOURCE 500 /* get M_PI in math.h */ #include <stdio.h> #include <assert.h> diff --git a/converter/other/cameratopam/identify.c b/converter/other/cameratopam/identify.c index 02208be6..7e77adb2 100644 --- a/converter/other/cameratopam/identify.c +++ b/converter/other/cameratopam/identify.c @@ -1,3 +1,4 @@ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _BSD_SOURCE /* Make sure strcasecmp() is in string.h */ #include <string.h> diff --git a/converter/other/cameratopam/ljpeg.c b/converter/other/cameratopam/ljpeg.c index 07791e25..331d258c 100644 --- a/converter/other/cameratopam/ljpeg.c +++ b/converter/other/cameratopam/ljpeg.c @@ -1,3 +1,4 @@ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _BSD_SOURCE /* Make sure string.h containst strcasecmp() */ #include <stdlib.h> #include <string.h> diff --git a/converter/other/fiasco/binerror.c b/converter/other/fiasco/binerror.c index 77243c64..9820d853 100644 --- a/converter/other/fiasco/binerror.c +++ b/converter/other/fiasco/binerror.c @@ -7,8 +7,8 @@ * Credits: Modelled after variable argument routines from Jef * Poskanzer's pbmplus package. * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -18,6 +18,7 @@ * $State: Exp $ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _ERROR_C diff --git a/converter/other/fiasco/binerror.h b/converter/other/fiasco/binerror.h index e7ff43c9..4f313aca 100644 --- a/converter/other/fiasco/binerror.h +++ b/converter/other/fiasco/binerror.h @@ -4,8 +4,8 @@ * Written by: Stefan Frank * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/buttons.c b/converter/other/fiasco/buttons.c index 82ed18cd..fc54d84a 100644 --- a/converter/other/fiasco/buttons.c +++ b/converter/other/fiasco/buttons.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/buttons.h b/converter/other/fiasco/buttons.h index a09f3423..079715f5 100644 --- a/converter/other/fiasco/buttons.h +++ b/converter/other/fiasco/buttons.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/approx.c b/converter/other/fiasco/codec/approx.c index 5072fae3..d8fefcaa 100644 --- a/converter/other/fiasco/codec/approx.c +++ b/converter/other/fiasco/codec/approx.c @@ -1,10 +1,10 @@ /* - * approx.c: Approximation of range images with matching pursuit + * approx.c: Approximation of range images with matching pursuit * - * Written by: Ullrich Hafner - * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * Written by: Ullrich Hafner + * + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -34,7 +34,7 @@ /***************************************************************************** - local variables + local variables *****************************************************************************/ @@ -52,227 +52,205 @@ typedef struct mp /***************************************************************************** - prototypes + prototypes *****************************************************************************/ static void orthogonalize (unsigned index, unsigned n, unsigned level, real_t min_norm, - const word_t *domain_blocks, const coding_t *c); + const word_t *domain_blocks, const coding_t *c); static void matching_pursuit (mp_t *mp, bool_t full_search, real_t price, - unsigned max_edges, int y_state, const range_t *range, - const domain_pool_t *domain_pool, const coeff_t *coeff, - const wfa_t *wfa, const coding_t *c); + unsigned max_edges, int y_state, const range_t *range, + const domain_pool_t *domain_pool, const coeff_t *coeff, + const wfa_t *wfa, const coding_t *c); /***************************************************************************** - public code + public code *****************************************************************************/ real_t approximate_range (real_t max_costs, real_t price, int max_edges, - int y_state, range_t *range, domain_pool_t *domain_pool, - coeff_t *coeff, const wfa_t *wfa, const coding_t *c) -/* - * Approximate image block 'range' by matching pursuit. This functions - * calls the matching pursuit algorithm several times (with different - * parameters) in order to find the best approximation. Refer to function - * 'matching_pursuit()' for more details about parameters. - * - * Return value: - * approximation costs - */ -{ - mp_t mp; - bool_t success = NO; - - /* - * First approximation attempt: default matching pursuit algorithm. - */ - mp.exclude [0] = NO_EDGE; - matching_pursuit (&mp, c->options.full_search, price, max_edges, - y_state, range, domain_pool, coeff, wfa, c); - - /* - * Next approximation attempt: remove domain block mp->indices [0] - * from domain pool (vector with smallest costs) and run the - * matching pursuit again. - */ - if (c->options.second_domain_block) - { - mp_t tmp_mp = mp; + int y_state, range_t *range, domain_pool_t *domain_pool, + coeff_t *coeff, const wfa_t *wfa, const coding_t *c) { +/*---------------------------------------------------------------------------- + Approximate image block 'range' by matching pursuit. This functions + calls the matching pursuit algorithm several times (with different + parameters) in order to find the best approximation. Refer to function + 'matching_pursuit()' for more details about parameters. + + Return value: approximation costs +-----------------------------------------------------------------------------*/ + mp_t mp; + + /* + * First approximation attempt: default matching pursuit algorithm. + */ + mp.exclude [0] = NO_EDGE; + matching_pursuit(&mp, c->options.full_search, price, max_edges, + y_state, range, domain_pool, coeff, wfa, c); + + /* + * Next approximation attempt: remove domain block mp->indices [0] + * from domain pool (vector with smallest costs) and run the + * matching pursuit again. + */ + if (c->options.second_domain_block) { + mp_t tmp_mp; - tmp_mp.exclude [0] = tmp_mp.indices [0]; - tmp_mp.exclude [1] = NO_EDGE; - - matching_pursuit (&tmp_mp, c->options.full_search, price, max_edges, - y_state, range, domain_pool, coeff, wfa, c); - if (tmp_mp.costs < mp.costs) /* success */ - { - success = YES; - mp = tmp_mp; - } - } - - /* - * Next approximation attempt: check whether some coefficients have - * been quantized to zero. Vectors causing the underflow are - * removed from the domain pool and then the matching pursuit - * algorithm is run again (until underflow doesn't occur anymore). - */ - if (c->options.check_for_underflow) - { - int iteration = -1; - mp_t tmp_mp = mp; + tmp_mp = mp; /* initial value */ + + tmp_mp.exclude[0] = tmp_mp.indices [0]; + tmp_mp.exclude[1] = NO_EDGE; + + matching_pursuit(&tmp_mp, c->options.full_search, price, max_edges, + y_state, range, domain_pool, coeff, wfa, c); + if (tmp_mp.costs < mp.costs) /* success */ + mp = tmp_mp; + } + + /* + * Next approximation attempt: check whether some coefficients have + * been quantized to zero. Vectors causing the underflow are + * removed from the domain pool and then the matching pursuit + * algorithm is run again (until underflow doesn't occur anymore). + */ + if (c->options.check_for_underflow) { + mp_t tmp_mp; + int iteration; + + tmp_mp = mp; /* initial value */ + iteration = -1; /* initial value */ - do - { - int i; + do { + int i; + + ++iteration; + tmp_mp.exclude[iteration] = NO_EDGE; + + for (i = 0; isdomain(tmp_mp.indices[i]); ++i) { + if (tmp_mp.weight [i] == 0) { + tmp_mp.exclude[iteration] = tmp_mp.indices [i]; + break; + } + } + if (isdomain (tmp_mp.exclude [iteration])) { + /* try again */ + tmp_mp.exclude [iteration + 1] = NO_EDGE; + + matching_pursuit(&tmp_mp, c->options.full_search, price, + max_edges, y_state, range, domain_pool, + coeff, wfa, c); + if (tmp_mp.costs < mp.costs) /* success */ + mp = tmp_mp; + } + } while (isdomain (tmp_mp.exclude [iteration]) + && iteration < MAXEDGES - 1); + } + + /* + * Next approximation attempt: check whether some coefficients have + * been quantized to +/- max-value. Vectors causing the overflow are + * removed from the domain pool and then the matching pursuit + * algorithm is run again (until overflow doesn't occur anymore). + */ + if (c->options.check_for_overflow) { + mp_t tmp_mp; + int iteration; + + tmp_mp = mp; /* initial value */ + iteration = -1; /* initial value */ + + do { + int i; - iteration++; - tmp_mp.exclude [iteration] = NO_EDGE; - - for (i = 0; isdomain (tmp_mp.indices [i]); i++) - if (tmp_mp.weight [i] == 0) - { - tmp_mp.exclude [iteration] = tmp_mp.indices [i]; - break; - } + ++iteration; + tmp_mp.exclude[iteration] = NO_EDGE; + + for (i = 0; isdomain (tmp_mp.indices [i]); ++i) { + rpf_t * const rpf = + tmp_mp.indices [i] ? coeff->rpf : coeff->dc_rpf; + + if (tmp_mp.weight [i] == btor (rtob (200, rpf), rpf) + || tmp_mp.weight [i] == btor (rtob (-200, rpf), rpf)) { + tmp_mp.exclude [iteration] = tmp_mp.indices [i]; + break; + } + } - if (isdomain (tmp_mp.exclude [iteration])) /* try again */ - { - tmp_mp.exclude [iteration + 1] = NO_EDGE; - - matching_pursuit (&tmp_mp, c->options.full_search, price, - max_edges, y_state, range, domain_pool, - coeff, wfa, c); - if (tmp_mp.costs < mp.costs) /* success */ - { - success = YES; - mp = tmp_mp; - } - } - } while (isdomain (tmp_mp.exclude [iteration]) - && iteration < MAXEDGES - 1); - } - - /* - * Next approximation attempt: check whether some coefficients have - * been quantized to +/- max-value. Vectors causing the overflow are - * removed from the domain pool and then the matching pursuit - * algorithm is run again (until overflow doesn't occur anymore). - */ - if (c->options.check_for_overflow) - { - int iteration = -1; - mp_t tmp_mp = mp; - - do - { - int i; - - iteration++; - tmp_mp.exclude [iteration] = NO_EDGE; - - for (i = 0; isdomain (tmp_mp.indices [i]); i++) - { - rpf_t *rpf = tmp_mp.indices [i] ? coeff->rpf : coeff->dc_rpf; - - if (tmp_mp.weight [i] == btor (rtob (200, rpf), rpf) - || tmp_mp.weight [i] == btor (rtob (-200, rpf), rpf)) - { - tmp_mp.exclude [iteration] = tmp_mp.indices [i]; - break; - } - } + if (isdomain(tmp_mp.exclude[iteration])) { + /* try again */ + tmp_mp.exclude[iteration + 1] = NO_EDGE; + + matching_pursuit(&tmp_mp, c->options.full_search, price, + max_edges, y_state, range, domain_pool, + coeff, wfa, c); + if (tmp_mp.costs < mp.costs) /* success */ + mp = tmp_mp; + } + } while (isdomain (tmp_mp.exclude [iteration]) + && iteration < MAXEDGES - 1); + } + + /* + * Finally, check whether the best approximation has costs + * smaller than 'max_costs'. + */ + if (mp.costs < max_costs) { + int edge; + int new_index, old_index; + + new_index = 0; + for (old_index = 0; isdomain (mp.indices[old_index]); ++old_index) { + if (mp.weight [old_index] != 0) { + mp.indices [new_index] = mp.indices [old_index]; + mp.into [new_index] = mp.into [old_index]; + mp.weight [new_index] = mp.weight [old_index]; + ++new_index; + } + } + mp.indices [new_index] = NO_EDGE; + mp.into [new_index] = NO_EDGE; + + /* + * Update of probability models + */ + { + word_t * const domain_blocks = + domain_pool->generate(range->level, y_state, + wfa, + domain_pool->model); + domain_pool->update(domain_blocks, mp.indices, + range->level, y_state, wfa, + domain_pool->model); + coeff->update (mp.weight, mp.into, range->level, coeff); + + Free(domain_blocks); + } - if (isdomain (tmp_mp.exclude [iteration])) /* try again */ - { - tmp_mp.exclude [iteration + 1] = NO_EDGE; - - matching_pursuit (&tmp_mp, c->options.full_search, price, - max_edges, y_state, range, domain_pool, - coeff, wfa, c); - if (tmp_mp.costs < mp.costs) /* success */ - { - success = YES; - mp = tmp_mp; - } - } - } while (isdomain (tmp_mp.exclude [iteration]) - && iteration < MAXEDGES - 1); - } - - /* - * Finally, check whether the best approximation has costs - * smaller than 'max_costs'. - */ - if (mp.costs < max_costs) - { - int edge; - bool_t overflow = NO; - bool_t underflow = NO; - int new_index, old_index; - - new_index = 0; - for (old_index = 0; isdomain (mp.indices [old_index]); old_index++) - if (mp.weight [old_index] != 0) - { - rpf_t *rpf = mp.indices [old_index] ? coeff->rpf : coeff->dc_rpf; - - if (mp.weight [old_index] == btor (rtob (200, rpf), rpf) - || mp.weight [old_index] == btor (rtob (-200, rpf), rpf)) - overflow = YES; - - mp.indices [new_index] = mp.indices [old_index]; - mp.into [new_index] = mp.into [old_index]; - mp.weight [new_index] = mp.weight [old_index]; - new_index++; - } - else - underflow = YES; - - mp.indices [new_index] = NO_EDGE; - mp.into [new_index] = NO_EDGE; - - /* - * Update of probability models - */ - { - word_t *domain_blocks = domain_pool->generate (range->level, y_state, - wfa, - domain_pool->model); - domain_pool->update (domain_blocks, mp.indices, - range->level, y_state, wfa, domain_pool->model); - coeff->update (mp.weight, mp.into, range->level, coeff); - - Free (domain_blocks); - } - - for (edge = 0; isedge (mp.indices [edge]); edge++) - { - range->into [edge] = mp.into [edge]; - range->weight [edge] = mp.weight [edge]; - } - range->into [edge] = NO_EDGE; - range->matrix_bits = mp.matrix_bits; - range->weights_bits = mp.weights_bits; - range->err = mp.err; - } - else - { - range->into [0] = NO_EDGE; - mp.costs = MAXCOSTS; - } + for (edge = 0; isedge (mp.indices [edge]); ++edge) { + range->into [edge] = mp.into [edge]; + range->weight [edge] = mp.weight [edge]; + } + range->into [edge] = NO_EDGE; + range->matrix_bits = mp.matrix_bits; + range->weights_bits = mp.weights_bits; + range->err = mp.err; + } else { + range->into [0] = NO_EDGE; + mp.costs = MAXCOSTS; + } - return mp.costs; + return mp.costs; } + + /***************************************************************************** - local variables + local variables *****************************************************************************/ @@ -310,15 +288,15 @@ static bool_t used [MAXSTATES]; /***************************************************************************** - private code + private code *****************************************************************************/ static void matching_pursuit (mp_t *mp, bool_t full_search, real_t price, - unsigned max_edges, int y_state, const range_t *range, - const domain_pool_t *domain_pool, const coeff_t *coeff, - const wfa_t *wfa, const coding_t *c) + unsigned max_edges, int y_state, const range_t *range, + const domain_pool_t *domain_pool, const coeff_t *coeff, + const wfa_t *wfa, const coding_t *c) /* * Find an approximation of the current 'range' with a linear * combination of vectors of the 'domain_pool'. The linear @@ -339,311 +317,318 @@ matching_pursuit (mp_t *mp, bool_t full_search, real_t price, * No return value. * * Side effects: - * vectors, factors, rate, distortion and costs are stored in 'mp' + * vectors, factors, rate, distortion and costs are stored in 'mp' */ { - unsigned n; /* current vector of the OB */ - int index; /* best fitting domain image */ - unsigned domain; /* counter */ - real_t norm; /* norm of range image */ - real_t additional_bits; /* bits for mc, nd, and tree */ - word_t *domain_blocks; /* current set of domain images */ - const real_t min_norm = 2e-3; /* lower bound of norm */ - unsigned best_n = 0; - unsigned size = size_of_level (range->level); + unsigned n; /* current vector of the OB */ + int index; /* best fitting domain image */ + unsigned domain; /* counter */ + real_t norm; /* norm of range image */ + real_t additional_bits; /* bits for mc, nd, and tree */ + word_t *domain_blocks; /* current set of domain images */ + const real_t min_norm = 2e-3; /* lower bound of norm */ + unsigned best_n = 0; + unsigned size = size_of_level (range->level); - /* - * Initialize domain pool and inner product arrays - */ - domain_blocks = domain_pool->generate (range->level, y_state, wfa, - domain_pool->model); - for (domain = 0; domain_blocks [domain] >= 0; domain++) - { - used [domain] = NO; - rem_denominator [domain] /* norm of domain */ - = get_ip_state_state (domain_blocks [domain], domain_blocks [domain], - range->level, c); - if (rem_denominator [domain] / size < min_norm) - used [domain] = YES; /* don't use domains with small norm */ - else - rem_numerator [domain] /* inner product <s_domain, b> */ - = get_ip_image_state (range->image, range->address, - range->level, domain_blocks [domain], c); - if (!used [domain] && fabs (rem_numerator [domain]) < min_norm) - used [domain] = YES; - } - - /* - * Exclude all domain blocks given in array 'mp->exclude' - */ - for (n = 0; isdomain (mp->exclude [n]); n++) - used [mp->exclude [n]] = YES; - - /* - * Compute the approximation costs if 'range' is approximated with - * no linear combination, i.e. the error is equal to the square - * of the image norm and the size of the automaton is determined by - * storing only zero elements in the current matrix row - */ - for (norm = 0, n = 0; n < size; n++) - norm += square (c->pixels [range->address * size + n]); - - additional_bits = range->tree_bits + range->mv_tree_bits - + range->mv_coord_bits + range->nd_tree_bits - + range->nd_weights_bits; - - mp->err = norm; - mp->weights_bits = 0; - mp->matrix_bits = domain_pool->bits (domain_blocks, NULL, range->level, - y_state, wfa, domain_pool->model); - mp->costs = (mp->matrix_bits + mp->weights_bits - + additional_bits) * price + mp->err; - - n = 0; - do - { - /* - * Current approximation is: b = d_0 o_0 + ... + d_(n-1) o_(n-1) - * with corresponding costs 'range->err + range->bits * p'. - * For all remaining state images s_i (used[s_i] == NO) set - * o_n : = s_i - \sum(k = 0, ... , n-1) {(<s_i, o_k> / ||o_k||^2) o_k} - * and try to beat current costs. - * Choose that vector for the next orthogonalization step, - * which has minimal costs: s_index. - * (No progress is indicated by index == -1) - */ + /* + * Initialize domain pool and inner product arrays + */ + domain_blocks = domain_pool->generate (range->level, y_state, wfa, + domain_pool->model); + for (domain = 0; domain_blocks [domain] >= 0; domain++) + { + used [domain] = NO; + rem_denominator [domain] = /* norm of domain */ + get_ip_state_state (domain_blocks [domain], domain_blocks [domain], + range->level, c); + if (rem_denominator [domain] / size < min_norm) + used [domain] = YES; /* don't use domains with small norm */ + else + rem_numerator [domain] /* inner product <s_domain, b> */ + = get_ip_image_state (range->image, range->address, + range->level, domain_blocks [domain], c); + if (!used [domain] && fabs (rem_numerator [domain]) < min_norm) + used [domain] = YES; + } + + /* + * Exclude all domain blocks given in array 'mp->exclude' + */ + for (n = 0; isdomain (mp->exclude [n]); n++) + used [mp->exclude [n]] = YES; + + /* + * Compute the approximation costs if 'range' is approximated with + * no linear combination, i.e. the error is equal to the square + * of the image norm and the size of the automaton is determined by + * storing only zero elements in the current matrix row + */ + for (norm = 0, n = 0; n < size; n++) + norm += square (c->pixels [range->address * size + n]); + + additional_bits = range->tree_bits + range->mv_tree_bits + + range->mv_coord_bits + range->nd_tree_bits + + range->nd_weights_bits; + + mp->err = norm; + mp->weights_bits = 0; + mp->matrix_bits = domain_pool->bits (domain_blocks, NULL, range->level, + y_state, wfa, domain_pool->model); + mp->costs = (mp->matrix_bits + mp->weights_bits + + additional_bits) * price + mp->err; + + n = 0; + do + { + /* + * Current approximation is: b = d_0 o_0 + ... + d_(n-1) o_(n-1) + * with corresponding costs 'range->err + range->bits * p'. + * For all remaining state images s_i (used[s_i] == NO) set + * o_n : = s_i - \sum(k = 0, ... , n-1) {(<s_i, o_k> / ||o_k||^2) o_k} + * and try to beat current costs. + * Choose that vector for the next orthogonalization step, + * which has minimal costs: s_index. + * (No progress is indicated by index == -1) + */ - real_t min_matrix_bits = 0; - real_t min_weights_bits = 0; - real_t min_error = 0; - real_t min_weight [MAXEDGES]; - real_t min_costs = full_search ? MAXCOSTS : mp->costs; + real_t min_matrix_bits = 0; + real_t min_weights_bits = 0; + real_t min_error = 0; + real_t min_weight [MAXEDGES]; + real_t min_costs = full_search ? MAXCOSTS : mp->costs; - for (index = -1, domain = 0; domain_blocks [domain] >= 0; domain++) - if (!used [domain]) - { - real_t matrix_bits, weights_bits; - /* - * To speed up the search through the domain images, - * the costs of using domain image 'domain' as next vector - * can be approximated in a first step: - * improvement of image quality - * <= square (rem_numerator[domain]) / rem_denominator[domain] - */ - { - word_t vectors [MAXEDGES + 1]; - word_t states [MAXEDGES + 1]; - real_t weights [MAXEDGES + 1]; - unsigned i, k; - - for (i = 0, k = 0; k < n; k++) - if (mp->weight [k] != 0) - { - vectors [i] = mp->indices [k]; - states [i] = domain_blocks [vectors [i]]; - weights [i] = mp->weight [k]; - i++; - } - vectors [i] = domain; - states [i] = domain_blocks [domain]; - weights [i] = 0.5; - vectors [i + 1] = -1; - states [i + 1] = -1; - - weights_bits = coeff->bits (weights, states, range->level, - coeff); - matrix_bits = domain_pool->bits (domain_blocks, vectors, - range->level, y_state, - wfa, domain_pool->model); - } - if (((matrix_bits + weights_bits + additional_bits) * price + - mp->err - - square (rem_numerator [domain]) / rem_denominator [domain]) - < min_costs) - { - /* - * 1.) Compute the weights (linear factors) c_i of the - * linear combination - * b = c_0 v_0 + ... + c_(n-1) v_(n-1) + c_n v_'domain' - * Use backward substitution to obtain c_i from the linear - * factors of the lin. comb. b = d_0 o_0 + ... + d_n o_n - * of the corresponding orthogonal vectors {o_0, ..., o_n}. - * Vector o_n of the orthogonal basis is obtained by using - * vector 'v_domain' in step n of the Gram Schmidt - * orthogonalization (see above for definition of o_n). - * Recursive formula for the coefficients c_i: - * c_n := <b, o_n> / ||o_n||^2 - * for i = n - 1, ... , 0: - * c_i := <b, o_i> / ||o_i||^2 + - * \sum (k = i + 1, ... , n){ c_k <v_k, o_i> - * / ||o_i||^2 } - * 2.) Because linear factors are stored with reduced precision - * factor c_i is rounded with the given precision in step i - * of the recursive formula. - */ - - unsigned k; /* counter */ - int l; /* counter */ - real_t m_bits; /* number of matrix bits to store */ - real_t w_bits; /* number of weights bits to store */ - real_t r [MAXEDGES]; /* rounded linear factors */ - real_t f [MAXEDGES]; /* linear factors */ - int v [MAXEDGES]; /* mapping of domains to vectors */ - real_t costs; /* current approximation costs */ - real_t m_err; /* current approximation error */ - - f [n] = rem_numerator [domain] / rem_denominator [domain]; - v [n] = domain; /* corresponding mapping */ - for (k = 0; k < n; k++) - { - f [k] = ip_image_ortho_vector [k] / norm_ortho_vector [k]; - v [k] = mp->indices [k]; - } - - for (l = n; l >= 0; l--) - { - rpf_t *rpf = domain_blocks [v [l]] - ? coeff->rpf : coeff->dc_rpf; - - r [l] = f [l] = btor (rtob (f [l], rpf), rpf); - - for (k = 0; k < (unsigned) l; k++) - f [k] -= f [l] * ip_domain_ortho_vector [v [l]][k] - / norm_ortho_vector [k] ; - } - - /* - * Compute the number of output bits of the linear combination - * and store the weights with reduced precision. The - * resulting linear combination is - * b = r_0 v_0 + ... + r_(n-1) v_(n-1) + r_n v_'domain' - */ - { - word_t vectors [MAXEDGES + 1]; - word_t states [MAXEDGES + 1]; - real_t weights [MAXEDGES + 1]; - int i; - - for (i = 0, k = 0; k <= n; k++) - if (f [k] != 0) - { - vectors [i] = v [k]; - states [i] = domain_blocks [v [k]]; - weights [i] = f [k]; - i++; - } - vectors [i] = -1; - states [i] = -1; - - w_bits = coeff->bits (weights, states, range->level, coeff); - m_bits = domain_pool->bits (domain_blocks, vectors, - range->level, y_state, - wfa, domain_pool->model); - } - - /* - * To compute the approximation error, the corresponding - * linear factors of the linear combination - * b = r_0 o_0 + ... + r_(n-1) o_(n-1) + r_n o_'domain' - * with orthogonal vectors must be computed with following - * formula: - * r_i := r_i + - * \sum (k = i + 1, ... , n) { r_k <v_k, o_i> - * / ||o_i||^2 } - */ - for (l = 0; (unsigned) l <= n; l++) - { - /* - * compute <v_n, o_n> - */ - real_t a; - - a = get_ip_state_state (domain_blocks [v [l]], - domain_blocks [domain], - range->level, c); - for (k = 0; k < n; k++) - a -= ip_domain_ortho_vector [v [l]][k] - / norm_ortho_vector [k] - * ip_domain_ortho_vector [domain][k]; - ip_domain_ortho_vector [v [l]][n] = a; - } - norm_ortho_vector [n] = rem_denominator [domain]; - ip_image_ortho_vector [n] = rem_numerator [domain]; - - for (k = 0; k <= n; k++) - for (l = k + 1; (unsigned) l <= n; l++) - r [k] += ip_domain_ortho_vector [v [l]][k] * r [l] - / norm_ortho_vector [k]; - /* - * Compute approximation error: - * error := ||b||^2 + - * \sum (k = 0, ... , n){r_k^2 ||o_k||^2 - 2 r_k <b, o_k>} - */ - m_err = norm; - for (k = 0; k <= n; k++) - m_err += square (r [k]) * norm_ortho_vector [k] - - 2 * r [k] * ip_image_ortho_vector [k]; - if (m_err < 0) /* TODO: return MAXCOSTS */ - warning ("Negative image norm: %f" - " (current domain: %d, level = %d)", - (double) m_err, domain, range->level); - - costs = (m_bits + w_bits + additional_bits) * price + m_err; - if (costs < min_costs) /* found a better approximation */ - { - index = domain; - min_costs = costs; - min_matrix_bits = m_bits; - min_weights_bits = w_bits; - min_error = m_err; - for (k = 0; k <= n; k++) - min_weight [k] = f [k]; - } - } - } + for (index = -1, domain = 0; domain_blocks [domain] >= 0; domain++) + if (!used [domain]) + { + real_t matrix_bits, weights_bits; + /* + * To speed up the search through the domain images, + * the costs of using domain image 'domain' as next vector + * can be approximated in a first step: + * improvement of image quality + * <= square (rem_numerator[domain]) / rem_denominator[domain] + */ + { + word_t vectors [MAXEDGES + 1]; + word_t states [MAXEDGES + 1]; + real_t weights [MAXEDGES + 1]; + unsigned i, k; + + for (i = 0, k = 0; k < n; k++) + if (mp->weight [k] != 0) + { + vectors [i] = mp->indices [k]; + states [i] = domain_blocks [vectors [i]]; + weights [i] = mp->weight [k]; + i++; + } + vectors [i] = domain; + states [i] = domain_blocks [domain]; + weights [i] = 0.5; + vectors [i + 1] = -1; + states [i + 1] = -1; + + weights_bits = coeff->bits (weights, states, range->level, + coeff); + matrix_bits = domain_pool->bits (domain_blocks, vectors, + range->level, y_state, + wfa, domain_pool->model); + } + if (((matrix_bits + weights_bits + additional_bits) * price + + mp->err - + square (rem_numerator[domain]) / rem_denominator[domain]) + < min_costs) + { + /* + * 1.) Compute the weights (linear factors) c_i of the + * linear combination + * b = c_0 v_0 + ... + c_(n-1) v_(n-1) + c_n v_'domain' + * Use backward substitution to obtain c_i from the linear + * factors of the lin. comb. b = d_0 o_0 + ... + d_n o_n + * of the corresponding orthogonal vectors {o_0, ..., o_n}. + * Vector o_n of the orthogonal basis is obtained by using + * vector 'v_domain' in step n of the Gram Schmidt + * orthogonalization (see above for definition of o_n). + * Recursive formula for the coefficients c_i: + * c_n := <b, o_n> / ||o_n||^2 + * for i = n - 1, ... , 0: + * c_i := <b, o_i> / ||o_i||^2 + + * \sum (k = i + 1, ... , n){ c_k <v_k, o_i> + * / ||o_i||^2 } + * 2.) Because linear factors are stored with reduced + * precision factor c_i is rounded with the given + * precision in step i of the recursive formula. + */ + + unsigned k; /* counter */ + int l; /* counter */ + real_t m_bits; /* number of matrix bits to store */ + real_t w_bits; /* number of weights bits to store */ + real_t r [MAXEDGES]; /* rounded linear factors */ + real_t f [MAXEDGES]; /* linear factors */ + int v [MAXEDGES]; /* mapping of domains to vectors*/ + real_t costs; /* current approximation costs */ + real_t m_err; /* current approximation error */ + + f [n] = rem_numerator [domain] / rem_denominator [domain]; + v [n] = domain; /* corresponding mapping */ + for (k = 0; k < n; k++) + { + f[k] = ip_image_ortho_vector[k] / norm_ortho_vector[k]; + v [k] = mp->indices [k]; + } + + for (l = n; l >= 0; --l) { + rpf_t * const rpf = domain_blocks[v[l]] + ? coeff->rpf : coeff->dc_rpf; + + unsigned int k; + + r[l] = f[l] = btor(rtob(f[l], rpf), rpf); + + { + real_t const fl = f[l]; + + for (k = 0; k < l; ++k) { + f[k] -= fl * ip_domain_ortho_vector[v[l]][k] + / norm_ortho_vector[k]; + } + } + } + + /* + * Compute the number of output bits of the linear + * combination and store the weights with reduced + * precision. The resulting linear combination is + * b = r_0 v_0 + ... + r_(n-1) v_(n-1) + r_n v_'domain' + */ + { + word_t vectors [MAXEDGES + 1]; + word_t states [MAXEDGES + 1]; + real_t weights [MAXEDGES + 1]; + int i; + + for (i = 0, k = 0; k <= n; k++) + if (f [k] != 0) + { + vectors [i] = v [k]; + states [i] = domain_blocks [v [k]]; + weights [i] = f [k]; + i++; + } + vectors [i] = -1; + states [i] = -1; + + w_bits = + coeff->bits(weights, states, range->level, coeff); + m_bits = domain_pool->bits (domain_blocks, vectors, + range->level, y_state, + wfa, domain_pool->model); + } + + /* + * To compute the approximation error, the corresponding + * linear factors of the linear combination + * b = r_0 o_0 + ... + r_(n-1) o_(n-1) + r_n o_'domain' + * with orthogonal vectors must be computed with following + * formula: + * r_i := r_i + + * \sum (k = i + 1, ... , n) { r_k <v_k, o_i> + * / ||o_i||^2 } + */ + for (l = 0; (unsigned) l <= n; l++) + { + /* + * compute <v_n, o_n> + */ + real_t a; + + a = get_ip_state_state (domain_blocks [v [l]], + domain_blocks [domain], + range->level, c); + for (k = 0; k < n; k++) + a -= ip_domain_ortho_vector [v [l]][k] + / norm_ortho_vector [k] + * ip_domain_ortho_vector [domain][k]; + ip_domain_ortho_vector [v [l]][n] = a; + } + norm_ortho_vector [n] = rem_denominator [domain]; + ip_image_ortho_vector [n] = rem_numerator [domain]; + + for (k = 0; k <= n; k++) + for (l = k + 1; (unsigned) l <= n; l++) + r [k] += ip_domain_ortho_vector [v [l]][k] * r [l] + / norm_ortho_vector [k]; + /* + * Compute approximation error: + * error := ||b||^2 + + * \sum (k = 0, ... , n){r_k^2 ||o_k||^2 - 2 r_k <b, o_k>} + */ + m_err = norm; + for (k = 0; k <= n; k++) + m_err += square (r [k]) * norm_ortho_vector [k] + - 2 * r [k] * ip_image_ortho_vector [k]; + if (m_err < 0) /* TODO: return MAXCOSTS */ + warning ("Negative image norm: %f" + " (current domain: %d, level = %d)", + (double) m_err, domain, range->level); + + costs = (m_bits + w_bits + additional_bits) * price + m_err; + if (costs < min_costs) /* found a better approximation */ + { + index = domain; + min_costs = costs; + min_matrix_bits = m_bits; + min_weights_bits = w_bits; + min_error = m_err; + for (k = 0; k <= n; k++) + min_weight [k] = f [k]; + } + } + } - if (index >= 0) /* found a better approximation */ - { - if (min_costs < mp->costs) - { - unsigned k; - - mp->costs = min_costs; - mp->err = min_error; - mp->matrix_bits = min_matrix_bits; - mp->weights_bits = min_weights_bits; - - for (k = 0; k <= n; k++) - mp->weight [k] = min_weight [k]; - - best_n = n + 1; - } - - mp->indices [n] = index; - mp->into [n] = domain_blocks [index]; - - used [index] = YES; - - /* - * Gram-Schmidt orthogonalization step n - */ - orthogonalize (index, n, range->level, min_norm, domain_blocks, c); - n++; - } - } - while (n < max_edges && index >= 0); - - mp->indices [best_n] = NO_EDGE; + if (index >= 0) /* found a better approximation */ + { + if (min_costs < mp->costs) + { + unsigned k; + + mp->costs = min_costs; + mp->err = min_error; + mp->matrix_bits = min_matrix_bits; + mp->weights_bits = min_weights_bits; + + for (k = 0; k <= n; k++) + mp->weight [k] = min_weight [k]; + + best_n = n + 1; + } + + mp->indices [n] = index; + mp->into [n] = domain_blocks [index]; + + used [index] = YES; + + /* + * Gram-Schmidt orthogonalization step n + */ + orthogonalize (index, n, range->level, min_norm, domain_blocks, c); + n++; + } + } + while (n < max_edges && index >= 0); + + mp->indices [best_n] = NO_EDGE; - mp->costs = (mp->matrix_bits + mp->weights_bits + additional_bits) * price - + mp->err; + mp->costs = (mp->matrix_bits + mp->weights_bits + additional_bits) * price + + mp->err; - Free (domain_blocks); + Free (domain_blocks); } static void orthogonalize (unsigned index, unsigned n, unsigned level, real_t min_norm, - const word_t *domain_blocks, const coding_t *c) + const word_t *domain_blocks, const coding_t *c) /* * Step 'n' of the Gram-Schmidt orthogonalization procedure: * vector 'index' is orthogonalized with respect to the set @@ -655,8 +640,8 @@ orthogonalize (unsigned index, unsigned n, unsigned level, real_t min_norm, * No return value. * * Side effects: - * The remainder values (numerator and denominator) of - * all 'domain_blocks' are updated. + * The remainder values (numerator and denominator) of + * all 'domain_blocks' are updated. */ { unsigned domain; @@ -676,25 +661,25 @@ orthogonalize (unsigned index, unsigned n, unsigned level, real_t min_norm, for (domain = 0; domain_blocks [domain] >= 0; domain++) if (!used [domain]) { - unsigned k; - real_t tmp = get_ip_state_state (domain_blocks [index], - domain_blocks [domain], level, c); - - for (k = 0; k < n; k++) - tmp -= ip_domain_ortho_vector [domain][k] / norm_ortho_vector [k] - * ip_domain_ortho_vector [index][k]; - ip_domain_ortho_vector [domain][n] = tmp; - rem_denominator [domain] -= square (tmp) / norm_ortho_vector [n]; - rem_numerator [domain] -= ip_image_ortho_vector [n] - / norm_ortho_vector [n] - * ip_domain_ortho_vector [domain][n] ; - - /* - * Exclude vectors with small denominator - */ - if (!used [domain]) - if (rem_denominator [domain] / size_of_level (level) < min_norm) - used [domain] = YES; + unsigned k; + real_t tmp = get_ip_state_state (domain_blocks [index], + domain_blocks [domain], level, c); + + for (k = 0; k < n; k++) + tmp -= ip_domain_ortho_vector [domain][k] / norm_ortho_vector [k] + * ip_domain_ortho_vector [index][k]; + ip_domain_ortho_vector [domain][n] = tmp; + rem_denominator [domain] -= square (tmp) / norm_ortho_vector [n]; + rem_numerator [domain] -= ip_image_ortho_vector [n] + / norm_ortho_vector [n] + * ip_domain_ortho_vector [domain][n] ; + + /* + * Exclude vectors with small denominator + */ + if (!used [domain]) + if (rem_denominator [domain] / size_of_level (level) < min_norm) + used [domain] = YES; } } diff --git a/converter/other/fiasco/codec/approx.h b/converter/other/fiasco/codec/approx.h index c54b78c9..42f1458a 100644 --- a/converter/other/fiasco/codec/approx.h +++ b/converter/other/fiasco/codec/approx.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/bintree.c b/converter/other/fiasco/codec/bintree.c index ddd74e15..b050ab63 100644 --- a/converter/other/fiasco/codec/bintree.c +++ b/converter/other/fiasco/codec/bintree.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/bintree.h b/converter/other/fiasco/codec/bintree.h index cdb80c94..3dc88ac1 100644 --- a/converter/other/fiasco/codec/bintree.h +++ b/converter/other/fiasco/codec/bintree.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/coder.c b/converter/other/fiasco/codec/coder.c index 94e367dd..1e21994d 100644 --- a/converter/other/fiasco/codec/coder.c +++ b/converter/other/fiasco/codec/coder.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -14,6 +14,7 @@ * $State: Exp $ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ diff --git a/converter/other/fiasco/codec/coder.h b/converter/other/fiasco/codec/coder.h index c6f4bb7c..2fe81d81 100644 --- a/converter/other/fiasco/codec/coder.h +++ b/converter/other/fiasco/codec/coder.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/coeff.c b/converter/other/fiasco/codec/coeff.c index 0cd64f17..6d33bad5 100644 --- a/converter/other/fiasco/codec/coeff.c +++ b/converter/other/fiasco/codec/coeff.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/coeff.h b/converter/other/fiasco/codec/coeff.h index 118cd0fc..6193e2ee 100644 --- a/converter/other/fiasco/codec/coeff.h +++ b/converter/other/fiasco/codec/coeff.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/control.c b/converter/other/fiasco/codec/control.c index 94c23c83..2ea06052 100644 --- a/converter/other/fiasco/codec/control.c +++ b/converter/other/fiasco/codec/control.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/control.h b/converter/other/fiasco/codec/control.h index f601d8b8..6c0834a1 100644 --- a/converter/other/fiasco/codec/control.h +++ b/converter/other/fiasco/codec/control.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/cwfa.h b/converter/other/fiasco/codec/cwfa.h index 9c4e7fee..dd86fbfc 100644 --- a/converter/other/fiasco/codec/cwfa.h +++ b/converter/other/fiasco/codec/cwfa.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/decoder.c b/converter/other/fiasco/codec/decoder.c index 26284596..229996b6 100644 --- a/converter/other/fiasco/codec/decoder.c +++ b/converter/other/fiasco/codec/decoder.c @@ -3,11 +3,11 @@ * * Written by: Ullrich Hafner * Michael Unger - * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ - + /* * $Date: 2000/10/22 10:44:48 $ * $Author: hafner $ @@ -37,7 +37,7 @@ /***************************************************************************** prototypes - + *****************************************************************************/ static void @@ -63,7 +63,7 @@ duplicate_state_image (const word_t *domain, unsigned offset, unsigned level); /***************************************************************************** public code - + *****************************************************************************/ video_t * @@ -78,7 +78,7 @@ alloc_video (bool_t store_wfa) */ { video_t *video = Calloc (1, sizeof (video_t)); - + video->future_display = -1; video->display = 0; @@ -138,13 +138,13 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, * Get next frame of the WFA 'video' from stream 'input'. * 'orig_wfa' is the constant part of the WFA used by all frames. * Depending on values of 'enlarge_factor' and 'smoothing' enlarge and - * smooth image, respectively. + * smooth image, respectively. * If 'store_wfa' is TRUE, then store WFA structure of reference frames * (used by analysis tool xwfa). * If 'reference_frame' is not NULL, then load image 'reference_frame' * from disk. * 'format' gives the color format to be used (either 4:2:0 or 4:4:4). - * If 'timer' is not NULL, then accumulate running time statistics. + * If 'timer' is not NULL, then accumulate running time statistics. * * Return value: * pointer to decoded frame @@ -157,7 +157,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, image_t *sframe = NULL; /* current smoothed frame */ bool_t current_frame_is_future_frame = NO; - if (video->future_display == video->display) + if (video->future_display == video->display) { /* * Future frame is already computed since it has been used @@ -189,7 +189,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, clock_t ptimer; unsigned int stop_timer [3]; wfa_t *tmp_wfa = NULL; - + if (!store_wfa) video->wfa = orig_wfa; else @@ -198,7 +198,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, copy_wfa (tmp_wfa, video->wfa); copy_wfa (video->wfa, orig_wfa); } - + /* * First step: read WFA from disk */ @@ -210,7 +210,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, timer->input [video->wfa->frame_type] += stop_timer [0]; timer->frames [video->wfa->frame_type]++; } - + /* * Read reference frame from disk if required * (i.e., 1st frame is of type B or P) @@ -225,7 +225,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, video->frame = read_image_file (reference_frame); video->sframe = NULL; } - + /* * Depending on current frame type update past and future frames */ @@ -313,7 +313,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, } if (tmp_wfa) free_wfa (tmp_wfa); - + current_frame_is_future_frame = NO; /* * Second step: decode image @@ -323,7 +323,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, unsigned orig_width, orig_height; stop_timer [0] = stop_timer [1] = stop_timer [2] = 0; - + enlarge_image (enlarge_factor, format, (video->wfa->wfainfo->color && format == FORMAT_4_2_0) @@ -332,10 +332,10 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, if (enlarge_factor > 0) { orig_width = video->wfa->wfainfo->width << enlarge_factor; - orig_height = video->wfa->wfainfo->height << enlarge_factor; + orig_height = video->wfa->wfainfo->height << enlarge_factor; } else - { + { orig_width = video->wfa->wfainfo->width >> - enlarge_factor; orig_height = video->wfa->wfainfo->height >> - enlarge_factor; if (orig_width & 1) @@ -343,7 +343,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, if (orig_height & 1) orig_height++; } - + frame = decode_image (orig_width, orig_height, format, timer != NULL ? stop_timer : NULL, video->wfa); @@ -381,7 +381,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, } else sframe = NULL; - + stop_timer [0] = prg_timer (&ptimer, STOP); if (timer) timer->smooth [video->wfa->frame_type] += stop_timer [0]; @@ -399,7 +399,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, video->future_display = frame_number; current_frame_is_future_frame = YES; } - + if (!store_wfa) remove_states (video->wfa->basis_states, video->wfa); } while (!video->frame); @@ -407,7 +407,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, if (!store_wfa) video->wfa = NULL; } - + return video->sframe ? video->sframe : video->frame; } @@ -418,8 +418,8 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, * Compute image which is represented by the given 'wfa'. * 'orig_width'x'orig_height' gives the resolution of the image at * coding time. Use 4:2:0 subsampling or 4:4:4 'format' for color images. - * If 'dec_timer' is given, accumulate running time statistics. - * + * If 'dec_timer' is given, accumulate running time statistics. + * * Return value: * pointer to decoded image * @@ -458,7 +458,7 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, for (max_level = 0, state = wfa->basis_states; state < wfa->states; state++) if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0])) max_level = MAX(max_level, wfa->level_of_state [state]); - + /* * Allocate frame buffer for decoded image @@ -468,7 +468,7 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, width = MAX(width, orig_width); height = MAX(height, orig_height); frame = alloc_image (width, height, wfa->wfainfo->color, format); - + /* * Allocate buffers for intermediate state images */ @@ -478,7 +478,7 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, wfa->level_of_state [wfa->tree[wfa->root_state][0]] = 128; wfa->level_of_state [wfa->tree[wfa->root_state][1]] = 128; } - alloc_state_images (&images, &offsets, frame, root_state, 0, max_level, + alloc_state_images (&images, &offsets, frame, root_state, 0, max_level, format, wfa); if (dec_timer) @@ -498,20 +498,20 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, prg_timer (&ptimer, START); free_state_images (max_level, frame->color, images, offsets, root_state, 0, format, wfa); - + /* * Crop decoded image if the image size differs. */ if (orig_width != width || orig_height != height) { - frame->height = orig_height; - frame->width = orig_width; - if (orig_width != width) + frame->height = orig_height; + frame->width = orig_width; + if (orig_width != width) { color_e band; /* current color band */ word_t *src, *dst; /* source and destination pointers */ unsigned y; /* current row */ - + for (band = first_band (frame->color); band <= last_band (frame->color); band++) { @@ -546,7 +546,7 @@ decode_state (unsigned state, unsigned level, wfa_t *wfa) * pointer to decoded state image * * Side effects: - * 'wfa' states > 'state' are removed. + * 'wfa' states > 'state' are removed. */ { word_t *domains [2]; @@ -571,7 +571,7 @@ decode_state (unsigned state, unsigned level, wfa_t *wfa) { word_t *src, *dst; unsigned y; - + src = domains [0]; dst = img->pixels [GRAY]; for (y = img->height; y; y--) @@ -603,75 +603,73 @@ decode_range (unsigned range_state, unsigned range_label, unsigned range_level, * 'wfa->level_of_state []' is changed */ { - unsigned root_state [3]; /* dummy (for alloc_state_images) */ - image_t *state_image; /* regenerated state image */ - word_t **images; /* pointer to array of pointers - to state images */ - u_word_t *offsets; /* pointer to array of state image - offsets */ - word_t *range; - - enlarge_image (range_level - (wfa->level_of_state [range_state] - 1), - FORMAT_4_4_4, -1, wfa); - root_state [0] = range_state; - state_image = alloc_image (width_of_level (range_level + 1), - height_of_level (range_level + 1), - NO, FORMAT_4_4_4); - alloc_state_images (&images, &offsets, state_image, NULL, range_state, - range_level + 1, NO, wfa); - compute_state_images (range_level + 1, images, offsets, wfa); - - range = Calloc (size_of_level (range_level), sizeof (word_t)); - - if ((range_level & 1) == 0) /* square image */ - { - memcpy (range, - images [range_state + (range_level + 1) * wfa->states] - + range_label * size_of_level (range_level), - size_of_level (range_level) * sizeof (word_t)); - } - else /* rectangle */ - { - word_t *src, *dst; - unsigned y; - - src = images [range_state + (range_level + 1) * wfa->states] - + range_label * width_of_level (range_level); - dst = range; - for (y = height_of_level (range_level); y; y--) - { - memcpy (dst, src, width_of_level (range_level) * sizeof (word_t)); - dst += width_of_level (range_level); - src += width_of_level (range_level + 1); - } - } - - if (domain != NULL) /* copy domain images */ - { - int s; /* domain state */ - unsigned edge; /* counter */ - - if (ischild (s = wfa->tree [range_state][range_label])) - *domain++ = duplicate_state_image (images [s + (range_level) - * wfa->states], - offsets [s + (range_level) - * wfa->states], - range_level); - for (edge = 0; isedge (s = wfa->into[range_state][range_label][edge]); - edge++) - *domain++ = duplicate_state_image (images [s + (range_level) - * wfa->states], - offsets [s + (range_level) - * wfa->states], - range_level); - *domain = NULL; - } - - free_state_images (range_level + 1, NO, images, offsets, NULL, range_state, - NO, wfa); - free_image (state_image); - - return range; + image_t *state_image; /* regenerated state image */ + word_t **images; /* pointer to array of pointers + to state images */ + u_word_t *offsets; /* pointer to array of state image + offsets */ + word_t *range; + + enlarge_image (range_level - (wfa->level_of_state [range_state] - 1), + FORMAT_4_4_4, -1, wfa); + state_image = alloc_image (width_of_level (range_level + 1), + height_of_level (range_level + 1), + NO, FORMAT_4_4_4); + alloc_state_images (&images, &offsets, state_image, NULL, range_state, + range_level + 1, FORMAT_4_4_4, wfa); + compute_state_images (range_level + 1, images, offsets, wfa); + + range = Calloc (size_of_level (range_level), sizeof (word_t)); + + if ((range_level & 1) == 0) /* square image */ + { + memcpy (range, + images [range_state + (range_level + 1) * wfa->states] + + range_label * size_of_level (range_level), + size_of_level (range_level) * sizeof (word_t)); + } + else /* rectangle */ + { + word_t *src, *dst; + unsigned y; + + src = images [range_state + (range_level + 1) * wfa->states] + + range_label * width_of_level (range_level); + dst = range; + for (y = height_of_level (range_level); y; y--) + { + memcpy (dst, src, width_of_level (range_level) * sizeof (word_t)); + dst += width_of_level (range_level); + src += width_of_level (range_level + 1); + } + } + + if (domain != NULL) /* copy domain images */ + { + int s; /* domain state */ + unsigned edge; /* counter */ + + if (ischild (s = wfa->tree [range_state][range_label])) + *domain++ = duplicate_state_image (images [s + (range_level) + * wfa->states], + offsets [s + (range_level) + * wfa->states], + range_level); + for (edge = 0; isedge (s = wfa->into[range_state][range_label][edge]); + edge++) + *domain++ = duplicate_state_image (images [s + (range_level) + * wfa->states], + offsets [s + (range_level) + * wfa->states], + range_level); + *domain = NULL; + } + + free_state_images (range_level + 1, NO, images, offsets, NULL, range_state, + FORMAT_4_4_4, wfa); + free_image (state_image); + + return range; } void @@ -687,7 +685,7 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image) */ { int is, inegs; /* integer factors of s and 1 - s*/ - unsigned state; + unsigned state; unsigned img_width = image->width; unsigned img_height = image->height; real_t s = 1.0 - sf / 200.0; @@ -697,7 +695,7 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image) is = s * 512 + .5; /* integer representation of s */ inegs = (1 - s) * 512 + .5; /* integer representation of 1 - s */ - + for (state = wfa->basis_states; state < (wfa->wfainfo->color ? wfa->tree [wfa->root_state][0] @@ -708,10 +706,10 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image) unsigned level = wfa->level_of_state[state]; /* level of state image */ unsigned width = width_of_level (level); /* size of state image */ unsigned height = height_of_level (level); /* size of state image */ - + if (wfa->y [state][1] >= img_height || wfa->x [state][1] >= img_width) continue; /* outside visible area */ - + if (level % 2) /* horizontal smoothing */ { unsigned i; /* line counter */ @@ -721,12 +719,12 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image) img1 = bptr + (wfa->y [state][1] - 1) * img_width + wfa->x [state][1]; img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1]; - + for (i = MIN(width, img_width - wfa->x [state][1]); i; i--, img1++, img2++) { int tmp = *img1; - + #ifdef HAVE_SIGNED_SHIFT *img1 = (((is * tmp) >> 10) << 1) + (((inegs * (int) *img2) >> 10) << 1); @@ -748,12 +746,12 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image) img1 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1] - 1; img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1]; - + for (i = MIN(height, img_height - wfa->y [state][1]); i; i--, img1 += img_width, img2 += img_width) { int tmp = *img1; - + #ifdef HAVE_SIGNED_SHIFT *img1 = (((is * tmp) >> 10) << 1) + (((inegs * (int) *img2) >> 10) << 1); @@ -773,7 +771,7 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image) /***************************************************************************** private code - + *****************************************************************************/ static void @@ -791,7 +789,7 @@ enlarge_image (int enlarge_factor, format_e format, unsigned y_root, * are modified. */ { - + if (enlarge_factor != 0 || format == FORMAT_4_2_0) { unsigned state; @@ -803,11 +801,11 @@ enlarge_image (int enlarge_factor, format_e format, unsigned y_root, } else state = wfa->basis_states; - + for (; state < wfa->states; state++) { unsigned label, n; - + wfa->level_of_state [state] = MAX(wfa->level_of_state [state] + enlarge_factor * 2, 0); @@ -857,12 +855,12 @@ compute_actual_size (unsigned luminance_root, { unsigned x = 0, y = 0; /* maximum coordinates */ unsigned state; /* counter */ - + for (state = wfa->basis_states; state < wfa->states; state++) if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0])) { unsigned mult = state > luminance_root ? 2 : 1; - + x = MAX((wfa->x [state][0] + width_of_level (wfa->level_of_state [state])) * mult, x); y = MAX((wfa->y [state][0] @@ -888,7 +886,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, * 'max_level' fives the max. level of a linear combination. * Memory is allocated for every required state image. * Use 4:2:0 subsampling or 4:4:4 'format' for color images. - * If 'range_state' > 0 then rather compute image of 'range_state' than + * If 'range_state' > 0 then rather compute image of 'range_state' than * image of 'wfa->root_state'. * * Return values: @@ -902,7 +900,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, word_t **simg; /* ptr to list of state image ptr's */ u_word_t *offs; /* ptr to list of offsets */ unsigned level; /* counter */ - + simg = Calloc (wfa->states * (max_level + 1), sizeof (word_t *)); offs = Calloc (wfa->states * (max_level + 1), sizeof (u_word_t)); @@ -940,7 +938,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, } } } - + /* * Generate list of state images which must be computed at each level */ @@ -948,9 +946,9 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, { int child, domain; unsigned state, label, edge; - + /* - * Range approximation with child. + * Range approximation with child. */ for (state = 1; state < (range_state > 0 ? range_state + 1 : wfa->states); state++) @@ -992,7 +990,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, } } /* - * Range approximation with linear combination + * Range approximation with linear combination */ for (state = 1; state < (range_state > 0 ? range_state + 1 : wfa->states); state++) @@ -1010,7 +1008,7 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, = width_of_level (level - 1); } } - + } *images = simg; @@ -1041,7 +1039,7 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image, else { unsigned state; - + /* * Initialize state image array with states at 'max_level' */ @@ -1055,19 +1053,19 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image, level = max_level - 2; else level = max_level; - + for (; state < wfa->states; state++) if (wfa->level_of_state [state] == level) state_image [state + level * wfa->states] = ▮ } } - + for (level = max_level; level > 0; level--) { int domain, child; unsigned state, label, edge; /* - * Range approximation with child. + * Range approximation with child. */ for (state = 1; state < (range_state > 0 ? range_state + 1 : wfa->states); state++) @@ -1082,7 +1080,7 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image, state_image [child + (level - 1) * wfa->states] = ▮ } /* - * Range approximation with linear combination + * Range approximation with linear combination */ for (state = 1; state < (range_state > 0 ? range_state + 1 : wfa->states); @@ -1091,7 +1089,7 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image, for (label = 0; label < MAXLABELS; label++) for (edge = 0; isedge (domain = wfa->into[state][label][edge]); edge++) - if (domain > 0 + if (domain > 0 && (state_image [domain + (level - 1) * wfa->states] != NULL) && (state_image [domain + (level - 1) * wfa->states] @@ -1114,7 +1112,7 @@ compute_state_images (unsigned max_level, word_t **simg, * which are marked in the array 'simg' (offsets of state images * are given by 'offset'). * - * Warning: Several optimizations are used in this function making + * Warning: Several optimizations are used in this function making * it difficult to understand. * * No return value. @@ -1125,7 +1123,7 @@ compute_state_images (unsigned max_level, word_t **simg, */ { unsigned level, state; - + /* * Copy one-pixel images in case state_image pointer != &final distr. */ @@ -1140,17 +1138,17 @@ compute_state_images (unsigned max_level, word_t **simg, * 'weight' gives the weight in integer notation * 'src', 'dst', and 'idst' are pointers to the source and * destination pixels (short or integer format), respectively. - * Short format : one operation per register (16 bit mode). - * Integer format : two operations per register (32 bit mode). + * Short format : one operation per register (16 bit mode). + * Integer format : two operations per register (32 bit mode). * 'src_offset', 'dst_offset', and 'dst_offset' give the number of * pixels which have to be omitted when jumping to the next image row. */ - for (level = 1; level <= max_level; level++) + for (level = 1; level <= max_level; level++) { unsigned label; unsigned width = width_of_level (level - 1); unsigned height = height_of_level (level - 1); - + for (state = 1; state < wfa->states; state++) if (simg [state + level * wfa->states] != NULL) for (label = 0; label < MAXLABELS; label++) @@ -1178,7 +1176,7 @@ compute_state_images (unsigned max_level, word_t **simg, } /* - * Generate the state images by adding the corresponding + * Generate the state images by adding the corresponding * weighted state images: * subimage [label] = * weight_1 * image_1 + ... + weight_n * image_n @@ -1228,12 +1226,12 @@ compute_state_images (unsigned max_level, word_t **simg, src_offset = offset [domain + ((level - 1) * wfa->states)] - width; weight = wfa->int_weight [state][label][edge]; - + if (width == 1) /* can't add two-pixels in a row */ { word_t *dst; unsigned dst_offset; - + dst = range; dst_offset = offset [state + level * wfa->states] - width; @@ -1242,7 +1240,7 @@ compute_state_images (unsigned max_level, word_t **simg, #else /* not HAVE_SIGNED_SHIFT */ *dst++ = ((weight * (int) *src++) / 1024) * 2; #endif /* not HAVE_SIGNED_SHIFT */ - if (height == 2) + if (height == 2) { src += src_offset; dst += dst_offset; @@ -1258,14 +1256,14 @@ compute_state_images (unsigned max_level, word_t **simg, unsigned y; int *idst; unsigned idst_offset; - + idst = (int *) range; idst_offset = (offset [state + level * wfa->states] - width) / 2; for (y = height; y; y--) { int *comp_dst = idst + (width >> 1); - + for (; idst != comp_dst; ) { int tmp; /* temp. value of adjacent pixels */ @@ -1314,11 +1312,11 @@ compute_state_images (unsigned max_level, word_t **simg, { word_t *dst; unsigned dst_offset; - + dst = range; dst_offset = offset [state + level * wfa->states] - width; - + *dst++ = weight; if (height == 2) { @@ -1331,7 +1329,7 @@ compute_state_images (unsigned max_level, word_t **simg, unsigned x, y; int *idst; unsigned idst_offset; - + weight = (weight * 65536) | (weight & 0xffff); idst = (int *) range; idst_offset = offset [state + level * wfa->states] @@ -1353,7 +1351,7 @@ compute_state_images (unsigned max_level, word_t **simg, } else edge = 0; - + /* * Add remaining weighted domain images to current range */ @@ -1370,12 +1368,12 @@ compute_state_images (unsigned max_level, word_t **simg, src_offset = offset [domain + ((level - 1) * wfa->states)] - width; weight = wfa->int_weight [state][label][edge]; - + if (width == 1) /* can't add two-pixels in a row */ { word_t *dst; unsigned dst_offset; - + dst = range; dst_offset = offset [state + level * wfa->states] - width; @@ -1385,7 +1383,7 @@ compute_state_images (unsigned max_level, word_t **simg, #else /* not HAVE_SIGNED_SHIFT */ *dst++ += ((weight * (int) *src++) / 1024) * 2; #endif /* not HAVE_SIGNED_SHIFT */ - if (height == 2) + if (height == 2) { src += src_offset; dst += dst_offset; @@ -1401,15 +1399,15 @@ compute_state_images (unsigned max_level, word_t **simg, int *idst; unsigned idst_offset; unsigned y; - + idst = (int *) range; idst_offset = (offset [state + level * wfa->states] - width) / 2; - + for (y = height; y; y--) { int *comp_dst = idst + (width >> 1); - + for (; idst != comp_dst;) { int tmp; /* temp. value of adjacent pixels */ @@ -1459,11 +1457,11 @@ compute_state_images (unsigned max_level, word_t **simg, { word_t *dst; unsigned dst_offset; - + dst = range; dst_offset = offset [state + level * wfa->states] - width; - + *dst++ += weight; if (height == 2) { @@ -1476,16 +1474,16 @@ compute_state_images (unsigned max_level, word_t **simg, int *idst; unsigned idst_offset; unsigned y; - + weight = (weight * 65536) | (weight & 0xffff); idst = (int *) range; idst_offset = (offset [state + level * wfa->states] - width) /2; - + for (y = height; y; y--) { int *comp_dst = idst + (width >> 1); - + for (; idst != comp_dst; ) { *idst = (*idst + weight) & 0xfffefffe; @@ -1496,14 +1494,14 @@ compute_state_images (unsigned max_level, word_t **simg, } } } - } + } } } static word_t * duplicate_state_image (const word_t *domain, unsigned offset, unsigned level) /* - * Allocate new memory block 'pixels' and copy pixel values of 'domain' + * Allocate new memory block 'pixels' and copy pixel values of 'domain' * (size and pixel offset are given by 'level' and 'offset') * to the lock 'pixels'. * diff --git a/converter/other/fiasco/codec/decoder.h b/converter/other/fiasco/codec/decoder.h index 8cd211e0..7823ab91 100644 --- a/converter/other/fiasco/codec/decoder.h +++ b/converter/other/fiasco/codec/decoder.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/dfiasco.c b/converter/other/fiasco/codec/dfiasco.c index 2fdec573..d45c9e39 100644 --- a/converter/other/fiasco/codec/dfiasco.c +++ b/converter/other/fiasco/codec/dfiasco.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/dfiasco.h b/converter/other/fiasco/codec/dfiasco.h index bcc3c7f9..eed12b6b 100644 --- a/converter/other/fiasco/codec/dfiasco.h +++ b/converter/other/fiasco/codec/dfiasco.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/domain-pool.c b/converter/other/fiasco/codec/domain-pool.c index 7cc3900e..1c14a30c 100644 --- a/converter/other/fiasco/codec/domain-pool.c +++ b/converter/other/fiasco/codec/domain-pool.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/domain-pool.h b/converter/other/fiasco/codec/domain-pool.h index d1488779..a2c46141 100644 --- a/converter/other/fiasco/codec/domain-pool.h +++ b/converter/other/fiasco/codec/domain-pool.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/ip.c b/converter/other/fiasco/codec/ip.c index ade0d916..56b0ae9a 100644 --- a/converter/other/fiasco/codec/ip.c +++ b/converter/other/fiasco/codec/ip.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/ip.h b/converter/other/fiasco/codec/ip.h index e5e4dd65..0c693826 100644 --- a/converter/other/fiasco/codec/ip.h +++ b/converter/other/fiasco/codec/ip.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/motion.c b/converter/other/fiasco/codec/motion.c index 876a2998..0d1fa099 100644 --- a/converter/other/fiasco/codec/motion.c +++ b/converter/other/fiasco/codec/motion.c @@ -4,8 +4,8 @@ * Written by: Ullrich Hafner * Michael Unger * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/motion.h b/converter/other/fiasco/codec/motion.h index 2ea382f7..82d1f1ec 100644 --- a/converter/other/fiasco/codec/motion.h +++ b/converter/other/fiasco/codec/motion.h @@ -4,8 +4,8 @@ * Written by: Ullrich Hafner * Michael Unger * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/mwfa.c b/converter/other/fiasco/codec/mwfa.c index 43a7dae2..0be08a4f 100644 --- a/converter/other/fiasco/codec/mwfa.c +++ b/converter/other/fiasco/codec/mwfa.c @@ -4,8 +4,8 @@ * Written by: Michael Unger * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/mwfa.h b/converter/other/fiasco/codec/mwfa.h index 52f41866..2c1e7c9f 100644 --- a/converter/other/fiasco/codec/mwfa.h +++ b/converter/other/fiasco/codec/mwfa.h @@ -4,8 +4,8 @@ * Written by: Michael Unger * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/options.c b/converter/other/fiasco/codec/options.c index c8e4d2e2..b9c64efd 100644 --- a/converter/other/fiasco/codec/options.c +++ b/converter/other/fiasco/codec/options.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -14,6 +14,7 @@ * $State: Exp $ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ diff --git a/converter/other/fiasco/codec/options.h b/converter/other/fiasco/codec/options.h index 3af6be01..783c41ef 100644 --- a/converter/other/fiasco/codec/options.h +++ b/converter/other/fiasco/codec/options.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/prediction.c b/converter/other/fiasco/codec/prediction.c index e056d10f..e78e5acc 100644 --- a/converter/other/fiasco/codec/prediction.c +++ b/converter/other/fiasco/codec/prediction.c @@ -4,8 +4,8 @@ * Written by: Ullrich Hafner * Michael Unger * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/prediction.h b/converter/other/fiasco/codec/prediction.h index 1068501a..0646dfd8 100644 --- a/converter/other/fiasco/codec/prediction.h +++ b/converter/other/fiasco/codec/prediction.h @@ -4,8 +4,8 @@ * Written by: Ullrich Hafner * Michael Unger * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/subdivide.c b/converter/other/fiasco/codec/subdivide.c index 2ace18e4..348f838a 100644 --- a/converter/other/fiasco/codec/subdivide.c +++ b/converter/other/fiasco/codec/subdivide.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/subdivide.h b/converter/other/fiasco/codec/subdivide.h index b6840e58..bd9cd10e 100644 --- a/converter/other/fiasco/codec/subdivide.h +++ b/converter/other/fiasco/codec/subdivide.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/tiling.c b/converter/other/fiasco/codec/tiling.c index 21e4428a..9af43da0 100644 --- a/converter/other/fiasco/codec/tiling.c +++ b/converter/other/fiasco/codec/tiling.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/tiling.h b/converter/other/fiasco/codec/tiling.h index 2eb04fe0..6668ad8b 100644 --- a/converter/other/fiasco/codec/tiling.h +++ b/converter/other/fiasco/codec/tiling.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/wfa.h b/converter/other/fiasco/codec/wfa.h index 9253affd..59020fc1 100644 --- a/converter/other/fiasco/codec/wfa.h +++ b/converter/other/fiasco/codec/wfa.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/codec/wfalib.c b/converter/other/fiasco/codec/wfalib.c index 61d64d2f..90420d6f 100644 --- a/converter/other/fiasco/codec/wfalib.c +++ b/converter/other/fiasco/codec/wfalib.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -14,6 +14,7 @@ * $State: Exp $ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ diff --git a/converter/other/fiasco/codec/wfalib.h b/converter/other/fiasco/codec/wfalib.h index 4622fcd2..5c1e0907 100644 --- a/converter/other/fiasco/codec/wfalib.h +++ b/converter/other/fiasco/codec/wfalib.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/display.c b/converter/other/fiasco/display.c index cf160329..d8d32fa6 100644 --- a/converter/other/fiasco/display.c +++ b/converter/other/fiasco/display.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner * * Based on mpeg2decode, (C) 1994, MPEG Software Simulation Group * and mpeg2play, (C) 1994 Stefan Eckart diff --git a/converter/other/fiasco/display.h b/converter/other/fiasco/display.h index 5f30b117..8049456a 100644 --- a/converter/other/fiasco/display.h +++ b/converter/other/fiasco/display.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/doc/README.LIB b/converter/other/fiasco/doc/README.LIB index 4bf8c382..ce8a6b2b 100644 --- a/converter/other/fiasco/doc/README.LIB +++ b/converter/other/fiasco/doc/README.LIB @@ -1,5 +1,5 @@ --------------------------------------------------------------------------- - FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + FIASCO (Fractal Image And Sequence COdec) Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>, http://ulli.linuxave.net Version 1.0 diff --git a/converter/other/fiasco/doc/fiasco_c_options_new.3 b/converter/other/fiasco/doc/fiasco_c_options_new.3 index 52efb86c..d873b642 100644 --- a/converter/other/fiasco/doc/fiasco_c_options_new.3 +++ b/converter/other/fiasco/doc/fiasco_c_options_new.3 @@ -429,4 +429,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/doc/fiasco_coder.3 b/converter/other/fiasco/doc/fiasco_coder.3 index 3d1c6b87..9f2e0f8e 100644 --- a/converter/other/fiasco/doc/fiasco_coder.3 +++ b/converter/other/fiasco/doc/fiasco_coder.3 @@ -103,4 +103,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/doc/fiasco_d_options_new.3 b/converter/other/fiasco/doc/fiasco_d_options_new.3 index 4294330a..d7f2181a 100644 --- a/converter/other/fiasco/doc/fiasco_d_options_new.3 +++ b/converter/other/fiasco/doc/fiasco_d_options_new.3 @@ -119,4 +119,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/doc/fiasco_decoder_new.3 b/converter/other/fiasco/doc/fiasco_decoder_new.3 index 05e981a9..5d1d0d08 100644 --- a/converter/other/fiasco/doc/fiasco_decoder_new.3 +++ b/converter/other/fiasco/doc/fiasco_decoder_new.3 @@ -191,4 +191,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/doc/fiasco_get_error_message.3 b/converter/other/fiasco/doc/fiasco_get_error_message.3 index 09d593fb..ce53e6d9 100644 --- a/converter/other/fiasco/doc/fiasco_get_error_message.3 +++ b/converter/other/fiasco/doc/fiasco_get_error_message.3 @@ -38,4 +38,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/doc/fiasco_image_new.3 b/converter/other/fiasco/doc/fiasco_image_new.3 index 10625b63..ac3297bf 100644 --- a/converter/other/fiasco/doc/fiasco_image_new.3 +++ b/converter/other/fiasco/doc/fiasco_image_new.3 @@ -92,4 +92,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/doc/fiasco_options_new.3 b/converter/other/fiasco/doc/fiasco_options_new.3 index 26e070ca..f26586a7 100644 --- a/converter/other/fiasco/doc/fiasco_options_new.3 +++ b/converter/other/fiasco/doc/fiasco_options_new.3 @@ -438,4 +438,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/doc/fiasco_renderer_new.3 b/converter/other/fiasco/doc/fiasco_renderer_new.3 index b24d8462..8b5e47cd 100644 --- a/converter/other/fiasco/doc/fiasco_renderer_new.3 +++ b/converter/other/fiasco/doc/fiasco_renderer_new.3 @@ -122,4 +122,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/doc/fiasco_set_verbosity.3 b/converter/other/fiasco/doc/fiasco_set_verbosity.3 index 746854b1..3e88399a 100644 --- a/converter/other/fiasco/doc/fiasco_set_verbosity.3 +++ b/converter/other/fiasco/doc/fiasco_set_verbosity.3 @@ -43,4 +43,4 @@ Finite Automata\fP, Ph.D. thesis, Mensch & Buch Verlag, ISBN 3-89820-002-7, October 1999. .SH AUTHOR -Ullrich Hafner <hafner@bigfoot.de> +Ullrich Hafner diff --git a/converter/other/fiasco/fiasco.h b/converter/other/fiasco/fiasco.h index 59367bb8..88f999fc 100644 --- a/converter/other/fiasco/fiasco.h +++ b/converter/other/fiasco/fiasco.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/converter/other/fiasco/fiascotopnm.c b/converter/other/fiasco/fiascotopnm.c index dfba2256..e95e27fc 100644 --- a/converter/other/fiasco/fiascotopnm.c +++ b/converter/other/fiasco/fiascotopnm.c @@ -4,8 +4,8 @@ * Written by: Ullrich Hafner * Michael Unger * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -15,6 +15,7 @@ * $State: Exp $ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ @@ -361,6 +362,8 @@ video_decoder (const char *wfa_name, const char *image_name, bool_t panel, while (prg_timer (&fps_timer, STOP) < frame_time) /* wait */ ; } +#else + if (frame_time) {/* defeat compiler warning */} #endif /* not X_DISPLAY_MISSING */ } free (filename); diff --git a/converter/other/fiasco/input/basis.c b/converter/other/fiasco/input/basis.c index 4a748f61..aa371ea1 100644 --- a/converter/other/fiasco/input/basis.c +++ b/converter/other/fiasco/input/basis.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/basis.h b/converter/other/fiasco/input/basis.h index fa26bca2..e2242198 100644 --- a/converter/other/fiasco/input/basis.h +++ b/converter/other/fiasco/input/basis.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/matrices.c b/converter/other/fiasco/input/matrices.c index 47cde1aa..388855ea 100644 --- a/converter/other/fiasco/input/matrices.c +++ b/converter/other/fiasco/input/matrices.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/matrices.h b/converter/other/fiasco/input/matrices.h index ba8fd9bf..6d1cef15 100644 --- a/converter/other/fiasco/input/matrices.h +++ b/converter/other/fiasco/input/matrices.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/mc.c b/converter/other/fiasco/input/mc.c index 070d839e..2d4a073d 100644 --- a/converter/other/fiasco/input/mc.c +++ b/converter/other/fiasco/input/mc.c @@ -4,8 +4,8 @@ * written by: Michael Unger * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/mc.h b/converter/other/fiasco/input/mc.h index 1e14d287..9d9d714d 100644 --- a/converter/other/fiasco/input/mc.h +++ b/converter/other/fiasco/input/mc.h @@ -4,8 +4,8 @@ * written by: Michael Unger * Ullrich Hafner - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/nd.c b/converter/other/fiasco/input/nd.c index 1a68bfbf..52d48e61 100644 --- a/converter/other/fiasco/input/nd.c +++ b/converter/other/fiasco/input/nd.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/nd.h b/converter/other/fiasco/input/nd.h index 2c2fff4b..0fe06cf1 100644 --- a/converter/other/fiasco/input/nd.h +++ b/converter/other/fiasco/input/nd.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/read.c b/converter/other/fiasco/input/read.c index e6e2d7e8..9f4ac993 100644 --- a/converter/other/fiasco/input/read.c +++ b/converter/other/fiasco/input/read.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -14,6 +14,7 @@ * $State: Exp $ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ diff --git a/converter/other/fiasco/input/read.h b/converter/other/fiasco/input/read.h index d0d0ee13..1f59f103 100644 --- a/converter/other/fiasco/input/read.h +++ b/converter/other/fiasco/input/read.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/tree.c b/converter/other/fiasco/input/tree.c index e3e7117e..0ac2b6ae 100644 --- a/converter/other/fiasco/input/tree.c +++ b/converter/other/fiasco/input/tree.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/tree.h b/converter/other/fiasco/input/tree.h index e4b5f2d8..f743ee98 100644 --- a/converter/other/fiasco/input/tree.h +++ b/converter/other/fiasco/input/tree.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/weights.c b/converter/other/fiasco/input/weights.c index 15c35731..8a1e8899 100644 --- a/converter/other/fiasco/input/weights.c +++ b/converter/other/fiasco/input/weights.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/input/weights.h b/converter/other/fiasco/input/weights.h index 1e2285a9..36cea5c2 100644 --- a/converter/other/fiasco/input/weights.h +++ b/converter/other/fiasco/input/weights.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/arith.c b/converter/other/fiasco/lib/arith.c index dc35d1d1..825d4757 100644 --- a/converter/other/fiasco/lib/arith.c +++ b/converter/other/fiasco/lib/arith.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/arith.h b/converter/other/fiasco/lib/arith.h index 744eb9d7..04297eb5 100644 --- a/converter/other/fiasco/lib/arith.h +++ b/converter/other/fiasco/lib/arith.h @@ -1,8 +1,8 @@ /* * arith.h * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/bit-io.c b/converter/other/fiasco/lib/bit-io.c index 1bfef598..f69343e6 100644 --- a/converter/other/fiasco/lib/bit-io.c +++ b/converter/other/fiasco/lib/bit-io.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -14,6 +14,7 @@ * $State: Exp $ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ diff --git a/converter/other/fiasco/lib/bit-io.h b/converter/other/fiasco/lib/bit-io.h index d37cc47c..08029824 100644 --- a/converter/other/fiasco/lib/bit-io.h +++ b/converter/other/fiasco/lib/bit-io.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/dither.c b/converter/other/fiasco/lib/dither.c index accd9dd6..669bb16c 100644 --- a/converter/other/fiasco/lib/dither.c +++ b/converter/other/fiasco/lib/dither.c @@ -3,8 +3,8 @@ * * Adapted by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -713,15 +713,11 @@ display_24_bit_bgr (const struct fiasco_renderer *this, unsigned char *ximage, word_t *cbptr, *crptr; /* pointer to chroma bands */ word_t *yptr; /* pointers to lumincance band */ int *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab; - unsigned int *r_table, *g_table, *b_table; Cr_g_tab = private->Cr_g_tab; Cr_r_tab = private->Cr_r_tab; Cb_b_tab = private->Cb_b_tab; Cb_g_tab = private->Cb_g_tab; - r_table = private->r_table; - g_table = private->g_table; - b_table = private->b_table; yptr = image->pixels [Y]; cbptr = image->pixels [Cb]; crptr = image->pixels [Cr]; @@ -1044,9 +1040,7 @@ display_24_bit_bgr (const struct fiasco_renderer *this, unsigned char *ximage, { unsigned int *dst; /* pointer to dithered pixels */ word_t *src; /* current pixel of frame */ - unsigned int *y_table; - y_table = private->y_table; dst = (unsigned int *) out; src = image->pixels [GRAY]; @@ -1164,15 +1158,11 @@ display_24_bit_rgb (const struct fiasco_renderer *this, unsigned char *ximage, word_t *cbptr, *crptr; /* pointer to chroma bands */ word_t *yptr; /* pointers to lumincance band */ int *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab; - unsigned int *r_table, *g_table, *b_table; Cr_g_tab = private->Cr_g_tab; Cr_r_tab = private->Cr_r_tab; Cb_b_tab = private->Cb_b_tab; Cb_g_tab = private->Cb_g_tab; - r_table = private->r_table; - g_table = private->g_table; - b_table = private->b_table; yptr = image->pixels [Y]; cbptr = image->pixels [Cb]; crptr = image->pixels [Cr]; @@ -1495,9 +1485,7 @@ display_24_bit_rgb (const struct fiasco_renderer *this, unsigned char *ximage, { unsigned int *dst; /* pointer to dithered pixels */ word_t *src; /* current pixel of frame */ - unsigned int *y_table; - y_table = private->y_table; dst = (unsigned int *) out; src = image->pixels [GRAY]; diff --git a/converter/other/fiasco/lib/dither.h b/converter/other/fiasco/lib/dither.h index 71f9d3c3..767bca28 100644 --- a/converter/other/fiasco/lib/dither.h +++ b/converter/other/fiasco/lib/dither.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/error.c b/converter/other/fiasco/lib/error.c index ee3afe1f..394f896f 100644 --- a/converter/other/fiasco/lib/error.c +++ b/converter/other/fiasco/lib/error.c @@ -3,29 +3,19 @@ * * Written by: Stefan Frank * Ullrich Hafner - * + * * Credits: Modelled after variable argument routines from Jef - * Poskanzer's pbmplus package. + * Poskanzer's pbmplus package. * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> - - "int dummy = " change to int dummy; dummy =" for Netpbm to avoid - unused variable warning. - - */ - -/* - * $Date: 2000/06/14 20:49:37 $ - * $Author: hafner $ - * $Revision: 5.1 $ - * $State: Exp $ + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ #define _ERROR_C #include "config.h" +#include <stdbool.h> #include <stdio.h> #include <errno.h> @@ -47,7 +37,7 @@ /***************************************************************************** local variables - + *****************************************************************************/ static fiasco_verbosity_e verboselevel = FIASCO_SOME_VERBOSITY; @@ -60,234 +50,237 @@ jmp_buf env; /***************************************************************************** public code - + *****************************************************************************/ void -set_error (const char *format, ...) -/* - * Set error text to given string. - */ -{ - va_list args; - unsigned len = 0; - const char *str = format; - - VA_START (args, format); - - len = strlen (format); - while ((str = strchr (str, '%'))) - { - str++; - if (*str == 's') - { - char *vstring = va_arg (args, char *); - len += strlen (vstring); - } - else if (*str == 'd') - { - int dummy; - dummy = va_arg (args, int); - len += 10; - } - else if (*str == 'c') - { - int dummy; - dummy = va_arg (args, int); - len += 1; - } - else - return; - str++; - } - va_end(args); - - VA_START (args, format); - - if (error_message) - Free (error_message); - error_message = Calloc (len, sizeof (char)); - - vsprintf (error_message, format, args); - - va_end (args); +set_error(const char * const format, ...) { +/*---------------------------------------------------------------------------- + Set error text to given string. +-----------------------------------------------------------------------------*/ + va_list args; + unsigned len; + bool error; + const char * str; + + VA_START (args, format); + + /* Compute how long the error text will be: 'len' */ + + for (len = strlen(format), str = &format[0], error = false; + *str && !error; ) { + + str = strchr(str, '%'); + + if (*str) { + ++str; /* Move past % */ + if (*str == 's') { + char * const vstring = va_arg (args, char *); + len += strlen(vstring); + } else if (*str == 'd') { + (void)va_arg(args, int); + len += 10; + } else if (*str == 'c') { + (void)va_arg(args, int); + len += 1; + } else + error = true; + if (!error) + ++str; + } + } + va_end(args); + + if (!error) { + VA_START(args, format); + + if (error_message) + Free(error_message); + error_message = Calloc(len, sizeof (char)); + + vsprintf(error_message, format, args); + + va_end(args); + } } + + void -error (const char *format, ...) -/* - * Set error text to given string. - */ -{ - va_list args; - unsigned len = 0; - const char *str = format; - - VA_START (args, format); - - len = strlen (format); - while ((str = strchr (str, '%'))) - { - str++; - if (*str == 's') - { - char *vstring = va_arg (args, char *); - len += strlen (vstring); - } - else if (*str == 'd') - { - int dummy; - dummy = va_arg (args, int); - len += 10; - } - else if (*str == 'c') - { - int dummy; - dummy = va_arg (args, int); - len += 1; - } - else - { +error(const char * const format, ...) { +/*---------------------------------------------------------------------------- + Set error text to given string. +-----------------------------------------------------------------------------*/ + va_list args; + unsigned len; + const char * str; + + len = 0; /* initial value */ + str = &format[0]; /* initial value */ + + VA_START (args, format); + + len = strlen (format); + while ((str = strchr (str, '%'))) { + ++str; + if (*str == 's') { + char * const vstring = va_arg (args, char *); + len += strlen(vstring); + } else if (*str == 'd') { + (void)va_arg(args, int); + len += 10; + } else if (*str == 'c') { + (void)va_arg(args, int); + len += 1; + } else { #if HAVE_SETJMP_H - longjmp (env, 1); -#else /* not HAVE_SETJMP_H */ - exit (1); -#endif /* HAVE_SETJMP_H */ - }; - - str++; - } - va_end(args); - - VA_START (args, format); - - if (error_message) - Free (error_message); - error_message = Calloc (len, sizeof (char)); - - vsprintf (error_message, format, args); - - va_end (args); - + longjmp(env, 1); +#else + exit(1); +#endif + }; + + ++str; + } + va_end(args); + + VA_START(args, format); + + if (error_message) + Free(error_message); + error_message = Calloc(len, sizeof (char)); + + vsprintf(error_message, format, args); + + va_end(args); + #if HAVE_SETJMP_H - longjmp (env, 1); -#else /* not HAVE_SETJMP_H */ - exit (1); -#endif /* HAVE_SETJMP_H */ + longjmp(env, 1); +#else + exit(1); +#endif } + + const char * -fiasco_get_error_message (void) -/* - * Return value: - * Last error message of FIASCO library. - */ -{ - return error_message ? error_message : ""; +fiasco_get_error_message(void) { +/*---------------------------------------------------------------------------- + Last error message of FIASCO library. +-----------------------------------------------------------------------------*/ + return error_message ? error_message : ""; } + + const char * -get_system_error (void) -{ - return strerror (errno); +get_system_error(void) { + return strerror(errno); } + + void -file_error (const char *filename) -/* - * Print file error message and exit. - * - * No return value. - */ -{ - error ("File `%s': I/O Error - %s.", filename, get_system_error ()); +file_error(const char * const filename) { +/*---------------------------------------------------------------------------- + Print file error message and exit. +-----------------------------------------------------------------------------*/ + error("File `%s': I/O Error - %s.", filename, get_system_error ()); } -void -warning (const char *format, ...) -/* - * Issue a warning and continue execution. - * - * No return value. - */ -{ - va_list args; - - VA_START (args, format); - if (verboselevel == FIASCO_NO_VERBOSITY) - return; - - fprintf (stderr, "Warning: "); - vfprintf (stderr, format, args); - fputc ('\n', stderr); - va_end (args); +void +warning(const char * const format, ...) { +/*---------------------------------------------------------------------------- + Issue a warning. +-----------------------------------------------------------------------------*/ + va_list args; + + VA_START (args, format); + + if (verboselevel == FIASCO_NO_VERBOSITY) { + /* User doesn't want warnings */ + } else { + fprintf (stderr, "Warning: "); + vfprintf (stderr, format, args); + fputc ('\n', stderr); + } + va_end (args); } -void -message (const char *format, ...) -/* - * Print a message to stderr. - */ -{ - va_list args; - - VA_START (args, format); - if (verboselevel == FIASCO_NO_VERBOSITY) - return; - vfprintf (stderr, format, args); - fputc ('\n', stderr); - va_end (args); +void +message(const char * const format, ...) { +/*---------------------------------------------------------------------------- + Print a message to Standard Error +-----------------------------------------------------------------------------*/ + va_list args; + + VA_START (args, format); + + if (verboselevel == FIASCO_NO_VERBOSITY) { + /* User doesn't want messages */ + } else { + vfprintf (stderr, format, args); + fputc ('\n', stderr); + } + va_end (args); } -void -debug_message (const char *format, ...) -/* - * Print a message to stderr. - */ -{ - va_list args; - VA_START (args, format); - - if (verboselevel < FIASCO_ULTIMATE_VERBOSITY) - return; - - fprintf (stderr, "*** "); - vfprintf (stderr, format, args); - fputc ('\n', stderr); - va_end (args); -} void -info (const char *format, ...) -/* - * Print a message to stderr. Do not append a newline. - */ -{ - va_list args; +debug_message(const char * const format, ...) { +/*---------------------------------------------------------------------------- + Print a message to Standard Error if debug messages are enabled. +-----------------------------------------------------------------------------*/ + va_list args; + + VA_START (args, format); + + if (verboselevel >= FIASCO_ULTIMATE_VERBOSITY) { + fprintf (stderr, "*** "); + vfprintf (stderr, format, args); + fputc ('\n', stderr); + } + va_end (args); +} - VA_START (args, format); - if (verboselevel == FIASCO_NO_VERBOSITY) - return; - vfprintf (stderr, format, args); - fflush (stderr); - va_end (args); +void +info(const char * const format, ...) { +/*---------------------------------------------------------------------------- + Print a message to stderr. Do not append a newline. +-----------------------------------------------------------------------------*/ + va_list args; + + VA_START (args, format); + + if (verboselevel == FIASCO_NO_VERBOSITY) { + /* User doesn't want informational messages */ + } else { + vfprintf (stderr, format, args); + fflush (stderr); + } + va_end (args); } + + void -fiasco_set_verbosity (fiasco_verbosity_e level) -{ +fiasco_set_verbosity(fiasco_verbosity_e const level) { verboselevel = level; } + + fiasco_verbosity_e -fiasco_get_verbosity (void) -{ +fiasco_get_verbosity(void) { return verboselevel; } + + + diff --git a/converter/other/fiasco/lib/error.h b/converter/other/fiasco/lib/error.h index 288b25f4..4159ccd2 100644 --- a/converter/other/fiasco/lib/error.h +++ b/converter/other/fiasco/lib/error.h @@ -4,8 +4,8 @@ * Written by: Stefan Frank * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ #ifndef ERROR_H_INCLUDED diff --git a/converter/other/fiasco/lib/image.c b/converter/other/fiasco/lib/image.c index fa3b2db5..a700fe88 100644 --- a/converter/other/fiasco/lib/image.c +++ b/converter/other/fiasco/lib/image.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/image.h b/converter/other/fiasco/lib/image.h index 00978526..a87a3c05 100644 --- a/converter/other/fiasco/lib/image.h +++ b/converter/other/fiasco/lib/image.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/list.c b/converter/other/fiasco/lib/list.c index bb4efae1..b67ff4b8 100644 --- a/converter/other/fiasco/lib/list.c +++ b/converter/other/fiasco/lib/list.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/list.h b/converter/other/fiasco/lib/list.h index db7c08b2..68577dfd 100644 --- a/converter/other/fiasco/lib/list.h +++ b/converter/other/fiasco/lib/list.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/macros.h b/converter/other/fiasco/lib/macros.h index 9968110a..0bc80e7c 100644 --- a/converter/other/fiasco/lib/macros.h +++ b/converter/other/fiasco/lib/macros.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/misc.c b/converter/other/fiasco/lib/misc.c index 782ed1e9..c5629c5c 100644 --- a/converter/other/fiasco/lib/misc.c +++ b/converter/other/fiasco/lib/misc.c @@ -6,8 +6,8 @@ * Written by: Stefan Frank * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/misc.h b/converter/other/fiasco/lib/misc.h index 28fd8b5a..6f643b7a 100644 --- a/converter/other/fiasco/lib/misc.h +++ b/converter/other/fiasco/lib/misc.h @@ -4,8 +4,8 @@ * Written by: Stefan Frank * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/rpf.c b/converter/other/fiasco/lib/rpf.c index 84c1f9b6..e6ff6e09 100644 --- a/converter/other/fiasco/lib/rpf.c +++ b/converter/other/fiasco/lib/rpf.c @@ -1,10 +1,10 @@ /* - * rpf.c: Conversion of float to reduced precision format values + * rpf.c: Conversion of float to reduced precision format values * - * Written by: Stefan Frank - * Richard Krampfl - * Ullrich Hafner - * + * Written by: Stefan Frank + * Richard Krampfl + * Ullrich Hafner + * * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> */ @@ -18,6 +18,7 @@ #include "pm_config.h" #include "config.h" +#include "mallocvar.h" #include "types.h" #include "macros.h" @@ -26,39 +27,37 @@ #include "misc.h" #include "rpf.h" -/* - * CAUTION: The IEEE float format must be used by your compiler, - * or all following code is void! - */ +int const RPF_ZERO = -1; -#if BYTE_ORDER == BIG_ENDIAN -/* - * Big-Endian Architecture (e.g. SUN, Motorola) - * Memory representation of integer 0x00112233 is 00,11,22,33 - */ +/***************************************************************************** -enum real_bytes {BYTE_0, BYTE_1, BYTE_2, BYTE_3}; + private code + +*****************************************************************************/ -#else -/* - * Little-Endian Architecture (e.g. Intel, VAX, Alpha) - * Memory representation of integer 0x00112233 is 33,22,11,00 - */ -enum real_bytes {BYTE_3, BYTE_2, BYTE_1, BYTE_0}; +typedef struct { + double fraction; + int exponent; +} FracExp; -#endif -const int RPF_ZERO = -1; -/***************************************************************************** +static FracExp +fracExpFromDouble(double const x) { + + FracExp retval; + + retval.fraction = frexp(x, &retval.exponent); + + return retval; +} + - private code - -*****************************************************************************/ int -rtob (real_t f, const rpf_t *rpf) +rtob (real_t const f, + const rpf_t * const rpfP) /* * Convert real number 'f' into fixed point format. * The real number in [-'range'; +'range'] is scaled to [-1 ; +1]. @@ -66,111 +65,98 @@ rtob (real_t f, const rpf_t *rpf) * packed into one integer. * * Return value: - * real value in reduced precision format + * real value in reduced precision format */ { - unsigned int mantissa; - int exponent, sign; - union - { - float f; - unsigned char c[4]; - } v; /* conversion dummy */ - - f /= rpf->range; /* scale f to [-1,+1] */ - v.f = f; - - /* - * Extract mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit) - */ - - mantissa = ((((v.c[BYTE_1] & 127) << 8 ) | v.c[BYTE_2]) << 8) | v.c[BYTE_3]; - exponent = (((v.c[BYTE_0] & 127) << 1) | (v.c[BYTE_1] & 128 ? 1 : 0)) - 126; - sign = v.c[BYTE_0] & 128 ? 1 : 0; - - /* - * Generate reduced precision mantissa. - */ - mantissa >>= 1; /* shift 1 into from left */ - mantissa |= (1 << 22); - if (exponent > 0) - mantissa <<= exponent; - else - mantissa >>= -exponent; + /* + * Extract mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit) + */ + + double const normalized = f / rpfP->range; + /* 'f' scaled to [-1,+1] */ + FracExp const fracExp = fracExpFromDouble(normalized); + unsigned int const signedMantissa = + (unsigned int) (fracExp.fraction * (1<<23)); + + unsigned int mantissa; + unsigned int sign; /* 0 for positive; 1 for negative */ + + if (signedMantissa < 0) { + mantissa = -signedMantissa; + sign = 1; + } else { + mantissa = +signedMantissa; + sign = 0; + } + + /* + * Generate reduced precision mantissa. + */ + if (fracExp.exponent > 0) + mantissa <<= fracExp.exponent; + else + mantissa >>= -fracExp.exponent; + + mantissa >>= (23 - rpfP->mantissa_bits - 1); + + mantissa += 1; /* Round last bit. */ + mantissa >>= 1; - mantissa >>= (23 - rpf->mantissa_bits - 1); - - mantissa += 1; /* Round last bit. */ - mantissa >>= 1; - - if (mantissa == 0) /* close to zero */ - return RPF_ZERO; - else if (mantissa >= (1U << rpf->mantissa_bits)) /* overflow */ - return sign; - else - return ((mantissa & ((1U << rpf->mantissa_bits) - 1)) << 1) | sign; + if (mantissa == 0) /* close to zero */ + return RPF_ZERO; + else if (mantissa >= (1U << rpfP->mantissa_bits)) /* overflow */ + return sign; + else + return ((mantissa & ((1U << rpfP->mantissa_bits) - 1)) << 1) | sign; } + + float -btor (int binary, const rpf_t *rpf) +btor (int const binary, + const rpf_t * const rpfP) /* * Convert value 'binary' in reduced precision format to a real value. - * For more information refer to function lin_rtob() above. + * For more information refer to function rtob() above. * * Return value: - * converted value + * converted value */ { - unsigned int mantissa; - int sign, exponent; - union - { - float f; - unsigned char c[4]; - } value; - - if (binary == RPF_ZERO) - return 0; - - if (binary < 0 || binary >= 1 << (rpf->mantissa_bits + 1)) - error ("Reduced precision format: value %d out of range.", binary); - - /* - * Restore IEEE float format: - * mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit) - */ + unsigned int mantissa; + float sign; + float f; + + if (binary == RPF_ZERO) + return 0; + + if (binary < 0 || binary >= 1 << (rpfP->mantissa_bits + 1)) + error ("Reduced precision format: value %d out of range.", binary); + + /* + * Restore IEEE float format: + * mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit) + */ - sign = binary & 1; - mantissa = (binary & ((1 << (rpf->mantissa_bits + 1)) - 1)) >> 1; - mantissa <<= (23 - rpf->mantissa_bits); - exponent = 0; - - if (mantissa == 0) - { - value.f = (sign ? -1.0 : 1.0); - } - else - { - while (!(mantissa & (1 << 22))) /* normalize mantissa */ - { - exponent--; - mantissa <<= 1; - } - mantissa <<= 1; - - value.c[BYTE_0] = (sign << 7) | ((exponent + 126) >> 1); - value.c[BYTE_1] = (((exponent + 126) & 1) << 7) - | ((mantissa >> 16) & 127); - value.c[BYTE_2] = (mantissa >> 8) & 255; - value.c[BYTE_3] = mantissa & 255; - } + sign = (binary & 0x1) == 0 ? 1.0 : -1.0; + mantissa = (binary & ((0x1 << (rpfP->mantissa_bits + 1)) - 1)) >> 1; + mantissa <<= (23 - rpfP->mantissa_bits); + + if (mantissa == 0) + f = sign; + else + f = sign * (float) mantissa / 8388608; - return value.f * rpf->range; /* expand [ -1 ; +1 ] to - [ -range ; +range ] */ + return f * rpfP->range; /* expand [ -1 ; +1 ] to + [ -range ; +range ] */ } + + + rpf_t * -alloc_rpf (unsigned mantissa, fiasco_rpf_range_e range) +alloc_rpf (unsigned const mantissa, + fiasco_rpf_range_e const range) /* * Reduced precision format constructor. * Allocate memory for the rpf_t structure. @@ -180,45 +166,47 @@ alloc_rpf (unsigned mantissa, fiasco_rpf_range_e range) * returned. * * Return value - * pointer to the new rpf structure + * pointer to the new rpf structure */ { - rpf_t *rpf = Calloc (1, sizeof (rpf_t)); + rpf_t * rpfP; + + MALLOCVAR(rpfP); - if (mantissa < 2) - { - warning (_("Size of RPF mantissa has to be in the interval [2,8]. " - "Using minimum value 2.\n")); - mantissa = 2; - } - else if (mantissa > 8) - { - warning (_("Size of RPF mantissa has to be in the interval [2,8]. " - "Using maximum value 8.\n")); - mantissa = 2; - } - - rpf->mantissa_bits = mantissa; - rpf->range_e = range; - switch (range) - { - case FIASCO_RPF_RANGE_0_75: - rpf->range = 0.75; - break; - case FIASCO_RPF_RANGE_1_50: - rpf->range = 1.50; - break; - case FIASCO_RPF_RANGE_2_00: - rpf->range = 2.00; - break; - case FIASCO_RPF_RANGE_1_00: - rpf->range = 1.00; - break; - default: - warning (_("Invalid RPF range specified. Using default value 1.0.")); - rpf->range = 1.00; - rpf->range_e = FIASCO_RPF_RANGE_1_00; - break; - } - return rpf; + if (mantissa < 2) { + warning (_("Size of RPF mantissa has to be in the interval [2,8]. " + "Using minimum value 2.\n")); + rpfP->mantissa_bits = 2; + } else if (mantissa > 8) { + warning (_("Size of RPF mantissa has to be in the interval [2,8]. " + "Using maximum value 8.\n")); + rpfP->mantissa_bits = 2; + } else + rpfP->mantissa_bits = mantissa; + + switch (range) { + case FIASCO_RPF_RANGE_0_75: + rpfP->range = 0.75; + rpfP->range_e = range; + break; + case FIASCO_RPF_RANGE_1_50: + rpfP->range = 1.50; + rpfP->range_e = range; + break; + case FIASCO_RPF_RANGE_2_00: + rpfP->range = 2.00; + rpfP->range_e = range; + break; + case FIASCO_RPF_RANGE_1_00: + rpfP->range = 1.00; + rpfP->range_e = range; + break; + default: + warning (_("Invalid RPF range specified. Using default value 1.0.")); + rpfP->range = 1.00; + rpfP->range_e = FIASCO_RPF_RANGE_1_00; + break; + } + return rpfP; } + diff --git a/converter/other/fiasco/lib/rpf.h b/converter/other/fiasco/lib/rpf.h index ba3ff6be..e543f855 100644 --- a/converter/other/fiasco/lib/rpf.h +++ b/converter/other/fiasco/lib/rpf.h @@ -5,8 +5,8 @@ * Richard Krampfl * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/lib/types.h b/converter/other/fiasco/lib/types.h index 16d8028c..02e40a90 100644 --- a/converter/other/fiasco/lib/types.h +++ b/converter/other/fiasco/lib/types.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/matrices.c b/converter/other/fiasco/output/matrices.c index 01189669..7dc0e6d9 100644 --- a/converter/other/fiasco/output/matrices.c +++ b/converter/other/fiasco/output/matrices.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* NETPBM: When you call delta_encoding() with last_domain < 4, it diff --git a/converter/other/fiasco/output/matrices.h b/converter/other/fiasco/output/matrices.h index f880fef8..44671496 100644 --- a/converter/other/fiasco/output/matrices.h +++ b/converter/other/fiasco/output/matrices.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/mc.c b/converter/other/fiasco/output/mc.c index afff586b..d048bef5 100644 --- a/converter/other/fiasco/output/mc.c +++ b/converter/other/fiasco/output/mc.c @@ -4,8 +4,8 @@ * Written by: Michael Unger * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/mc.h b/converter/other/fiasco/output/mc.h index b7843fd8..cacddfe7 100644 --- a/converter/other/fiasco/output/mc.h +++ b/converter/other/fiasco/output/mc.h @@ -4,8 +4,8 @@ * Written by: Michael Unger * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/nd.c b/converter/other/fiasco/output/nd.c index a09ff762..65a85467 100644 --- a/converter/other/fiasco/output/nd.c +++ b/converter/other/fiasco/output/nd.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/nd.h b/converter/other/fiasco/output/nd.h index 600b3d73..01a37838 100644 --- a/converter/other/fiasco/output/nd.h +++ b/converter/other/fiasco/output/nd.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/tree.c b/converter/other/fiasco/output/tree.c index 0056d7dd..2eae2df9 100644 --- a/converter/other/fiasco/output/tree.c +++ b/converter/other/fiasco/output/tree.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/tree.h b/converter/other/fiasco/output/tree.h index 6f8a3800..50fe2279 100644 --- a/converter/other/fiasco/output/tree.h +++ b/converter/other/fiasco/output/tree.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/weights.c b/converter/other/fiasco/output/weights.c index 5aa17674..0203fef0 100644 --- a/converter/other/fiasco/output/weights.c +++ b/converter/other/fiasco/output/weights.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/weights.h b/converter/other/fiasco/output/weights.h index 271203ad..f22bd9f8 100644 --- a/converter/other/fiasco/output/weights.h +++ b/converter/other/fiasco/output/weights.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/write.c b/converter/other/fiasco/output/write.c index e6185ad3..d6faee26 100644 --- a/converter/other/fiasco/output/write.c +++ b/converter/other/fiasco/output/write.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/output/write.h b/converter/other/fiasco/output/write.h index a3ede1f4..6bdc2f1b 100644 --- a/converter/other/fiasco/output/write.h +++ b/converter/other/fiasco/output/write.h @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/params.c b/converter/other/fiasco/params.c index afacbada..7d0b84ab 100644 --- a/converter/other/fiasco/params.c +++ b/converter/other/fiasco/params.c @@ -4,8 +4,8 @@ * Written by: Stefan Frank * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* @@ -15,6 +15,7 @@ * $State: Exp $ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h and strcaseeq() is in nstring.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ @@ -325,8 +326,17 @@ parseargs (param_t *usr_params, NO, sys_path, usr_file_name); else if (streq (params [param_index].name, "version")) { - fprintf (stderr, "%s " VERSION "\n", argv [0]); - exit (2); + fprintf (stderr, "%s " VERSION "\n", argv [0]); + { + /* Kludge for standard Netpbm version announcement */ + char * modified_argv[2]; + int argc; + modified_argv[0] = argv[0]; + modified_argv[1] = (char *) "--version"; + argc = 2; + pm_proginit(&argc, (const char **) modified_argv); + } + exit (2); } else if (streq (params [param_index].name, "verbose")) fiasco_set_verbosity ( diff --git a/converter/other/fiasco/params.h b/converter/other/fiasco/params.h index 810a9ff0..a1164cf7 100644 --- a/converter/other/fiasco/params.h +++ b/converter/other/fiasco/params.h @@ -4,8 +4,8 @@ * Written by: Stefan Frank * Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/pnmtofiasco.c b/converter/other/fiasco/pnmtofiasco.c index eebd09a9..e2656c71 100644 --- a/converter/other/fiasco/pnmtofiasco.c +++ b/converter/other/fiasco/pnmtofiasco.c @@ -3,8 +3,8 @@ * * Written by: Ullrich Hafner * - * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) - * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + * This file is part of FIASCO (Fractal Image And Sequence COdec) + * Copyright (C) 1994-2000 Ullrich Hafner */ /* diff --git a/converter/other/fiasco/system.fiascorc b/converter/other/fiasco/system.fiascorc index 86ff2da2..77d60603 100644 --- a/converter/other/fiasco/system.fiascorc +++ b/converter/other/fiasco/system.fiascorc @@ -3,8 +3,8 @@ # # Written by: Ullrich Hafner # -# This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) -# Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> +# This file is part of FIASCO (Fractal Image And Sequence COdec) +# Copyright (C) 1994-2000 Ullrich Hafner # # $Date: 2000/06/25 16:38:01 $ diff --git a/converter/other/gemtopnm.c b/converter/other/gemtopnm.c index aac74793..d862213f 100644 --- a/converter/other/gemtopnm.c +++ b/converter/other/gemtopnm.c @@ -36,7 +36,7 @@ * read 4-plane color IMG files. Therefore changed from PBM to PPM. * Bryan changed it further to use the PNM facilities so it outputs * both PBM and PPM in the Netpbm tradition. Name changed from - * gemtopbm to gemtopnm. + * gemtopbm to gemtopnm. */ #include <assert.h> @@ -50,106 +50,106 @@ char pattern[8]; static void getinit ARGS ((FILE *file, int *colsP, int *rowsP, int *padrightP, - int *patlenP, int *planesP)); + int *patlenP, int *planesP)); int main(argc, argv) - int argc; - char *argv[]; + int argc; + char *argv[]; { - int debug = 0; - FILE *f; + int debug = 0; + FILE *f; int row; - int rows, cols, padright, patlen, planes; + int rows, cols, padright, patlen, planes; /* attributes of input image */ int type; /* The format type (PBM/PPM) of the output image */ - bit *bitrow[4]; + bit *bitrow[4]; /* One row of input, one or four planes. (If one, only [0] is defined)*/ xel * xelrow; /* One row of output */ - const char * const usage = "[-debug] [gem IMG file]"; - int argn; + const char * const usage = "[-debug] [gem IMG file]"; + int argn; /* Process multiple planes by maintaining a separate row of bits for each - * plane. In a single-plane image, all we have to do is write out the + * plane. In a single-plane image, all we have to do is write out the * first plane; in a multiple-plane image, we combine them just before writing * out the row. */ - pnm_init( &argc, argv ); - + pnm_init( &argc, argv ); + argn = 1; - while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') - { - if (pm_keymatch(argv[1], "-debug", 2)) - debug = 1; - else - pm_usage (usage); - ++argn; - } + while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') + { + if (pm_keymatch(argv[1], "-debug", 2)) + debug = 1; + else + pm_usage (usage); + ++argn; + } - if (argc == argn) - f = stdin; - else { - f = pm_openr (argv[argn]); - ++argn; - } + if (argc == argn) + f = stdin; + else { + f = pm_openr (argv[argn]); + ++argn; + } - if (argn != argc) - pm_usage (usage); + if (argn != argc) + pm_usage (usage); - getinit (f, &cols, &rows, &padright, &patlen, &planes); + getinit (f, &cols, &rows, &padright, &patlen, &planes); - if (planes == 1) + if (planes == 1) type = PBM_TYPE; - else + else type = PPM_TYPE; - pnm_writepnminit( stdout, cols, rows, MAXVAL, type, 0 ); + pnm_writepnminit( stdout, cols, rows, MAXVAL, type, 0 ); - { + { /* allocate input row data structure */ int plane; - for (plane = 0; plane < planes; plane++) + for (plane = 0; plane < planes; plane++) bitrow[plane] = malloc (cols + padright); } xelrow = pnm_allocrow(cols+padright); /* Output row */ - for (row = 0; row < rows; ) { + for (row = 0; row < rows; ) { int linerep; int plane; - linerep = 1; - for (plane = 0; plane < planes; plane++) { + linerep = 1; + for (plane = 0; plane < planes; plane++) { int col; - col = 0; - while (col < cols) { + col = 0; + while (col < cols) { int c; - switch (c = getc(f)) { - case 0x80: /* Bit String */ + switch (c = getc(f)) { + case 0x80: /* Bit String */ { int j; - c = getc(f); /* Byte count */ - if (debug) + c = getc(f); /* Byte count */ + if (debug) pm_message("bit string of %d bytes", c); - - if (col + c * 8 > cols + padright) - pm_error ("bad byte count"); - for (j = 0; j < c; ++j) { + + if (col + c * 8 > cols + padright) + pm_error ("bad byte count"); + for (j = 0; j < c; ++j) { int cc, k; - cc = getc(f); - for (k = 0x80; k; k >>= 1) { - bitrow[plane][col] = (k & cc) ? 0 : 1; - ++col; - } - } + cc = getc(f); + for (k = 0x80; k; k >>= 1) { + bitrow[plane][col] = (k & cc) ? 0 : 1; + ++col; + } + } } break; - case 0: /* Pattern run */ + case 0: /* Pattern run */ { int j, l; - c = getc(f); /* Repeat count */ - if (debug) - pm_message("pattern run of %d repetitions", c); + c = getc(f); /* Repeat count */ + if (debug) + pm_message("pattern run of %d repetitions", c); /* line repeat */ if (c == 0) { c = getc(f); @@ -158,25 +158,25 @@ main(argc, argv) linerep = getc(f); break; } - fread (pattern, 1, patlen, f); - if (col + c * patlen * 8 > cols + padright) - pm_error ("bad pattern repeat count"); - for (j = 0; j < c; ++j) - for (l = 0; l < patlen; ++l) { + fread (pattern, 1, patlen, f); + if (col + c * patlen * 8 > cols + padright) + pm_error ("bad pattern repeat count"); + for (j = 0; j < c; ++j) + for (l = 0; l < patlen; ++l) { int k; - for (k = 0x80; k; k >>= 1) { - bitrow[plane][col] = (k & pattern[l]) ? 0 : 1; - ++col; - } + for (k = 0x80; k; k >>= 1) { + bitrow[plane][col] = (k & pattern[l]) ? 0 : 1; + ++col; + } } } break; - default: /* Solid run */ + default: /* Solid run */ { int l, j; - if (debug) - pm_message("solid run of %d bytes %s", c & 0x7f, + if (debug) + pm_message("solid run of %d bytes %s", c & 0x7f, c & 0x80 ? "on" : "off" ); /* each byte had eight bits DSB */ l = (c & 0x80) ? 0: 1; @@ -185,23 +185,23 @@ main(argc, argv) pm_error ("bad solid run repeat count"); for (j = 0; j < c; ++j) { bitrow[plane][col] = l; - ++col; + ++col; } } - break; + break; - case EOF: /* End of file */ - pm_error( "end of file reached" ); + case EOF: /* End of file */ + pm_error( "end of file reached" ); - } - } + } + } if ( debug ) pm_message( "EOL plane %d row %d", plane, row ); if (col != cols + padright) pm_error( "EOL beyond edge" ); - } + } - if (planes == 4) { + if (planes == 4) { /* Construct a pixel from the 4 planes of bits for this row */ int col; for (col = 0; col < cols; col++) { @@ -212,21 +212,21 @@ main(argc, argv) const int b_bit = !bitrow[2][col]; i = bitrow[3][col]; - /* Deal with weird GEM palette - white/black/gray are - encoded oddly + /* Deal with weird GEM palette - white/black/gray are + encoded oddly */ - if (r_bit == g_bit && g_bit == b_bit) { + if (r_bit == g_bit && g_bit == b_bit) { /* It's black, white, or gray */ - if (r_bit && i) r = LIGHT; - else if (r_bit) r = BLACK; - else if (i) r = MAXVAL; - else r = DARK; - g = b = r; - } else { + if (r_bit && i) r = LIGHT; + else if (r_bit) r = BLACK; + else if (i) r = MAXVAL; + else r = DARK; + g = b = r; + } else { /* It's one of the twelve colored colors */ if (!i) { /* Low intensity */ - r = r_bit * LIGHT; + r = r_bit * LIGHT; g = g_bit * LIGHT; b = b_bit * LIGHT; } else { @@ -237,21 +237,21 @@ main(argc, argv) } } PPM_ASSIGN(xelrow[col], r, g, b); - } - } else { + } + } else { int col; - for (col = 0; col < cols; col++) + for (col = 0; col < cols; col++) PNM_ASSIGN1(xelrow[col], bitrow[0][col]); } - while (linerep--) { - pnm_writepnmrow( stdout, xelrow, cols, MAXVAL, type, 0 ); - ++row; - } - } + while (linerep--) { + pnm_writepnmrow( stdout, xelrow, cols, MAXVAL, type, 0 ); + ++row; + } + } pnm_freerow(xelrow); - pm_close( f ); - pm_close( stdout ); - exit(0); + pm_close( f ); + pm_close( stdout ); + exit(0); } @@ -303,3 +303,5 @@ getinit (file, colsP, rowsP, padrightP, patlenP, planesP) } } + + diff --git a/converter/other/giftopnm.c b/converter/other/giftopnm.c index 76cf4bff..e2d5923d 100644 --- a/converter/other/giftopnm.c +++ b/converter/other/giftopnm.c @@ -9,7 +9,7 @@ /* +-------------------------------------------------------------------+ */ /* There is a copy of the GIF89 specification, as defined by its inventor, - Compuserve, in 1990 at: + Compuserve, in 1990 at: http://www.w3.org/Graphics/GIF/spec-gif89a.txt This covers the high level format, but does not cover how the "data" @@ -19,10 +19,12 @@ describe the Lempel-Ziv base. */ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _BSD_SOURCE /* for strcaseeq */ #include <string.h> #include <assert.h> +#include <stdbool.h> #include "pm_config.h" #include "pm_c_util.h" @@ -41,13 +43,13 @@ #define MAX_LZW_BITS 12 #ifndef FASTPBMRENDER - #define FASTPBMRENDER TRUE + #define FASTPBMRENDER true #endif static const bool useFastPbmRender = FASTPBMRENDER; #ifndef REPORTLZWCODES - #define REPORTLZWCODES FALSE + #define REPORTLZWCODES false #endif static const bool wantLzwCodes = REPORTLZWCODES; @@ -60,7 +62,11 @@ readFile(FILE * const ifP, unsigned char * const buffer, size_t const len, const char ** const errorP) { +/*---------------------------------------------------------------------------- + Read the next 'len' bytes from *ifP into 'buffer'. + Fail if there aren't that many bytes to read. +-----------------------------------------------------------------------------*/ size_t bytesRead; bytesRead = fread(buffer, 1, len, ifP); @@ -91,7 +97,7 @@ struct CmdlineInfo { bool allImages; /* He wants all the images */ unsigned int imageNum; /* image number he wants from input, starting at 0. Undefined - if allImages is TRUE + if allImages is true */ const char * alphaFileName; unsigned int quitearly; @@ -101,7 +107,7 @@ struct CmdlineInfo { static void -parseCommandLine(int argc, char ** argv, +parseCommandLine(int argc, const char ** argv, struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that @@ -110,7 +116,7 @@ parseCommandLine(int argc, char ** argv, optEntry * option_def; /* Instructions to pm_optParseOptions3 on how to parse our options. */ - + optStruct3 opt; unsigned int alphaSpec, imageSpec; @@ -119,9 +125,9 @@ parseCommandLine(int argc, char ** argv, unsigned int option_def_index; MALLOCARRAY_NOFAIL(option_def, 100); - + option_def_index = 0; /* incremented by OPTENTRY */ - OPTENT3(0, "verbose", OPT_FLAG, NULL, + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); OPTENT3(0, "comments", OPT_FLAG, NULL, &cmdlineP->comments, 0); @@ -131,24 +137,24 @@ parseCommandLine(int argc, char ** argv, &cmdlineP->repair, 0); OPTENT3(0, "image", OPT_STRING, &image, &imageSpec, 0); - OPTENT3(0, "alphaout", OPT_STRING, &cmdlineP->alphaFileName, + OPTENT3(0, "alphaout", OPT_STRING, &cmdlineP->alphaFileName, &alphaSpec, 0); opt.opt_table = option_def; - opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ - opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + opt.short_allowed = false; /* We have no short (old-fashioned) options */ + opt.allowNegNum = false; /* We have no parms that are negative numbers */ - pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ free(option_def); if (!imageSpec) { cmdlineP->imageNum = 0; - cmdlineP->allImages = FALSE; + cmdlineP->allImages = false; } else { - if (strcaseeq(image, "all")) { - cmdlineP->allImages = TRUE; + if (strcaseeq(image, "all")) { + cmdlineP->allImages = true; } else { char * tailptr; @@ -164,12 +170,12 @@ parseCommandLine(int argc, char ** argv, pm_error("Invalid value for 'image' option. You specified " "zero. The first image is 1."); - cmdlineP->allImages = FALSE; + cmdlineP->allImages = false; cmdlineP->imageNum = (unsigned int) imageNum - 1; } } - - if (argc-1 == 0) + + if (argc-1 == 0) cmdlineP->inputFilespec = "-"; else if (argc-1 != 1) pm_error("Program takes zero or one argument (filename). You " @@ -177,7 +183,7 @@ parseCommandLine(int argc, char ** argv, else cmdlineP->inputFilespec = argv[1]; - if (!alphaSpec) + if (!alphaSpec) cmdlineP->alphaFileName = NULL; } @@ -249,13 +255,13 @@ struct GifScreen { /* Aspect ratio of each pixel, times 64, minus 15. (i.e. 1 => 1:4). But Zero means 1:1. */ - bool hasGray; + bool hasGray; /* Boolean: global colormap has at least one gray color - (not counting black and white) + (not counting black and white) */ bool hasColor; /* Boolean: global colormap has at least one non-gray, - non-black, non-white color + non-black, non-white color */ }; @@ -263,7 +269,7 @@ struct Gif89 { bool haveTransColor; /* The GIF specifies a transparent background color */ unsigned int transparentIndex; - /* The color index of the color which is the transparent + /* The color index of the color which is the transparent background color. Meaningful only when 'haveTransColor' is true @@ -282,7 +288,7 @@ initGif89(struct Gif89 * const gif89P) { gif89P->haveDelayTime = false; gif89P->haveInputFlag = false; gif89P->haveDisposal = false; -} +} static bool verbose; @@ -311,8 +317,8 @@ readColorMap(FILE * const ifP, assert(cmapSize <= MAXCOLORMAPSIZE); - *hasGrayP = FALSE; /* initial assumption */ - *hasColorP = FALSE; /* initial assumption */ + *hasGrayP = false; /* initial assumption */ + *hasColorP = false; /* initial assumption */ for (i = 0; i < cmapSize; ++i) { const char * error; @@ -326,23 +332,23 @@ readColorMap(FILE * const ifP, if (rgb[0] == rgb[1] && rgb[1] == rgb[2]) { if (rgb[0] != 0 && rgb[0] != GIFMAXVAL) - *hasGrayP = TRUE; + *hasGrayP = true; } else - *hasColorP = TRUE; + *hasColorP = true; } cmapP->size = cmapSize; } -static bool zeroDataBlock = FALSE; +static bool zeroDataBlock = false; /* the most recently read DataBlock was an EOD marker, i.e. had zero length */ static void -getDataBlock(FILE * const ifP, - unsigned char * const buf, +getDataBlock(FILE * const ifP, + unsigned char * const buf, bool * const eofP, unsigned int * const lengthP, const char ** const errorP) { @@ -354,10 +360,10 @@ getDataBlock(FILE * const ifP, of the datablock at 'buf', and its length as *lengthP. Except that if we hit EOF or have an I/O error reading the first - byte (size field) of the DataBlock, we return *eofP == TRUE and + byte (size field) of the DataBlock, we return *eofP == true and *lengthP == 0. - We return *eofP == FALSE if we don't hit EOF or have an I/O error. + We return *eofP == false if we don't hit EOF or have an I/O error. If we hit EOF or have an I/O error reading the data portion of the DataBlock, we exit the program with pm_error(). @@ -366,7 +372,7 @@ getDataBlock(FILE * const ifP, unsigned char count; const char * error; - + readFile(ifP, &count, sizeof(count), &error); if (error) { @@ -374,22 +380,22 @@ getDataBlock(FILE * const ifP, error); pm_strfree(error); *errorP = NULL; - *eofP = TRUE; + *eofP = true; *lengthP = 0; } else { if (verbose) pm_message("%d byte block at Position %ld", count, pos); - *eofP = FALSE; + *eofP = false; *lengthP = count; if (count == 0) { *errorP = NULL; - zeroDataBlock = TRUE; + zeroDataBlock = true; } else { const char * error; - zeroDataBlock = FALSE; - readFile(ifP, buf, count, &error); + zeroDataBlock = false; + readFile(ifP, buf, count, &error); if (error) { pm_asprintf(errorP, @@ -416,7 +422,7 @@ readThroughEod(FILE * const ifP) { unsigned char buf[256]; bool eod; - eod = FALSE; /* initial value */ + eod = false; /* initial value */ while (!eod) { bool eof; unsigned int count; @@ -429,7 +435,7 @@ readThroughEod(FILE * const ifP) { "anyway as if an EOD marker were at the end " "of the file."); if (error || eof || count == 0) - eod = TRUE; + eod = true; } } @@ -440,7 +446,7 @@ doPlainTextExtension(FILE * const ifP) { #if 0 /* incomplete code fragment, attempt to handle Plain Text Extension */ GetDataBlock(ifP, (unsigned char*) buf, &eof, &length); - + lpos = LM_to_uint(buf[0], buf[1]); tpos = LM_to_uint(buf[2], buf[3]); width = LM_to_uint(buf[4], buf[5]); @@ -461,25 +467,25 @@ doCommentExtension(FILE * const ifP) { /*---------------------------------------------------------------------------- Read the rest of a comment extension from the input file 'ifP' and handle it. - + We ought to deal with the possibility that the comment is not text. I.e. it could have nonprintable characters or embedded nulls. I don't know if the GIF spec requires regular text or not. -----------------------------------------------------------------------------*/ char buf[256]; - unsigned int blocklen; + unsigned int blocklen; bool done; - done = FALSE; + done = false; while (!done) { bool eof; const char * error; - getDataBlock(ifP, (unsigned char*) buf, &eof, &blocklen, &error); + getDataBlock(ifP, (unsigned char*) buf, &eof, &blocklen, &error); if (error) pm_error("Error reading a data block in a comment extension. %s", error); if (blocklen == 0 || eof) - done = TRUE; + done = true; else { buf[blocklen] = '\0'; if (showComment) { @@ -500,7 +506,7 @@ LM_to_uint(unsigned char const a, -static void +static void doGraphicControlExtension(FILE * const ifP, struct Gif89 * const gif89P) { @@ -515,7 +521,7 @@ doGraphicControlExtension(FILE * const ifP, if (eof) pm_error("EOF/error encountered reading " "1st DataBlock of Graphic Control Extension."); - else if (length < 4) + else if (length < 4) pm_error("graphic control extension 1st DataBlock too short. " "It must be at least 4 bytes; it is %d bytes.", length); @@ -542,7 +548,7 @@ doExtension(FILE * const ifP, struct Gif89 * const gif89P) { const char * str; - + switch (label) { case 0x01: /* Plain Text Extension */ str = "Plain Text"; @@ -576,7 +582,7 @@ doExtension(FILE * const ifP, struct GetCodeState { unsigned char buf[280]; - /* This is the buffer through which we read the data from the + /* This is the buffer through which we read the data from the stream. We must buffer it because we have to read whole data blocks at a time, but our client wants one code at a time. The buffer typically contains the contents of one data block @@ -599,7 +605,7 @@ struct GetCodeState { static void -getAnotherBlock(FILE * const ifP, +getAnotherBlock(FILE * const ifP, struct GetCodeState * const gsP, const char ** const errorP) { @@ -617,11 +623,11 @@ getAnotherBlock(FILE * const ifP, gsP->curbit -= (gsP->bufCount-2)*8; gsP->bufCount = 2; - + /* Add the next block to the buffer */ getDataBlock(ifP, &gsP->buf[gsP->bufCount], &eof, &count, errorP); if (*errorP) - gsP->streamExhausted = TRUE; + gsP->streamExhausted = true; else { if (eof) { pm_message("EOF encountered in image " @@ -634,7 +640,7 @@ getAnotherBlock(FILE * const ifP, assumedCount = count; gsP->streamExhausted = (assumedCount == 0); - + gsP->bufCount += assumedCount; } } @@ -645,13 +651,13 @@ static struct GetCodeState getCodeState; static void getCode_init(struct GetCodeState * const getCodeStateP) { - + /* Fake a previous data block */ getCodeStateP->buf[0] = 0; getCodeStateP->buf[1] = 0; getCodeStateP->bufCount = 2; getCodeStateP->curbit = getCodeStateP->bufCount * 8; - getCodeStateP->streamExhausted = FALSE; + getCodeStateP->streamExhausted = false; } @@ -669,7 +675,7 @@ bitsOfLeBuffer(const unsigned char * const buf, first byte of buf[]. We return the string as an integer such that its pure binary encoding with - the bits numbered Intel-style is the string. E.g. the string 0,1,1 + the bits numbered Intel-style is the string. E.g. the string 0,1,1 yields six. -----------------------------------------------------------------------------*/ uint32_t codeBlock; @@ -688,8 +694,8 @@ bitsOfLeBuffer(const unsigned char * const buf, (buf[start/8+0] << 0) | (buf[start/8+1] << 8) | (buf[start/8+2] << 16); - - return (unsigned int) + + return (unsigned int) (codeBlock >> (start % 8)) & ((1 << len) - 1); } @@ -697,7 +703,7 @@ bitsOfLeBuffer(const unsigned char * const buf, static void getCode_get(struct GetCodeState * const gsP, - FILE * const ifP, + FILE * const ifP, int const codeSize, bool * const eofP, unsigned int * const codeP, @@ -707,21 +713,21 @@ getCode_get(struct GetCodeState * const gsP, 'codeSize' is the number of bits in the code we are to get. - Return *eofP == TRUE iff we hit the end of the stream. That means a legal + Return *eofP == true iff we hit the end of the stream. That means a legal end of stream, marked by an EOD marker, not just end of file. An end of file in the middle of the GIF stream is an error. If there are bits left in the stream, but not 'codeSize' of them, we - call that a success with *eofP == TRUE. + call that a success with *eofP == true. - Return the code read (assuming *eofP == FALSE and *errorP == NULL) + Return the code read (assuming *eofP == false and *errorP == NULL) as *codeP. -----------------------------------------------------------------------------*/ *errorP = NULL; while (gsP->curbit + codeSize > gsP->bufCount * 8 && - !gsP->streamExhausted && !*errorP) + !gsP->streamExhausted && !*errorP) /* Not enough left in buffer to satisfy request. Get the next data block into the buffer. @@ -736,7 +742,7 @@ getCode_get(struct GetCodeState * const gsP, /* The buffer still doesn't have enough bits in it; that means there were no data blocks left to read. */ - *eofP = TRUE; + *eofP = true; { int const bitsUnused = gsP->bufCount * 8 - gsP->curbit; @@ -753,7 +759,7 @@ getCode_get(struct GetCodeState * const gsP, pm_message("LZW code=0x%03x [%d]", *codeP, codeSize); gsP->curbit += codeSize; - *eofP = FALSE; + *eofP = false; } } } @@ -769,7 +775,7 @@ struct Stack { -static void +static void initStack(struct Stack * const stackP, unsigned int const size) { MALLOCARRAY(stackP->stack, size); @@ -804,7 +810,7 @@ popStack(struct Stack * const stackP) { if (stackP->sp <= stackP->stack) pm_error("stack underflow"); - + return *(--stackP->sp); } @@ -816,14 +822,14 @@ termStack(struct Stack * const stackP) { stackP->stack = NULL; } - + /*---------------------------------------------------------------------------- Some notes on LZW. LZW is an extension of Limpel-Ziv. The two extensions are: - 1) in Limpel-Ziv, codes are all the same number of bits. In + 1) In Limpel-Ziv, codes are all the same number of bits. In LZW, they start out small and increase as the stream progresses. 2) LZW has a clear code that resets the string table and code @@ -833,33 +839,55 @@ termStack(struct Stack * const stackP) { The true data elements are dataWidth bits wide, so the maximum value of a true data element is 2**dataWidth-1. We call that - max_dataVal. The first byte in the stream tells you what dataWidth + maxDataVal. The first byte in the stream tells you what dataWidth is. - LZW codes 0 - max_dataVal are direct codes. Each one represents + LZW codes 0 - maxDataVal are direct codes. Each one represents the true data element whose value is that of the LZW code itself. No decompression is required. - max_dataVal + 1 and up are compression codes. They encode + maxDataVal + 1 and up are compression codes. They encode true data elements: - max_dataVal + 1 is the clear code. - - max_dataVal + 2 is the end code. + maxDataVal + 1 is the clear code. + + maxDataVal + 2 is the end code. - max_dataVal + 3 and up are string codes. Each string code + maxDataVal + 3 and up are string codes. Each string code represents a string of true data elements. The translation from a string code to the string of true data elements varies as the stream progresses. In the beginning and after every clear code, the translation table is empty, so no string codes are valid. As the - stream progresses, the table gets filled and more string codes + stream progresses, the table gets filled and more string codes become valid. + At the beginning of the stream, string codes are represented by + dataWidth + 1 bits. When enough codes have been defined to use up that + space, they start being represented by dataWidth + 2 bits, and so on. + + What we call 'dataWidth', others call the "minimum code size," which is a + misnomer, because the minimum code size in a stream must be at least one + more than 'dataWidth', to accomodate the clear and end codes. -----------------------------------------------------------------------------*/ static int const maxLzwCodeCt = (1<<MAX_LZW_BITS); -struct Decompressor { +typedef struct { +/*---------------------------------------------------------------------------- + An entry in the decompressor LZW code table. +-----------------------------------------------------------------------------*/ + unsigned int next; + /* The next code in the expansion after the one this entry specifies; + this is either another index into the LZW code table or a direct + code, which means it's the last data element in the expansion. + */ + unsigned int dataElement; + /* The data element (color map index or gray level) to add to the + expansion for this entry. + */ +} CodeTableEntry; + +typedef struct { struct Stack stack; bool fresh; /* The stream is right after a clear code or at the very beginning */ @@ -869,7 +897,7 @@ struct Decompressor { the stream. */ unsigned int maxCodeCt; - /* The maximum number of LZW codes that can be represented with the + /* The maximum number of LZW codes that can be represented with the current code size. (1 << codeSize) */ unsigned int nextTableSlot; @@ -882,6 +910,9 @@ struct Decompressor { /* The following are constant for the life of the decompressor */ FILE * ifP; unsigned int initCodeSize; + /* The code size, in bits, at the start of the stream and immediately + after a Clear code. + */ unsigned int cmapSize; unsigned int maxDataVal; unsigned int clearCode; @@ -889,22 +920,28 @@ struct Decompressor { bool haveTransColor; unsigned int transparentIndex; /* meaningful only when 'haveTransColor' is true */ - bool tolerateBadInput; + bool tolerateBadInput; /* We are to tolerate bad input data as best we can, rather than just declaring an error and bailing out. */ - unsigned int table[(1 << MAX_LZW_BITS)][2]; /* LZW code table */ -}; + CodeTableEntry table[(1 << MAX_LZW_BITS)]; /* LZW code table */ + /* This contains the strings of expansions of LZW string codes, in + linked list form. table[N] gives the first data element for the + string with string code N and the LZW code for the rest of the + string. The latter is often a string code itself, which can also + be looked up in this table. + */ +} Decompressor; static void -resetDecompressor(struct Decompressor * const decompP) { +resetDecompressor(Decompressor * const decompP) { - decompP->codeSize = decompP->initCodeSize+1; + decompP->codeSize = decompP->initCodeSize; decompP->maxCodeCt = 1 << decompP->codeSize; decompP->nextTableSlot = decompP->maxDataVal + 3; - decompP->fresh = TRUE; + decompP->fresh = true; } @@ -918,7 +955,7 @@ validateTransparentIndex(unsigned int const transparentIndex, if (transparentIndex >= cmapSize) { if (tolerateBadInput) { if (transparentIndex > maxDataVal) - pm_error("Invalid transparent index value: %d", + pm_error("Invalid transparent index value: %u", transparentIndex); } else { pm_error("Invalid transparent index value %d in image with " @@ -935,23 +972,21 @@ validateTransparentIndex(unsigned int const transparentIndex, static void -lzwInit(struct Decompressor * const decompP, - FILE * const ifP, - int const initCodeSize, - unsigned int const cmapSize, - bool const haveTransColor, - unsigned int const transparentIndex, - bool const tolerateBadInput) { - - unsigned int const maxDataVal = (1 << initCodeSize) - 1; - +lzwInit(Decompressor * const decompP, + FILE * const ifP, + int const dataWidth, + unsigned int const cmapSize, + bool const haveTransColor, + unsigned int const transparentIndex, + bool const tolerateBadInput) { + + unsigned int const maxDataVal = (1 << dataWidth) - 1; + if (verbose) - pm_message("Image says the initial compression code size is " - "%d bits", - initCodeSize); - + pm_message("Image says the data width is %u bits", dataWidth); + decompP->ifP = ifP; - decompP->initCodeSize = initCodeSize; + decompP->initCodeSize = dataWidth + 1; decompP->cmapSize = cmapSize; decompP->tolerateBadInput = tolerateBadInput; decompP->maxDataVal = maxDataVal; @@ -961,9 +996,9 @@ lzwInit(struct Decompressor * const decompP, if (verbose) pm_message("Initial code size is %u bits; clear code = 0x%03x, " "end code = 0x%03x", - decompP->initCodeSize, + decompP->initCodeSize, decompP->clearCode, decompP->endCode); - + /* The entries in the translation table for true data codes are constant throughout the image. For PBM output we make an adjustment later. Once set entries never change. @@ -971,8 +1006,8 @@ lzwInit(struct Decompressor * const decompP, { unsigned int i; for (i = 0; i <= maxDataVal; ++i) { - decompP->table[i][0] = 0; - decompP->table[i][1] = i < cmapSize ? i : 0; + decompP->table[i].next = 0; + decompP->table[i].dataElement = i < cmapSize ? i : 0; } } decompP->haveTransColor = haveTransColor; @@ -985,19 +1020,19 @@ lzwInit(struct Decompressor * const decompP, resetDecompressor(decompP); getCode_init(&getCodeState); - - decompP->fresh = TRUE; - + + decompP->fresh = true; + initStack(&decompP->stack, maxLzwCodeCt); - assert(decompP->initCodeSize < sizeof(decompP->maxDataVal) * 8); + assert(decompP->initCodeSize < sizeof(decompP->maxDataVal) * 8 + 1); } static void -lzwAdjustForPBM(struct Decompressor * const decompP, - GifColorMap const cmap) { +lzwAdjustForPBM(Decompressor * const decompP, + GifColorMap const cmap) { /*---------------------------------------------------------------------------- In the PBM case we use the table index value directly instead of looking up the color map for each pixel. @@ -1008,13 +1043,14 @@ lzwAdjustForPBM(struct Decompressor * const decompP, ----------------------------------------------------------------------------*/ unsigned int i; for (i = 0; i < cmap.size; ++i) - decompP->table[i][1] = cmap.map[i][0] == 0 ? PBM_BLACK : PBM_WHITE; + decompP->table[i].dataElement = + cmap.map[i][0] == 0 ? PBM_BLACK : PBM_WHITE; } static void -lzwTerm(struct Decompressor * const decompP) { +lzwTerm(Decompressor * const decompP) { termStack(&decompP->stack); } @@ -1022,8 +1058,8 @@ lzwTerm(struct Decompressor * const decompP) { static void -pushWholeStringOnStack(struct Decompressor * const decompP, - unsigned int const code0) { +pushWholeStringOnStack(Decompressor * const decompP, + unsigned int const code0) { /*---------------------------------------------------------------------------- Get the whole string that compression code 'code0' represents and push it onto the code stack so the leftmost code is on top. Set @@ -1034,21 +1070,47 @@ pushWholeStringOnStack(struct Decompressor * const decompP, for (stringCount = 0, code = code0; code > decompP->maxDataVal; - ++stringCount, code = decompP->table[code][0] + ++stringCount, code = decompP->table[code].next ) { - pushStack(&decompP->stack, decompP->table[code][1]); + pushStack(&decompP->stack, decompP->table[code].dataElement); } - decompP->firstcode = decompP->table[code][1]; + decompP->firstcode = decompP->table[code].dataElement; pushStack(&decompP->stack, decompP->firstcode); } static void -expandCodeOntoStack(struct Decompressor * const decompP, - unsigned int const incode, - const char ** const errorP) { +addLzwStringCode(Decompressor * const decompP) { + + if (decompP->nextTableSlot < maxLzwCodeCt) { + decompP->table[decompP->nextTableSlot].next = + decompP->prevcode; + decompP->table[decompP->nextTableSlot].dataElement = + decompP->firstcode; + ++decompP->nextTableSlot; + if (decompP->nextTableSlot >= decompP->maxCodeCt) { + /* We've used up all the codes of the current code size. + Future codes in the stream will have codes one bit longer. + But there's an exception if we're already at the LZW + maximum, in which case the codes will simply continue + the same size and no new ones will be defined. + */ + if (decompP->codeSize < MAX_LZW_BITS) { + ++decompP->codeSize; + decompP->maxCodeCt = 1 << decompP->codeSize; + } + } + } +} + + + +static void +expandCodeOntoStack(Decompressor * const decompP, + unsigned int const incode, + const char ** const errorP) { /*---------------------------------------------------------------------------- 'incode' is an LZW string code. It represents a string of true data elements, as defined by the string translation table in *decompP. @@ -1063,58 +1125,56 @@ expandCodeOntoStack(struct Decompressor * const decompP, as *errorP). -----------------------------------------------------------------------------*/ unsigned int code; + const char * gifError; - *errorP = NULL; /* Initial value */ + gifError = NULL; /* Initial value */ if (incode <= decompP->maxDataVal) { if (incode < decompP->cmapSize) code = incode; /* Direct index */ else if (decompP->tolerateBadInput && decompP->haveTransColor && - decompP->table[incode][1] == decompP->transparentIndex) + decompP->table[incode].dataElement == + decompP->transparentIndex) /* transparent code outside cmap exceptional case */ code = incode; else - pm_asprintf(errorP, "Error in GIF image: invalid color code %u. " + pm_asprintf(&gifError, "Invalid color code %u. " "Valid color values are 0 - %u", incode, decompP->cmapSize - 1); - } - else if (incode < decompP->nextTableSlot) + } else if (incode < decompP->nextTableSlot) /* LZW string, defined */ code = incode; - else if (incode == decompP->nextTableSlot && !decompP->fresh) { + else if (incode == decompP->nextTableSlot) { /* It's a code that isn't in our translation table yet. - This does not happen with the decoder in a fresh state. */ - if (wantLzwCodes && verbose) - pm_message ("LZW code valid, but not in decoder table"); + if (decompP->fresh) + pm_asprintf(&gifError, "LZW string code encountered with " + "decompressor in fresh state"); + else { + if (wantLzwCodes && verbose) + pm_message ("LZW code valid, but not in decoder table"); - pushStack(&decompP->stack, decompP->firstcode); - code = decompP->prevcode; + pushStack(&decompP->stack, decompP->firstcode); + code = decompP->prevcode; + } } else - pm_asprintf(errorP, "Error in GIF image: invalid LZW code"); - - if (!*errorP) { + pm_asprintf(&gifError, "LZW string code %u " + "is neither a previously defined one nor the " + "next in sequence to define (%u)", + incode, decompP->nextTableSlot); + + if (gifError) { + pm_asprintf(errorP, "INVALID GIF IMAGE: %s", gifError); + pm_strfree(gifError); + } else { pushWholeStringOnStack(decompP, code); - if (decompP->nextTableSlot < maxLzwCodeCt) { - decompP->table[decompP->nextTableSlot][0] = decompP->prevcode; - decompP->table[decompP->nextTableSlot][1] = decompP->firstcode; - ++decompP->nextTableSlot; - if (decompP->nextTableSlot >= decompP->maxCodeCt) { - /* We've used up all the codes of the current code size. - Future codes in the stream will have codes one bit longer. - But there's an exception if we're already at the LZW - maximum, in which case the codes will simply continue - the same size. - */ - if (decompP->codeSize < MAX_LZW_BITS) { - ++decompP->codeSize; - decompP->maxCodeCt = 1 << decompP->codeSize; - } - } - } + addLzwStringCode(decompP); + decompP->prevcode = incode; + + *errorP = NULL; } } @@ -1122,7 +1182,7 @@ expandCodeOntoStack(struct Decompressor * const decompP, static void lzwReadByteFresh(struct GetCodeState * const getCodeStateP, - struct Decompressor * const decompP, + Decompressor * const decompP, bool * const endOfImageP, unsigned char * const dataReadP, const char ** const errorP) { @@ -1142,7 +1202,7 @@ lzwReadByteFresh(struct GetCodeState * const getCodeStateP, assert(decompP->fresh); /* Entry requirement */ - decompP->fresh = FALSE; + decompP->fresh = false; do { getCode_get(getCodeStateP, decompP->ifP, decompP->codeSize, @@ -1151,12 +1211,12 @@ lzwReadByteFresh(struct GetCodeState * const getCodeStateP, if (!*errorP) { if (eof) - *endOfImageP = TRUE; + *endOfImageP = true; else if (code == decompP->endCode) { if (!zeroDataBlock) readThroughEod(decompP->ifP); - *endOfImageP = TRUE; - } else if (code >= decompP->cmapSize) { + *endOfImageP = true; + } else if (code >= decompP->cmapSize) { pm_asprintf(errorP, "Error in GIF image: invalid color code %u. " "Valid color values are: 0 - %u", code, decompP->cmapSize-1); @@ -1165,12 +1225,12 @@ lzwReadByteFresh(struct GetCodeState * const getCodeStateP, */ decompP->prevcode = decompP->firstcode = 0; - *endOfImageP = FALSE; + *endOfImageP = false; } else { /* valid code */ decompP->prevcode = code; - decompP->firstcode = decompP->table[code][1]; + decompP->firstcode = decompP->table[code].dataElement; *dataReadP = decompP->firstcode; - *endOfImageP = FALSE; + *endOfImageP = false; } } } @@ -1179,10 +1239,10 @@ lzwReadByteFresh(struct GetCodeState * const getCodeStateP, static void -lzwReadByte(struct Decompressor * const decompP, - unsigned char * const dataReadP, - bool * const endOfImageP, - const char ** const errorP) { +lzwReadByte(Decompressor * const decompP, + unsigned char * const dataReadP, + bool * const endOfImageP, + const char ** const errorP) { /*---------------------------------------------------------------------------- Return the next data element of the decompressed image. In the context of a GIF, a data element is the color table index of one pixel. @@ -1201,7 +1261,7 @@ lzwReadByte(struct Decompressor * const decompP, -----------------------------------------------------------------------------*/ if (!stackIsEmpty(&decompP->stack)) { *errorP = NULL; - *endOfImageP = FALSE; + *endOfImageP = false; *dataReadP = popStack(&decompP->stack); } else if (decompP->fresh) { lzwReadByteFresh(&getCodeState, decompP, endOfImageP, dataReadP, @@ -1224,10 +1284,10 @@ lzwReadByte(struct Decompressor * const decompP, if (code == decompP->endCode) { if (!zeroDataBlock) readThroughEod(decompP->ifP); - *endOfImageP = TRUE; + *endOfImageP = true; *errorP = NULL; } else { - *endOfImageP = FALSE; + *endOfImageP = false; expandCodeOntoStack(decompP, code, errorP); if (!*errorP) *dataReadP = popStack(&decompP->stack); @@ -1255,7 +1315,7 @@ bumpRowInterlace(unsigned int const rows, MULT4PLUS2: Rows 2, 6, 10, 14, etc. MULT2PLUS1: Rows 1, 3, 5, 7, 9, etc. */ - + switch (*passP) { case MULT8PLUS0: *rowP += 8; @@ -1300,7 +1360,7 @@ bumpRowInterlace(unsigned int const rows, static void renderRow(unsigned char * const cmapIndexRow, unsigned int const cols, - GifColorMap const cmap, + GifColorMap const cmap, bool const haveTransColor, unsigned int const transparentIndex, FILE * const imageOutfile, @@ -1311,11 +1371,14 @@ renderRow(unsigned char * const cmapIndexRow, /*---------------------------------------------------------------------------- Convert one row of cmap indexes to PPM/PGM/PBM output. + The row is *xelrow, which is 'cols' columns wide and has pixels of format + 'format'. + Render the alpha row to *alphaFileP iff 'alphabits' is non-NULL. If 'haveTransColor' is false, render all white (i.e. the row is opaque). 'alphabits' is otherwise just a one-row buffer for us to use in rendering the alpha row. - + imageOutfile is NULL if user wants only the alpha file. ----------------------------------------------------------------------------*/ if (alphabits) { @@ -1332,7 +1395,7 @@ renderRow(unsigned char * const cmapIndexRow, if (imageOutfile) { if (useFastPbmRender && format == PBM_FORMAT && !haveTransColor) { - bit * const bitrow = cmapIndexRow; + bit * const bitrow = cmapIndexRow; pbm_writepbmrow(imageOutfile, bitrow, cols, false); } else { @@ -1386,7 +1449,7 @@ pnmFormat(bool const hasGray, -----------------------------------------------------------------------------*/ int format; const char * formatName; - + if (hasColor) { format = PPM_FORMAT; formatName = "PPM"; @@ -1397,21 +1460,21 @@ pnmFormat(bool const hasGray, format = PBM_FORMAT; formatName = "PBM"; } - if (verbose) + if (verbose) pm_message("writing a %s file", formatName); - + return format; } static void -makePnmRow(struct Decompressor * const decompP, - unsigned int const cols, - unsigned int const rows, - bool const fillWithZero, - unsigned char * const cmapIndexRow, - const char ** const errorP) { +makePnmRow(Decompressor * const decompP, + unsigned int const cols, + unsigned int const rows, + bool const fillWithZero, + unsigned char *const cmapIndexRow, + const char ** const errorP) { bool fillingWithZero; unsigned int col; @@ -1426,7 +1489,7 @@ makePnmRow(struct Decompressor * const decompP, if (fillingWithZero) colorIndex = 0; - else { + else { const char * readError; unsigned char readColorIndex; bool endOfImage; @@ -1455,15 +1518,15 @@ makePnmRow(struct Decompressor * const decompP, static void -convertRaster(struct Decompressor * const decompP, - unsigned int const cols, - unsigned int const rows, - GifColorMap const cmap, - bool const interlace, - FILE * const imageOutFileP, - FILE * const alphaFileP, - bool const hasGray, - bool const hasColor) { +convertRaster(Decompressor * const decompP, + unsigned int const cols, + unsigned int const rows, + GifColorMap const cmap, + bool const interlace, + FILE * const imageOutFileP, + FILE * const alphaFileP, + bool const hasGray, + bool const hasColor) { /*---------------------------------------------------------------------------- Read the raster from the GIF decompressor *decompP, and write it as a complete PNM stream (starting with the header) on *imageOutFileP and @@ -1492,11 +1555,11 @@ convertRaster(struct Decompressor * const decompP, MALLOCARRAY2(cmapIndexArray, interlace ? rows : 1 , cols); if (imageOutFileP) - pnm_writepnminit(imageOutFileP, cols, rows, GIFMAXVAL, format, FALSE); + pnm_writepnminit(imageOutFileP, cols, rows, GIFMAXVAL, format, false); if (alphaFileP) - pbm_writepbminit(alphaFileP, cols, rows, FALSE); + pbm_writepbminit(alphaFileP, cols, rows, false); - xelrow = pnm_allocrow(cols); + xelrow = pnm_allocrow(cols); if (!xelrow) pm_error("couldn't alloc space for image" ); @@ -1540,10 +1603,10 @@ convertRaster(struct Decompressor * const decompP, decompP->haveTransColor, decompP->transparentIndex, imageOutFileP, format, xelrow, alphaFileP, alphabits); } - /* All rows decompressed (and rendered and output if non-interlaced) */ + /* All rows decompressed (and rendered and output if non-interlaced) */ if (interlace) { unsigned int row; - for (row = 0; row < rows; ++row) + for (row = 0; row < rows; ++row) renderRow(cmapIndexArray[row], cols, cmap, decompP->haveTransColor, decompP->transparentIndex, imageOutFileP, format, xelrow, alphaFileP, alphabits); @@ -1558,13 +1621,13 @@ convertRaster(struct Decompressor * const decompP, static void -skipExtraneousData(struct Decompressor * const decompP) { +skipExtraneousData(Decompressor * const decompP) { unsigned char byteRead; bool endOfImage; const char * error; - endOfImage = FALSE; /* initial value */ + endOfImage = false; /* initial value */ lzwReadByte(decompP, &byteRead, &endOfImage, &error); @@ -1591,13 +1654,13 @@ skipExtraneousData(struct Decompressor * const decompP) { static void issueTransparencyMessage(bool const haveTransColor, - unsigned int const transparentIndex, + unsigned int const transparentIndex, GifColorMap const cmap) { /*---------------------------------------------------------------------------- If user wants verbose output, tell him whether there is a transparent background color ('haveTransColor') and if so what it is ('transparentIndex'). - + Some GIFs put transparentIndex outside the color map. Allow this only with "-repair", checked in lzwInit(). Here we issue a warning and report the substitute color. @@ -1632,10 +1695,10 @@ issueTransparencyMessage(bool const haveTransColor, static void -readImageData(FILE * const ifP, +readImageData(FILE * const ifP, unsigned int const cols, unsigned int const rows, - GifColorMap const cmap, + GifColorMap const cmap, bool const interlace, bool const haveTransColor, unsigned int const transparentIndex, @@ -1645,22 +1708,25 @@ readImageData(FILE * const ifP, bool const hasColor, bool const tolerateBadInput) { - unsigned char lzwMinCodeSize; - struct Decompressor decomp; + unsigned char lzwDataWidth; + Decompressor decomp; const char * error; - readFile(ifP, &lzwMinCodeSize, sizeof(lzwMinCodeSize), &error); + readFile(ifP, &lzwDataWidth, sizeof(lzwDataWidth), &error); if (error) pm_error("Can't read GIF stream " "right after an image separator; no " "image data follows. %s", error); - if (lzwMinCodeSize > MAX_LZW_BITS) - pm_error("Invalid minimum code size value in image data: %u. " - "Maximum allowable code size in GIF is %u", - lzwMinCodeSize, MAX_LZW_BITS); + if (lzwDataWidth+1 > MAX_LZW_BITS) + pm_error("Invalid data width (bits for a true data item) " + "in image data: %u. " + "Maximum allowable code size in GIF is %u, " + "and a code has to be wide enough to accomodate both " + "all possible data values and two control codes", + lzwDataWidth, MAX_LZW_BITS); - lzwInit(&decomp, ifP, lzwMinCodeSize, cmap.size, + lzwInit(&decomp, ifP, lzwDataWidth, cmap.size, haveTransColor, transparentIndex, tolerateBadInput); issueTransparencyMessage(haveTransColor, transparentIndex, cmap); @@ -1721,24 +1787,24 @@ readGifHeader(FILE * const gifFileP, readFile(gifFileP, buf, 6, &error); if (error) pm_error("Error reading magic number. %s", error); - + if (!strneq((char *)buf, "GIF", 3)) pm_error("File does not contain a GIF stream. It does not start " "with 'GIF'."); - + strncpy(version, (char *)buf + 3, 3); version[3] = '\0'; - + if (verbose) pm_message("GIF format version is '%s'", version); - + if ((!streq(version, "87a")) && (!streq(version, "89a"))) pm_error("Bad version number, not '87a' or '89a'" ); - + readFile(gifFileP, buf, 7, &error); if (error) pm_error("Failed to read screen descriptor. %s", error); - + gifScreenP->width = LM_to_uint(buf[0],buf[1]); gifScreenP->height = LM_to_uint(buf[2],buf[3]); cmapSize = 1 << ((buf[4] & 0x07) + 1); @@ -1749,25 +1815,25 @@ readGifHeader(FILE * const gifFileP, if (verbose) { pm_message("GIF Width = %u GIF Height = %u " "Pixel aspect ratio = %u (%f:1)", - gifScreenP->width, gifScreenP->height, - gifScreenP->aspectRatio, - gifScreenP->aspectRatio == 0 ? + gifScreenP->width, gifScreenP->height, + gifScreenP->aspectRatio, + gifScreenP->aspectRatio == 0 ? 1 : (gifScreenP->aspectRatio + 15) / 64.0); pm_message("Global color count = %u Color Resolution = %u", cmapSize, gifScreenP->colorResolution); - } + } if (buf[4] & GLOBALCOLORMAP) { gifScreenP->hasGlobalColorMap = true; readColorMap(gifFileP, cmapSize, &gifScreenP->colorMap, &gifScreenP->hasGray, &gifScreenP->hasColor); if (verbose) { - pm_message("Global color map %s grays, %s colors", + pm_message("Global color map %s grays, %s colors", gifScreenP->hasGray ? "contains" : "doesn't contain", gifScreenP->hasColor ? "contains" : "doesn't contain"); } } else gifScreenP->hasGlobalColorMap = false; - + if (gifScreenP->aspectRatio != 0 && gifScreenP->aspectRatio != 49) warnUserNotSquare(gifScreenP->aspectRatio); @@ -1777,7 +1843,7 @@ readGifHeader(FILE * const gifFileP, static void -readExtensions(FILE* const ifP, +readExtensions(FILE* const ifP, struct Gif89 * const gif89P, bool * const eodP, const char ** const errorP) { @@ -1786,8 +1852,8 @@ readExtensions(FILE* const ifP, positioned. Read up through the image separator that begins the next image or GIF stream terminator. - If we encounter EOD (end of GIF stream) before we find an image - separator, we return *eodP == TRUE. Else *eodP == FALSE. + If we encounter EOD (end of GIF stream) before we find an image + separator, we return *eodP == true. Else *eodP == false. If we hit end of file before an EOD marker, we fail. -----------------------------------------------------------------------------*/ @@ -1796,8 +1862,8 @@ readExtensions(FILE* const ifP, *errorP = NULL; /* initial value */ - eod = FALSE; - imageStart = FALSE; + eod = false; + imageStart = false; /* Read the image descriptor */ while (!imageStart && !eod && !*errorP) { @@ -1813,7 +1879,7 @@ readExtensions(FILE* const ifP, pm_strfree(error); } else { if (c == ';') { /* GIF terminator */ - eod = TRUE; + eod = true; } else if (c == '!') { /* Extension */ unsigned char functionCode; const char * error; @@ -1828,9 +1894,9 @@ readExtensions(FILE* const ifP, } else { doExtension(ifP, functionCode, gif89P); } - } else if (c == ',') - imageStart = TRUE; - else + } else if (c == ',') + imageStart = true; + else pm_message("Encountered invalid character 0x%02x while " "seeking extension block, ignoring", (int)c); } @@ -1846,7 +1912,7 @@ struct GifImageHeader { -----------------------------------------------------------------------------*/ bool hasLocalColormap; /* The image has its own color map. Its size is 'localColorMapSize' */ - /* (If an image does not have its own color map, the image uses the + /* (If an image does not have its own color map, the image uses the global color map for the GIF stream) */ unsigned int localColorMapSize; @@ -1875,7 +1941,7 @@ reportImageHeader(struct GifImageHeader const imageHeader) { if (imageHeader.lpos > 0 || imageHeader.tpos > 0) pm_message(" Image left position: %u top position: %u", imageHeader.lpos, imageHeader.tpos); - + if (imageHeader.hasLocalColormap) pm_message(" Uses local colormap of %u colors", imageHeader.localColorMapSize); @@ -1921,7 +1987,7 @@ validateWithinGlobalScreen(struct GifImageHeader const imageHeader, struct GifScreen const gifScreen) { unsigned long int const rpos = imageHeader.lpos + imageHeader.cols; - unsigned long int const bpos = imageHeader.tpos + imageHeader.rows; + unsigned long int const bpos = imageHeader.tpos + imageHeader.rows; if (rpos > gifScreen.width) pm_error("Image right end (%lu) is outside global screen: %u x %u", @@ -1950,17 +2016,17 @@ skipImageData(FILE * const ifP) { static void -convertImage(FILE * const ifP, - bool const skipIt, - FILE * const imageoutFileP, - FILE * const alphafileP, +convertImage(FILE * const ifP, + bool const skipIt, + FILE * const imageoutFileP, + FILE * const alphafileP, struct GifScreen const gifScreen, struct Gif89 const gif89, bool const tolerateBadInput) { /*---------------------------------------------------------------------------- Read a single GIF image from the current position of file 'ifP'. - If 'skipIt' is TRUE, don't do anything else. Otherwise, write the + If 'skipIt' is true, don't do anything else. Otherwise, write the image to the current position of files *imageoutFileP and *alphafileP. If *alphafileP is NULL, though, don't write any alpha information. -----------------------------------------------------------------------------*/ @@ -1974,7 +2040,7 @@ convertImage(FILE * const ifP, validateWithinGlobalScreen(imageHeader, gifScreen); if (imageHeader.hasLocalColormap) { - readColorMap(ifP, imageHeader.localColorMapSize, &localColorMap, + readColorMap(ifP, imageHeader.localColorMapSize, &localColorMap, &hasGray, &hasColor); currentColorMapP = &localColorMap; } else if (gifScreen.hasGlobalColorMap) { @@ -2015,18 +2081,18 @@ disposeOfReadExtensionsError(const char * const error, pm_error("Error accessing Image %u of stream. %s", imageSeq, error); pm_strfree(error); - *eodP = TRUE; + *eodP = true; } } static void -convertImages(FILE * const ifP, +convertImages(FILE * const ifP, bool const allImages, - unsigned int const requestedImageSeq, + unsigned int const requestedImageSeq, bool const drainStream, - FILE * const imageOutFileP, + FILE * const imageOutFileP, FILE * const alphaFileP, bool const tolerateBadInput) { /*---------------------------------------------------------------------------- @@ -2034,9 +2100,9 @@ convertImages(FILE * const ifP, it as PNM images to file 'imageOutFileP'. If the images have transparency and 'alphafile' is non-NULL, write PGM alpha masks to file 'alphaFileP'. - 'allImages' means Caller wants all the images in the stream. + 'allImages' means Caller wants all the images in the stream. - 'requestedImageSeq' is meaningful only when 'allImages' is FALSE. It + 'requestedImageSeq' is meaningful only when 'allImages' is false. It is the sequence number of the one image Caller wants from the stream, with the first image being 0. @@ -2062,7 +2128,7 @@ convertImages(FILE * const ifP, readGifHeader(ifP, &gifScreen); - for (imageSeq = 0, eod = FALSE; + for (imageSeq = 0, eod = false; !eod && (allImages || imageSeq <= requestedImageSeq || drainStream); ++imageSeq) { @@ -2083,7 +2149,7 @@ convertImages(FILE * const ifP, if (verbose) pm_message("Reading Image Sequence %u", imageSeq); - convertImage(ifP, !allImages && (imageSeq != requestedImageSeq), + convertImage(ifP, !allImages && (imageSeq != requestedImageSeq), imageOutFileP, alphaFileP, gifScreen, gif89, tolerateBadInput); } @@ -2093,19 +2159,19 @@ convertImages(FILE * const ifP, int -main(int argc, char **argv) { +main(int argc, const char **argv) { struct CmdlineInfo cmdline; FILE * ifP; FILE * alphaFileP; FILE * imageOutFileP; - pnm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); verbose = cmdline.verbose; showComment = cmdline.comments; - + ifP = pm_openr(cmdline.inputFilespec); if (cmdline.alphaFileName == NULL) @@ -2118,12 +2184,12 @@ main(int argc, char **argv) { else imageOutFileP = stdout; - convertImages(ifP, cmdline.allImages, cmdline.imageNum, + convertImages(ifP, cmdline.allImages, cmdline.imageNum, !cmdline.quitearly, imageOutFileP, alphaFileP, cmdline.repair); pm_close(ifP); - if (imageOutFileP != NULL) + if (imageOutFileP != NULL) pm_close(imageOutFileP); if (alphaFileP != NULL) pm_close(alphaFileP); @@ -2132,4 +2198,3 @@ main(int argc, char **argv) { } - diff --git a/converter/other/ipdb.c b/converter/other/ipdb.c index 7ee37872..5e4dc82e 100644 --- a/converter/other/ipdb.c +++ b/converter/other/ipdb.c @@ -19,6 +19,7 @@ * Authors: Eric A. Howe (mu@trends.net) * Bryan Henderson, 2010 */ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _BSD_SOURCE /* Ensure strdup() is in <string.h> */ #include <assert.h> @@ -282,8 +283,8 @@ ipdb_image_alloc(const char * const name, if (w != 0 && h != 0) { MALLOCARRAY(imgP->data, w * h); - if (imgP->data) { - memset(imgP->data, 0, sizeof(*(imgP->data)) * w * h); + if (imgP->data != NULL) { + memset(imgP->data, 0, sizeof(*(imgP->data)) * w * h); } else failed = true; } diff --git a/converter/other/jbig/jbigtopnm.c b/converter/other/jbig/jbigtopnm.c index 733ba227..0d55ccc1 100644 --- a/converter/other/jbig/jbigtopnm.c +++ b/converter/other/jbig/jbigtopnm.c @@ -1,22 +1,93 @@ /* jbigtopnm - JBIG to PNM converter - + This program was derived from jbgtopbm.c in Markus Kuhn's JBIG-KIT package by Bryan Henderson on 2000.05.11 The main difference is that this version uses the Netpbm libraries. - + */ +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> +#include <limits.h> + #include <jbig.h> + #include "pnm.h" +#include "shhopt.h" +#include "mallocvar.h" #define BUFSIZE 8192 + +typedef struct { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileName; + const char * outputFileName; + unsigned long xmax; + unsigned long ymax; + unsigned int binary; + unsigned int diagnose; + unsigned int planeSpec; + unsigned int plane; +} CmdlineInfo; + + + +static void +parseCommandLine(int argc, + const char ** const argv, + CmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that the file spec array we return is stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optEntry * option_def; + + optStruct3 opt; + + unsigned int xmaxSpec, ymaxSpec; + + unsigned int option_def_index; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "binary", OPT_FLAG, NULL, &cmdlineP->binary, 0); + OPTENT3(0, "diagnose", OPT_FLAG, NULL, &cmdlineP->diagnose, 0); + OPTENT3(0, "plane", OPT_UINT, &cmdlineP->plane, &cmdlineP->planeSpec,0); + OPTENT3(0, "xmax", OPT_UINT, &cmdlineP->xmax, &xmaxSpec, 0); + OPTENT3(0, "ymax", OPT_UINT, &cmdlineP->ymax, &ymaxSpec, 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 */ + + pm_optParseOptions3(&argc, (char**)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (!xmaxSpec) + cmdlineP->xmax = UINT_MAX; + if (!ymaxSpec) + cmdlineP->ymax = UINT_MAX; + + cmdlineP->inputFileName = (argc-1 >= 1) ? argv[1] : "-"; + cmdlineP->outputFileName = (argc-1 >= 2) ? argv[2] : "-"; + + if (argc-1 > 2) + pm_error("Too many arguments: %u. The only possible " + "non-option arguments are input file name and " + "output file name", argc-1); +} + + + static void collect_image (unsigned char *data, size_t len, void *image) { static int cursor = 0; @@ -29,7 +100,7 @@ collect_image (unsigned char *data, size_t len, void *image) { -static void +static void write_pnm (FILE *fout, const unsigned char * const image, const int bpp, const int rows, const int cols, const int maxval, const int format) { @@ -46,22 +117,22 @@ write_pnm (FILE *fout, const unsigned char * const image, const int bpp, for (col = 0; col < cols; col++) { int j; for (j = 0; j < bpp; j++) - PNM_ASSIGN1(pnm_row[col], + PNM_ASSIGN1(pnm_row[col], image[(((row*cols)+col) * bpp) + j]); } pnm_writepnmrow(fout, pnm_row, cols, maxval, format, 0); } - + pnm_freerow(pnm_row); } static void -write_raw_pbm(FILE * const fout, +write_raw_pbm(FILE * const fout, const unsigned char * const binary_image, int const cols, - int const rows) { + int const rows) { unsigned int const bytes_per_row = pbm_packed_bytes(cols); @@ -70,7 +141,7 @@ write_raw_pbm(FILE * const fout, pbm_writepbminit(fout, cols, rows, 0); for (row = 0; row < rows; ++row) - pbm_writepbmrow_packed(fout, &binary_image[row*bytes_per_row], cols, + pbm_writepbmrow_packed(fout, &binary_image[row*bytes_per_row], cols, 0); } @@ -79,7 +150,7 @@ write_raw_pbm(FILE * const fout, /* * */ -static void +static void diagnose_bie(FILE *f) { unsigned char bih[20]; @@ -89,198 +160,153 @@ diagnose_bie(FILE *f) len = fread(bih, 1, 20, f); if (len < 20) { printf("Input file is %d < 20 bytes long and does therefore not " - "contain an intact BIE header!\n", len); + "contain an intact BIE header!\n", len); return; } printf("Decomposition of BIH:\n\n DL = %d\n D = %d\n P = %d\n" - " - = %d\n XD = %lu\n YD = %lu\n L0 = %lu\n MX = %d\n" - " MY = %d\n", - bih[0], bih[1], bih[2], bih[3], - xd = ((unsigned long) bih[ 4] << 24) | ((unsigned long)bih[ 5] << 16)| - ((unsigned long) bih[ 6] << 8) | ((unsigned long) bih[ 7]), - yd = ((unsigned long) bih[ 8] << 24) | ((unsigned long)bih[ 9] << 16)| - ((unsigned long) bih[10] << 8) | ((unsigned long) bih[11]), - l0 = ((unsigned long) bih[12] << 24) | ((unsigned long)bih[13] << 16)| - ((unsigned long) bih[14] << 8) | ((unsigned long) bih[15]), - bih[16], bih[17]); + " - = %d\n XD = %lu\n YD = %lu\n L0 = %lu\n MX = %d\n" + " MY = %d\n", + bih[0], bih[1], bih[2], bih[3], + xd = ((unsigned long) bih[ 4] << 24) | ((unsigned long)bih[ 5] << 16)| + ((unsigned long) bih[ 6] << 8) | ((unsigned long) bih[ 7]), + yd = ((unsigned long) bih[ 8] << 24) | ((unsigned long)bih[ 9] << 16)| + ((unsigned long) bih[10] << 8) | ((unsigned long) bih[11]), + l0 = ((unsigned long) bih[12] << 24) | ((unsigned long)bih[13] << 16)| + ((unsigned long) bih[14] << 8) | ((unsigned long) bih[15]), + bih[16], bih[17]); printf(" order = %d %s%s%s%s%s\n", bih[18], - bih[18] & JBG_HITOLO ? " HITOLO" : "", - bih[18] & JBG_SEQ ? " SEQ" : "", - bih[18] & JBG_ILEAVE ? " ILEAVE" : "", - bih[18] & JBG_SMID ? " SMID" : "", - bih[18] & 0xf0 ? " other" : ""); + bih[18] & JBG_HITOLO ? " HITOLO" : "", + bih[18] & JBG_SEQ ? " SEQ" : "", + bih[18] & JBG_ILEAVE ? " ILEAVE" : "", + bih[18] & JBG_SMID ? " SMID" : "", + bih[18] & 0xf0 ? " other" : ""); printf(" options = %d %s%s%s%s%s%s%s%s\n", bih[19], - bih[19] & JBG_LRLTWO ? " LRLTWO" : "", - bih[19] & JBG_VLENGTH ? " VLENGTH" : "", - bih[19] & JBG_TPDON ? " TPDON" : "", - bih[19] & JBG_TPBON ? " TPBON" : "", - bih[19] & JBG_DPON ? " DPON" : "", - bih[19] & JBG_DPPRIV ? " DPPRIV" : "", - bih[19] & JBG_DPLAST ? " DPLAST" : "", - bih[19] & 0x80 ? " other" : ""); + bih[19] & JBG_LRLTWO ? " LRLTWO" : "", + bih[19] & JBG_VLENGTH ? " VLENGTH" : "", + bih[19] & JBG_TPDON ? " TPDON" : "", + bih[19] & JBG_TPBON ? " TPBON" : "", + bih[19] & JBG_DPON ? " DPON" : "", + bih[19] & JBG_DPPRIV ? " DPPRIV" : "", + bih[19] & JBG_DPLAST ? " DPLAST" : "", + bih[19] & 0x80 ? " other" : ""); printf("\n %lu stripes, %d layers, %d planes\n\n", - ((yd >> bih[1]) + ((((1UL << bih[1]) - 1) & xd) != 0) + l0 - 1) / l0, - bih[1] - bih[0], bih[2]); + ((yd >> bih[1]) + ((((1UL << bih[1]) - 1) & xd) != 0) + l0 - 1) / l0, + bih[1] - bih[0], bih[2]); return; } -int main (int argc, char **argv) +int main (int argc, const char **argv) { - FILE *fin = stdin, *fout = stdout; - const char *fnin = "<stdin>", *fnout = "<stdout>"; - int i, j, result; - int all_args = 0, files = 0; - struct jbg_dec_state s; - char *buffer; - unsigned char *p; - size_t len, cnt; - unsigned long xmax = 4294967295UL, ymax = 4294967295UL; - int plane = -1, use_graycode = 1, diagnose = 0; - - pnm_init(&argc, argv); - - buffer = malloc(BUFSIZE); - if (!buffer) - pm_error("Sorry, not enough memory available!"); - - /* parse command line arguments */ - for (i = 1; i < argc; i++) { - if (!all_args && argv[i][0] == '-') { - if (argv[i][1] == '\0' && files == 0) - ++files; - else { - for (j = 1; j > 0 && argv[i][j]; j++) { - switch(tolower(argv[i][j])) { - case '-' : - all_args = 1; - break; - case 'b': - use_graycode = 0; - break; - case 'd': - diagnose = 1; - break; - case 'x': - if (++i >= argc) - pm_error("-x needs a value"); - xmax = atol(argv[i]); - j = -1; - break; - case 'y': - if (++i >= argc) - pm_error("-y needs a value"); - ymax = atol(argv[i]); - j = -1; - break; - case 'p': - if (++i >= argc) - pm_error("-p needs a value"); - plane = atoi(argv[i]); - j = -1; - break; - default: - pm_error("Unrecognized option: %c", argv[i][j]); - } - } - } - } else { - switch (files++) { - case 0: - if (argv[i][0] != '-' || argv[i][1] != '\0') { - fnin = argv[i]; - fin = fopen(fnin, "rb"); - if (!fin) - pm_error("Can't open input file '%s'", fnin); - } - if (diagnose) { - diagnose_bie(fin); - exit(0); - } - break; - case 1: - fnout = argv[i]; - fout = fopen(fnout, "wb"); - if (!fout) - pm_error("Can't open output file '%s'", fnout); + CmdlineInfo cmdline; + FILE * ifP; + FILE * ofP; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFileName); + ofP = pm_openw(cmdline.outputFileName); + + if (cmdline.diagnose) + diagnose_bie(ifP); + else { + struct jbg_dec_state s; + unsigned char * buffer; + int result; + + MALLOCARRAY(buffer, BUFSIZE); + if (!buffer) + pm_error("Failed to get %u bytes of memory for buffer", BUFSIZE); + + /* send input file to decoder */ + jbg_dec_init(&s); + jbg_dec_maxsize(&s, cmdline.xmax, cmdline.ymax); + result = JBG_EAGAIN; + do { + size_t len; + size_t cnt; + unsigned char * p; + + len = fread(buffer, 1, BUFSIZE, ifP); + if (len == 0) break; - default: - pm_error("Too many non-option arguments"); + cnt = 0; + p = &buffer[0]; + while (len > 0 && (result == JBG_EAGAIN || result == JBG_EOK)) { + result = jbg_dec_in(&s, p, len, &cnt); + p += cnt; + len -= cnt; + } + } while (result == JBG_EAGAIN || result == JBG_EOK); + if (ferror(ifP)) + pm_error("Error reading input file"); + if (result != JBG_EOK && result != JBG_EOK_INTR) + pm_error("Invalid contents of input file. %s", + jbg_strerror(result)); + if (cmdline.planeSpec && jbg_dec_getplanes(&s) <= cmdline.plane) + pm_error("Image has only %u planes", jbg_dec_getplanes(&s)); + + { + /* Write it out */ + + int rows, cols; + int maxval; + int bpp; + bool justOnePlane; + unsigned int plane_to_write; + + cols = jbg_dec_getwidth(&s); + rows = jbg_dec_getheight(&s); + maxval = pm_bitstomaxval(jbg_dec_getplanes(&s)); + bpp = (jbg_dec_getplanes(&s)+7)/8; + + if (jbg_dec_getplanes(&s) == 1) { + justOnePlane = true; + plane_to_write = 0; + } else { + if (cmdline.planeSpec) { + justOnePlane = true; + plane_to_write = cmdline.plane; + } else + justOnePlane = false; } - } - } - /* send input file to decoder */ - jbg_dec_init(&s); - jbg_dec_maxsize(&s, xmax, ymax); - result = JBG_EAGAIN; - do { - len = fread(buffer, 1, BUFSIZE, fin); - if (!len) break; - cnt = 0; - p = (unsigned char *) buffer; - while (len > 0 && (result == JBG_EAGAIN || result == JBG_EOK)) { - result = jbg_dec_in(&s, p, len, &cnt); - p += cnt; - len -= cnt; - } - } while (result == JBG_EAGAIN || result == JBG_EOK); - if (ferror(fin)) - pm_error("Problem while reading input file '%s", fnin); - if (result != JBG_EOK && result != JBG_EOK_INTR) - pm_error("Problem with input file '%s': %s\n", - fnin, jbg_strerror(result)); - if (plane >= 0 && jbg_dec_getplanes(&s) <= plane) - pm_error("Image has only %d planes!\n", jbg_dec_getplanes(&s)); - - { - /* Write it out */ - - int rows, cols; - int maxval; - int bpp; - int plane_to_write; - - cols = jbg_dec_getwidth(&s); - rows = jbg_dec_getheight(&s); - maxval = pm_bitstomaxval(jbg_dec_getplanes(&s)); - bpp = (jbg_dec_getplanes(&s)+7)/8; - - if (jbg_dec_getplanes(&s) == 1) - plane_to_write = 0; - else - plane_to_write = plane; - - if (plane_to_write >= 0) { - /* Write just one plane */ - unsigned char * binary_image; - - pm_message("WRITING PBM FILE"); - - binary_image=jbg_dec_getimage(&s, plane_to_write); - write_raw_pbm(fout, binary_image, cols, rows); - } else { - unsigned char *image; - pm_message("WRITING PGM FILE"); - - /* Write out all the planes */ - /* What jbig.doc doesn't tell you is that jbg_dec_merge_planes - delivers the image in chunks, in consecutive calls to - the data-out callback function. And a row can span two - chunks. - */ - image = malloc(cols*rows*bpp); - jbg_dec_merge_planes(&s, use_graycode, collect_image, image); - write_pnm(fout, image, bpp, rows, cols, maxval, PGM_TYPE); - free(image); + if (justOnePlane) { + unsigned char * binary_image; + + pm_message("WRITING PBM FILE"); + + binary_image=jbg_dec_getimage(&s, plane_to_write); + write_raw_pbm(ofP, binary_image, cols, rows); + } else { + unsigned char *image; + pm_message("WRITING PGM FILE"); + + /* Write out all the planes */ + /* What jbig.doc doesn't tell you is that jbg_dec_merge_planes + delivers the image in chunks, in consecutive calls to + the data-out callback function. And a row can span two + chunks. + */ + image = malloc(cols*rows*bpp); + jbg_dec_merge_planes(&s, !cmdline.binary, collect_image, + image); + write_pnm(ofP, image, bpp, rows, cols, maxval, PGM_TYPE); + free(image); + } + jbg_dec_free(&s); } - } - - pm_close(fout); - - jbg_dec_free(&s); + pm_close(ofP); + pm_close(ifP); + free(buffer); + } return 0; } + + + diff --git a/converter/other/jbig/libjbig/jbig.c b/converter/other/jbig/libjbig/jbig.c index d7141a75..e8141070 100644 --- a/converter/other/jbig/libjbig/jbig.c +++ b/converter/other/jbig/libjbig/jbig.c @@ -22,15 +22,13 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * + * * If you want to use this program under different license conditions, * then contact the author for an arrangement. */ #ifdef DEBUG #include <stdio.h> -#else -#define NDEBUG #endif #include <stdlib.h> @@ -68,7 +66,7 @@ /* object code version id */ -const char jbg_version[] = +const char jbg_version[] = "JBIG-KIT " JBG_VERSION " -- (c) 1995-2014 Markus Kuhn -- " "Licence: " JBG_LICENCE "\n"; @@ -117,7 +115,7 @@ static const char *errmsg[] = { * then simply add the necessary semaphores or mutex primitives below. * In contrast to C's malloc() and realloc(), but like C's calloc(), * these functions take two parameters nmemb and size that are multiplied - * before being passed on to the corresponding C function. + * before being passed on to the corresponding C function. * This we can catch all overflows during a size_t multiplication a * a single place. */ @@ -137,7 +135,7 @@ static void *checked_malloc(size_t nmemb, size_t size) /* assert that nmemb * size <= SIZE_MAX */ if (size > SIZE_MAX / nmemb) abort(); - + p = malloc(nmemb * size); if (!p) @@ -163,7 +161,7 @@ static void *checked_realloc(void *ptr, size_t nmemb, size_t size) /* assert that nmemb * size <= SIZE_MAX */ if (size > SIZE_MAX / nmemb) abort(); - + p = realloc(ptr, nmemb * size); if (!p) @@ -212,7 +210,7 @@ static void checked_free(void *ptr) static struct jbg_buf *jbg_buf_init(struct jbg_buf **free_list) { struct jbg_buf *new_block; - + /* Test whether a block from the free list is available */ if (*free_list) { new_block = *free_list; @@ -238,13 +236,13 @@ static struct jbg_buf *jbg_buf_init(struct jbg_buf **free_list) static void jbg_buf_free(struct jbg_buf **free_list) { struct jbg_buf *tmp; - + while (*free_list) { tmp = (*free_list)->next; checked_free(*free_list); *free_list = tmp; } - + return; } @@ -308,7 +306,7 @@ static void jbg_buf_remove_zeros(struct jbg_buf *head) */ if (head->last->len && head->last->d[head->last->len - 1] == MARKER_ESC) jbg_buf_write(MARKER_STUFF, head); - + return; } @@ -324,7 +322,7 @@ static void jbg_buf_prefix(struct jbg_buf *new_prefix, struct jbg_buf **start) new_prefix->last->next->previous = new_prefix->last; new_prefix->last = new_prefix->last->next->last; *start = new_prefix; - + return; } @@ -341,7 +339,7 @@ static void jbg_buf_output(struct jbg_buf **head, void *file) { struct jbg_buf *tmp; - + while (*head) { data_out((*head)->d, (*head)->len, file); tmp = (*head)->next; @@ -349,7 +347,7 @@ static void jbg_buf_output(struct jbg_buf **head, *(*head)->free_list = *head; *head = tmp; } - + return; } @@ -364,7 +362,7 @@ static void jbg_buf_output(struct jbg_buf **head, unsigned long jbg_ceil_half(unsigned long x, int n) { unsigned long mask; - + assert(n >= 0 && n < 32); mask = (1UL << n) - 1; /* the lowest n bits are 1 here */ return (x >> n) + ((mask & x) != 0); @@ -796,7 +794,7 @@ void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, s->comment = NULL; s->dppriv = jbg_dptable; s->res_tab = jbg_resred; - + s->highres = (int *) checked_malloc(planes, sizeof(int)); s->lhp[0] = p; s->lhp[1] = (unsigned char **) @@ -806,9 +804,9 @@ void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, s->lhp[1][i] = (unsigned char *) checked_malloc(jbg_ceil_half(y, 1), jbg_ceil_half(x, 1+3)); } - + s->free_list = NULL; - s->s = (struct jbg_arenc_state *) + s->s = (struct jbg_arenc_state *) checked_malloc(s->planes, sizeof(struct jbg_arenc_state)); s->tx = (int *) checked_malloc(s->planes, sizeof(int)); lx = jbg_ceil_half(x, 1); @@ -830,9 +828,9 @@ void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y, * l0 (height of one stripe in the lowest resolution layer) is * selected, which obeys the recommended limitations for l0 in annex A * and C of the JBIG standard. The selected number of resolution layers - * is returned. + * is returned. */ -int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long x, +int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long x, unsigned long y) { for (s->d = 0; s->d < 6; s->d++) @@ -846,8 +844,8 @@ int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long x, /* - * As an alternative to jbg_enc_lrlmax(), the following function allows - * to specify the number of layers directly. The stripe height and layer + * As an alternative to jbg_enc_lrlmax(), the following function allows the + * user to specify the number of layers directly. The stripe height and layer * range is also adjusted automatically here. */ void jbg_enc_layers(struct jbg_enc_state *s, int d) @@ -879,9 +877,9 @@ int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh) /* - * The following function allows to specify the bits describing the - * options of the format as well as the maximum AT movement window and - * the number of layer 0 lines per stripes. + * The following function allows the user to specify the bits describing the + * options of the format as well as the maximum AT movement window and the + * number of layer 0 lines per stripes. */ void jbg_enc_options(struct jbg_enc_state *s, int order, int options, unsigned long l0, int mx, int my) @@ -957,7 +955,7 @@ static void encode_sde(struct jbg_enc_state *s, hp = s->lhp[s->highres[plane]][plane] + stripe * hl * hbpl; lp2 = s->lhp[1 - s->highres[plane]][plane] + stripe * ll * lbpl; lp1 = lp2 + lbpl; - + /* check whether we can refer to any state of a previous stripe */ reset = (stripe == 0) || (s->options & JBG_SDRST); @@ -1035,7 +1033,7 @@ static void encode_sde(struct jbg_enc_state *s, at_determined = 1; } assert(s->tx[plane] >= 0); /* i.e., tx can safely be cast to unsigned */ - + /* typical prediction */ if (s->options & JBG_TPBON) { ltp = 1; @@ -1066,11 +1064,11 @@ static void encode_sde(struct jbg_enc_state *s, * 76543210765432107654321076543210 line_h2 * 76543210765432107654321X76543210 line_h1 */ - + line_h1 = line_h2 = line_h3 = 0; if (i > 0 || !reset) line_h2 = (long)*(hp - hbpl) << 8; if (i > 1 || !reset) line_h3 = (long)*(hp - hbpl - hbpl) << 8; - + /* encode line */ for (j = 0; j < hx; hp++) { line_h1 |= *hp; @@ -1177,7 +1175,7 @@ static void encode_sde(struct jbg_enc_state *s, /* * Encode differential layer */ - + for (i = 0; i < hl && y < hy; i++, y++) { /* check whether it is worth to perform an ATMOVE */ @@ -1213,7 +1211,7 @@ static void encode_sde(struct jbg_enc_state *s, } at_determined = 1; } - + if ((i >> 1) >= ll - 1 || (y >> 1) >= ly - 1) lp1 = lp2; @@ -1299,7 +1297,7 @@ static void encode_sde(struct jbg_enc_state *s, * 76543210 7654321Y 76543210 76543210 line_l2 * 76543210 76543210 76543210 76543210 line_l1 */ - + line_h1 = line_h2 = line_h3 = line_l1 = line_l2 = line_l3 = 0; if (i > 0 || !reset) line_h2 = (long)*(hp - hbpl) << 8; @@ -1309,7 +1307,7 @@ static void encode_sde(struct jbg_enc_state *s, } line_l2 = (long)*lp2 << 8; line_l1 = (long)*lp1 << 8; - + /* encode line */ for (j = 0; j < hx; lp1++, lp2++) { if ((j >> 1) < lbpl * 8 - 8) { @@ -1403,8 +1401,8 @@ static void encode_sde(struct jbg_enc_state *s, #endif continue; } - } - } + } + } } /* determine context */ @@ -1437,7 +1435,7 @@ static void encode_sde(struct jbg_enc_state *s, #ifdef DEBUG encoded_pixels++; #endif - + /* statistics for adaptive template changes */ if (!at_determined && j >= s->mx) { c[0] += !(((line_h2 >> 6) ^ line_h1) & 0x100); @@ -1445,7 +1443,7 @@ static void encode_sde(struct jbg_enc_state *s, c[t] += !(((line_h1 >> t) ^ line_h1) & 0x100); ++c_all; } - + } while (++j & 1 && j < hx); } while (j & 7 && j < hx); hp++; @@ -1457,10 +1455,10 @@ static void encode_sde(struct jbg_enc_state *s, lp1 -= lbpl; lp2 -= lbpl; } - + } /* for (i = ...) */ } - + arith_encode_flush(se); jbg_buf_remove_zeros(s->sde[stripe][layer][plane]); jbg_buf_write(MARKER_ESC, s->sde[stripe][layer][plane]); @@ -1541,7 +1539,7 @@ static void resolution_reduction(struct jbg_enc_state *s, int plane, hp1 = hp2 + hbpl; hp3 = hp2 - hbpl; lp = s->lhp[1 - s->highres[plane]][plane]; - + #ifdef DEBUG fprintf(stderr, "resolution_reduction: plane = %d, higher_layer = %d\n", plane, higher_layer); @@ -1608,7 +1606,7 @@ static void resolution_reduction(struct jbg_enc_state *s, int plane, { FILE *f; char fn[50]; - + sprintf(fn, "dbg_d=%02d.pbm", higher_layer - 1); f = fopen(fn, "wb"); fprintf(f, "P4\n%lu %lu\n", lx, ly); @@ -1621,7 +1619,7 @@ static void resolution_reduction(struct jbg_enc_state *s, int plane, } -/* +/* * This function is called inside the three loops of jbg_enc_out() in * order to write the next SDE. It has first to generate the required * SDE and all SDEs which have to be encoded before this SDE can be @@ -1642,7 +1640,7 @@ static void output_sde(struct jbg_enc_state *s, int lfcl; /* lowest fully coded layer */ long i; unsigned long u; - + assert(s->sde[stripe][layer][plane] != SDE_DONE); if (s->sde[stripe][layer][plane] != SDE_TODO) { @@ -1679,7 +1677,7 @@ static void output_sde(struct jbg_enc_state *s, if (lfcl > 1) resolution_reduction(s, plane, lfcl - 1); } - + encode_sde(s, stripe, layer, plane); #ifdef DEBUG @@ -1687,14 +1685,14 @@ static void output_sde(struct jbg_enc_state *s, #endif jbg_buf_output(&s->sde[stripe][layer][plane], s->data_out, s->file); s->sde[stripe][layer][plane] = SDE_DONE; - + if (stripe == s->stripes - 1 && layer > 0 && s->sde[0][layer-1][plane] == SDE_TODO) { s->highres[plane] ^= 1; if (layer > 1) resolution_reduction(s, plane, layer - 1); } - + return; } @@ -1729,7 +1727,7 @@ void jbg_int2dppriv(unsigned char *dptable, const char *internal) int trans1[ 9] = { 1, 0, 3, 2, 8, 7, 6, 5, 4 }; int trans2[11] = { 1, 0, 3, 2, 10, 9, 8, 7, 6, 5, 4 }; int trans3[12] = { 1, 0, 3, 2, 11, 10, 9, 8, 7, 6, 5, 4 }; - + for (i = 0; i < 1728; dptable[i++] = 0) ; #define FILL_TABLE1(offset, len, trans) \ @@ -1762,7 +1760,7 @@ void jbg_dppriv2int(char *internal, const unsigned char *dptable) int trans1[ 9] = { 1, 0, 3, 2, 8, 7, 6, 5, 4 }; int trans2[11] = { 1, 0, 3, 2, 10, 9, 8, 7, 6, 5, 4 }; int trans3[12] = { 1, 0, 3, 2, 11, 10, 9, 8, 7, 6, 5, 4 }; - + #define FILL_TABLE2(offset, len, trans) \ for (i = 0; i < len; i++) { \ k = 0; \ @@ -1790,7 +1788,7 @@ void jbg_enc_out(struct jbg_enc_state *s) unsigned long bpl; unsigned char buf[20]; unsigned long xd, yd, y; - long ii[3], is[3], ie[3]; /* generic variables for the 3 nested loops */ + long ii[3], is[3], ie[3]; /* generic variables for the 3 nested loops */ unsigned long stripe; int layer, plane; int order; @@ -1918,7 +1916,7 @@ void jbg_enc_out(struct jbg_enc_state *s) for (ii[0] = is[0]; ii[0] <= ie[0]; ii[0]++) for (ii[1] = is[1]; ii[1] <= ie[1]; ii[1]++) for (ii[2] = is[2]; ii[2] <= ie[2]; ii[2]++) { - + stripe = ii[iindex[order][STRIPE]]; if (s->order & JBG_HITOLO) layer = s->dh - (ii[iindex[order][LAYER]] - s->dl); @@ -1949,7 +1947,7 @@ void jbg_enc_out(struct jbg_enc_state *s) */ if (s->yd1 > s->yd && (stripe == s->stripes - 1 || - (stripe == s->stripes - 2 && + (stripe == s->stripes - 2 && (s->dl != s->dh || s->planes > 1)))) { s->yd1 = s->yd; yd = jbg_ceil_half(s->yd, s->d - s->dh); @@ -2017,10 +2015,10 @@ void jbg_enc_free(struct jbg_enc_state *s) checked_free(s->lhp[1][plane]); checked_free(s->lhp[1]); } - + /* clear buffer for index of highres image in lhp */ checked_free(s->highres); - + return; } @@ -2039,7 +2037,7 @@ const char *jbg_strerror(int errnum) /* - * The constructor for a decoder + * The constructor for a decoder */ void jbg_dec_init(struct jbg_dec_state *s) { @@ -2077,7 +2075,7 @@ void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax, /* * Decode the new len PSDC bytes to which data points and add them to * the current stripe. Return the number of bytes which have actually - * been read (this will be less than len if a marker segment was + * been read (this will be less than len if a marker segment was * part of the data or if the final byte was 0xff, in which case * this code cannot determine whether we have a marker segment). */ @@ -2106,7 +2104,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, se = s->s[plane] + layer - s->dl; se->pscd_ptr = data; se->pscd_end = data + len; - + /* number of lines per stripe in highres image */ hl = s->l0 << layer; /* number of lines per stripe in lowres image */ @@ -2194,7 +2192,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, /* this line is 'not typical' and has to be coded completely */ } s->pseudo = 0; - + /* * Layout of the variables line_h1, line_h2, line_h3, which contain * as bits the neighbour pixels of the currently decoded pixel X: @@ -2203,7 +2201,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, * 76543210 76543210 76543210 76543210 line_h2 * 76543210 76543210 76543210 76543210 X line_h1 */ - + if (x == 0) { line_h1 = line_h2 = line_h3 = 0; if (s->i > 0 || (y > 0 && !s->reset[plane][layer - s->dl])) @@ -2211,7 +2209,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) line_h3 = (long)*(hp - hbpl - hbpl) << 8; } - + /* * Another tiny JBIG standard bug: * @@ -2315,7 +2313,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, (line_h1 & 0x003))); if (pix < 0) goto leave; - + line_h1 = (line_h1 << 1) | pix; line_h2 <<= 1; line_h3 <<= 1; @@ -2327,7 +2325,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, x = 0; s->pseudo = 1; } /* for (i = ...) */ - + } else { /* @@ -2378,7 +2376,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, * 76543210 76543210 Y6543210 76543210 line_l2 * 76543210 76543210 76543210 76543210 line_l1 */ - + if (x == 0) { line_h1 = line_h2 = line_h3 = line_l1 = line_l2 = line_l3 = 0; @@ -2392,14 +2390,14 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, line_l2 = (long)*lp2 << 8; line_l1 = (long)*lp1 << 8; } - + /* decode line */ while (x < hx) { if ((x & 15) == 0) if ((x >> 1) < lbpl * 8 - 8) { line_l1 |= *(lp1 + 1); line_l2 |= *(lp2 + 1); - if (s->i > 1 || + if (s->i > 1 || (y > 1 && !s->reset[plane][layer - s->dl])) line_l3 |= *(lp2 - lbpl + 1); } @@ -2430,13 +2428,13 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, line_h1 = (line_h1 << 1) | (cx & 1); } while ((++x & 1) && x < hx); line_h2 <<= 2; line_h3 <<= 2; - } else + } else do { - + /* deterministic prediction */ if (s->options & JBG_DPON) if ((y & 1) == 0) - if ((x & 1) == 0) + if ((x & 1) == 0) /* phase 0 */ pix = s->dppriv[((line_l3 >> 15) & 0x003) | ((line_l2 >> 13) & 0x00c) | @@ -2492,7 +2490,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, line_h1 = (line_h1 << 1) | pix; line_h2 <<= 1; line_h3 <<= 1; - + } while ((++x & 1) && x < hx); line_l1 <<= 1; line_l2 <<= 1; line_l3 <<= 1; } while ((x & 7) && x < hx); @@ -2502,7 +2500,7 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, ++lp2; } /* while */ x = 0; - + *(hp - 1) <<= hbpl * 8 - hx; if ((s->i & 1) == 0) { /* low resolution pixels are used twice */ @@ -2510,9 +2508,9 @@ static size_t decode_pscd(struct jbg_dec_state *s, unsigned char *data, lp2 -= lbpl; } else s->pseudo = 1; - + } /* for (i = ...) */ - + } leave: @@ -2581,7 +2579,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, if (s->bie_len < 20) { while (s->bie_len < 20 && *cnt < len) s->buffer[s->bie_len++] = data[(*cnt)++]; - if (s->bie_len < 20) + if (s->bie_len < 20) return JBG_EAGAIN; /* test whether this looks like a valid JBIG header at all */ if (s->buffer[1] < s->buffer[0]) @@ -2642,7 +2640,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, /* calculate number of stripes that will be required */ s->stripes = jbg_stripes(s->l0, s->yd, s->d); - + /* some initialization */ s->ii[iindex[s->order & 7][STRIPE]] = 0; s->ii[iindex[s->order & 7][LAYER]] = s->dl; @@ -2705,7 +2703,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, } /* read in DPTABLE */ - if (s->bie_len < 20 + 1728 && + if (s->bie_len < 20 + 1728 && (s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) == (JBG_DPON | JBG_DPPRIV)) { assert(s->bie_len >= 20); @@ -2713,7 +2711,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, s->dppriv = (char *) checked_malloc(1728, sizeof(char)); while (s->bie_len < 20 + 1728 && *cnt < len) s->dppriv[s->bie_len++ - 20] = data[(*cnt)++]; - if (s->bie_len < 20 + 1728) + if (s->bie_len < 20 + 1728) return JBG_EAGAIN; dppriv = (unsigned char *) s->dppriv; s->dppriv = (char *) checked_malloc(6912, sizeof(char)); @@ -2724,7 +2722,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, /* * BID processing loop */ - + while (*cnt < len) { /* process floating marker segments */ @@ -2801,27 +2799,27 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, break; case MARKER_ABORT: return JBG_EABORT; - + case MARKER_SDNORM: case MARKER_SDRST: /* decode final pixels based on trailing zero bytes */ decode_pscd(s, s->buffer, 2); - arith_decode_init(s->s[s->ii[iindex[s->order & 7][PLANE]]] + + arith_decode_init(s->s[s->ii[iindex[s->order & 7][PLANE]]] + s->ii[iindex[s->order & 7][LAYER]] - s->dl, s->ii[iindex[s->order & 7][STRIPE]] != s->stripes - 1 && s->buffer[1] != MARKER_SDRST); - + s->reset[s->ii[iindex[s->order & 7][PLANE]]] [s->ii[iindex[s->order & 7][LAYER]] - s->dl] = (s->buffer[1] == MARKER_SDRST); - + /* prepare for next SDE */ s->x = 0; s->i = 0; s->pseudo = 1; s->at_moves = 0; - + /* increment layer/stripe/plane loop variables */ /* start and end value for each loop: */ is[iindex[s->order & 7][STRIPE]] = 0; @@ -2842,7 +2840,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, } while (--i >= 0 && j); s->buf_len = 0; - + /* check whether this have been all SDEs */ if (j) { #ifdef DEBUG @@ -2887,7 +2885,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, #endif return JBG_EINVAL | 14; } - + } } /* of BID processing loop 'while (*cnt < len) ...' */ @@ -2930,7 +2928,7 @@ unsigned long jbg_dec_getheight(const struct jbg_dec_state *s) else return jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)); } - + return s->yd; } @@ -2950,7 +2948,7 @@ unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane) else return s->lhp[(s->ii[0] - 1) & 1][plane]; } - + return s->lhp[s->d & 1][plane]; } @@ -2968,11 +2966,11 @@ unsigned long jbg_dec_getsize(const struct jbg_dec_state *s) if (s->ii[0] < 1) return 0; else - return + return jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1) + 3) * /* overflow risk? */ jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)); } - + return jbg_ceil_half(s->xd, 3) * s->yd; } @@ -2990,17 +2988,17 @@ unsigned long jbg_dec_getsize_merged(const struct jbg_dec_state *s) if (s->ii[0] < 1) return 0; else - return + return jbg_ceil_half(s->xd, s->d - (s->ii[0] - 1)) * /* overflow risk? */ jbg_ceil_half(s->yd, s->d - (s->ii[0] - 1)) * ((s->planes + 7) / 8); } - + return s->xd * s->yd * ((s->planes + 7) / 8); } -/* +/* * The destructor function which releases any resources obtained by the * other decoder functions. */ @@ -3021,7 +3019,7 @@ void jbg_dec_free(struct jbg_dec_state *s) checked_free(s->lhp[0][i]); checked_free(s->lhp[1][i]); } - + checked_free(s->s); checked_free(s->tx); checked_free(s->ty); @@ -3063,10 +3061,10 @@ void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, if (encode_planes > has_planes) encode_planes = has_planes; use_graycode = use_graycode != 0 && encode_planes > 1; - + for (p = 0; p < encode_planes; p++) memset(dest[p], 0, bpl * y); - + for (line = 0; line < y; line++) { /* lines loop */ for (i = 0; i * 8 < x; i++) { /* dest bytes loop */ for (k = 0; k < 8 && i * 8 + k < x; k++) { /* pixel loop */ @@ -3098,11 +3096,11 @@ void jbg_split_planes(unsigned long x, unsigned long y, int has_planes, for (p = 0; p < encode_planes; p++) /* right padding loop */ dest[p][bpl * (line + 1) - 1] <<= 8 - k; } - + return; } -/* +/* * Merge the separate bit planes decoded by the JBIG decoder into an * integer pixel field. This is essentially the counterpart to * jbg_split_planes(). @@ -3123,7 +3121,7 @@ void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, /* sanity check */ use_graycode = use_graycode != 0; - + x = jbg_dec_getwidth(s); y = jbg_dec_getheight(s); if (x == 0 || y == 0) @@ -3137,7 +3135,7 @@ void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, src = s->lhp[(s->ii[0] - 1) & 1]; else src = s->lhp[s->d & 1]; - + for (line = 0; line < y; line++) { /* lines loop */ for (i = 0; i * 8 < x; i++) { /* src bytes loop */ for (k = 0; k < 8 && i * 8 + k < x; k++) { /* pixel loop */ @@ -3157,10 +3155,10 @@ void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, } } } - + if (bp - buf > 0) data_out(buf, bp - buf, file); - + return; } @@ -3175,7 +3173,7 @@ void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode, * - not enough bytes left for complete marker segment * - no marker segment terminates the PSCD * - unknown marker code encountered - * + * */ static unsigned char *jbg_next_pscdms(unsigned char *p, size_t len) { diff --git a/converter/other/jpeg2000/jpeg2ktopam.c b/converter/other/jpeg2000/jpeg2ktopam.c index 405de9c9..b507f56e 100644 --- a/converter/other/jpeg2000/jpeg2ktopam.c +++ b/converter/other/jpeg2000/jpeg2ktopam.c @@ -8,6 +8,7 @@ *****************************************************************************/ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ /* In 2014.09, this was _XOPEN_SOURCE 600, with a comment saying it was @@ -61,7 +62,7 @@ parseCommandLine(int argc, char ** argv, MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ - OPTENT3(0, "verbose", OPT_FLAG, NULL, + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); OPTENT3(0, "debuglevel", OPT_UINT, &cmdlineP->debuglevel, &debuglevelSpec, 0); @@ -79,7 +80,7 @@ parseCommandLine(int argc, char ** argv, cmdlineP->inputFilename = strdup("-"); /* he wants stdin */ else if (argc - 1 == 1) cmdlineP->inputFilename = strdup(argv[1]); - else + else pm_error("Too many arguments. The only argument accepted\n" "is the input file specification"); @@ -106,11 +107,11 @@ validateJ2k(jas_stream_t * const instreamP) { } } - + static void -readJ2k(const char * const inputFilename, +readJ2k(const char * const inputFilename, jas_image_t ** const jasperPP) { jas_image_t * jasperP; @@ -126,7 +127,7 @@ readJ2k(const char * const inputFilename, instreamP = jas_stream_fopen(inputFilename, "rb"); if (instreamP == NULL ) pm_error("cannot open input image file '%s'", inputFilename); - } + } validateJ2k(instreamP); @@ -138,7 +139,7 @@ readJ2k(const char * const inputFilename, pm_error("Unable to interpret JPEG-2000 input. " "The Jasper library jas_image_decode() subroutine failed."); - jas_stream_close(instreamP); + jas_stream_close(instreamP); *jasperPP = jasperP; } @@ -149,7 +150,7 @@ static void getRgbComponents(int jasperCmpnt[], jas_image_t * const jasperP) { { - int const rc = + int const rc = jas_image_getcmptbytype(jasperP, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R)); if (rc < 0) @@ -158,12 +159,12 @@ getRgbComponents(int jasperCmpnt[], jas_image_t * const jasperP) { else jasperCmpnt[PAM_RED_PLANE] = rc; - if (jas_image_cmptsgnd(jasperP, rc)) + if (jas_image_cmptsgnd(jasperP, rc)) pm_error("Input image says it is RGB, but has signed values " "for what should be the red intensities."); } { - int const rc = + int const rc = jas_image_getcmptbytype(jasperP, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G)); if (rc < 0) @@ -172,12 +173,12 @@ getRgbComponents(int jasperCmpnt[], jas_image_t * const jasperP) { else jasperCmpnt[PAM_GRN_PLANE] = rc; - if (jas_image_cmptsgnd(jasperP, rc)) + if (jas_image_cmptsgnd(jasperP, rc)) pm_error("Input image says it is RGB, but has signed values " "for what should be the green intensities."); } { - int const rc = + int const rc = jas_image_getcmptbytype(jasperP, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B)); if (rc < 0) @@ -186,18 +187,18 @@ getRgbComponents(int jasperCmpnt[], jas_image_t * const jasperP) { else jasperCmpnt[PAM_BLU_PLANE] = rc; - if (jas_image_cmptsgnd(jasperP, rc)) + if (jas_image_cmptsgnd(jasperP, rc)) pm_error("Input image says it is RGB, but has signed values " "for what should be the blue intensities."); } -} +} static void getGrayComponent(int * jasperCmptP, jas_image_t * const jasperP) { - int const rc = + int const rc = jas_image_getcmptbytype(jasperP, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y)); if (rc < 0) @@ -205,7 +206,7 @@ getGrayComponent(int * jasperCmptP, jas_image_t * const jasperP) { "no gray intensity component"); else *jasperCmptP = rc; - if (jas_image_cmptsgnd(jasperP, 0)) + if (jas_image_cmptsgnd(jasperP, 0)) pm_error("Input image says it is grayscale, but has signed values " "for what should be the gray levels."); } @@ -220,13 +221,13 @@ validateComponentsAlike(jas_image_t * const jasperP) { all the channels are the same, and abort the program if not. -----------------------------------------------------------------------------*/ int cmptNo; - + for (cmptNo = 0; cmptNo < jas_image_numcmpts(jasperP); ++cmptNo) { - if (jas_image_cmptwidth(jasperP, cmptNo) != + if (jas_image_cmptwidth(jasperP, cmptNo) != jas_image_cmptwidth(jasperP, 0)) pm_message("Input image does not have components all the same " "width."); - if (jas_image_cmptheight(jasperP, cmptNo) != + if (jas_image_cmptheight(jasperP, cmptNo) != jas_image_cmptheight(jasperP, 0)) pm_message("Input image does not have components all the same " "height."); @@ -240,7 +241,7 @@ maxJasperComponentPrecision(jas_image_t * const jasperP) { int cmptNo; unsigned int max; - + max = 1; for (cmptNo = 0; cmptNo < jas_image_numcmpts(jasperP); ++cmptNo) @@ -261,8 +262,8 @@ computeOutputParm(jas_image_t * const jasperP, with the Jasper library that corresponds to Plane P of the PAM. */ - switch (jas_clrspc_fam(jas_image_clrspc(jasperP))) { - case JAS_CLRSPC_FAM_GRAY: + switch (jas_clrspc_fam(jas_image_clrspc(jasperP))) { + case JAS_CLRSPC_FAM_GRAY: outpamP->depth = 1; MALLOCARRAY_NOFAIL(jasperCmptNo, 1); getGrayComponent(&jasperCmptNo[0], jasperP); @@ -274,7 +275,7 @@ computeOutputParm(jas_image_t * const jasperP, strcpy(outpamP->tuple_type, PAM_PGM_TUPLETYPE); } break; - case JAS_CLRSPC_FAM_RGB: + case JAS_CLRSPC_FAM_RGB: outpamP->depth = 3; MALLOCARRAY_NOFAIL(jasperCmptNo, 3); getRgbComponents(jasperCmptNo, jasperP); @@ -292,15 +293,15 @@ computeOutputParm(jas_image_t * const jasperP, jasperCmptNo[plane] = plane; } strcpy(outpamP->tuple_type, ""); - if (jas_image_cmptsgnd(jasperP, 0)) + if (jas_image_cmptsgnd(jasperP, 0)) pm_message("Warning: Input image has signed sample values. " "They will be represented in the PAM output in " "two's complement."); } outpamP->plainformat = FALSE; - outpamP->width = jas_image_cmptwidth(jasperP, 0); - outpamP->height = jas_image_cmptheight(jasperP, 0); + outpamP->width = jas_image_cmptwidth(jasperP, 0); + outpamP->height = jas_image_cmptheight(jasperP, 0); validateComponentsAlike(jasperP); @@ -308,7 +309,7 @@ computeOutputParm(jas_image_t * const jasperP, unsigned int const maxPrecision = maxJasperComponentPrecision(jasperP); outpamP->maxval = pm_bitstomaxval(maxPrecision); - + outpamP->bytes_per_sample = (maxPrecision + 7)/8; } *jasperCmptNoP = jasperCmptNo; @@ -319,7 +320,7 @@ computeOutputParm(jas_image_t * const jasperP, static void createMatrices(struct pam * const outpamP, jas_matrix_t *** matrixP) { - jas_matrix_t ** matrix; + jas_matrix_t ** matrix; unsigned int plane; MALLOCARRAY_NOFAIL(matrix, outpamP->depth); @@ -330,14 +331,14 @@ createMatrices(struct pam * const outpamP, jas_matrix_t *** matrixP) { if (matrix[plane] == NULL) pm_error("Unable to create matrix for plane %u. " "jas_matrix_create() failed.", plane); - } + } *matrixP = matrix; } static void -destroyMatrices(struct pam * const outpamP, +destroyMatrices(struct pam * const outpamP, jas_matrix_t ** const matrix ) { unsigned int plane; @@ -345,7 +346,7 @@ destroyMatrices(struct pam * const outpamP, for (plane = 0; plane < outpamP->depth; ++plane) jas_matrix_destroy(matrix[plane]); free(matrix); -} +} @@ -355,7 +356,7 @@ computeComponentMaxval(struct pam * const outpamP, int const jasperCmpt[], sample ** const jasperMaxvalP, bool * const singleMaxvalP) { - + sample * jasperMaxval; unsigned int plane; @@ -363,7 +364,7 @@ computeComponentMaxval(struct pam * const outpamP, *singleMaxvalP = TRUE; /* initial assumption */ for (plane = 0; plane < outpamP->depth; ++plane) { - jasperMaxval[plane] = + jasperMaxval[plane] = pm_bitstomaxval(jas_image_cmptprec(jasperP, jasperCmpt[plane])); if (jasperMaxval[plane] != jasperMaxval[0]) *singleMaxvalP = FALSE; @@ -371,7 +372,7 @@ computeComponentMaxval(struct pam * const outpamP, *jasperMaxvalP = jasperMaxval; } - + static void copyRowSingleMaxval(jas_seqent_t ** const jasperRow, @@ -386,10 +387,10 @@ copyRowSingleMaxval(jas_seqent_t ** const jasperRow, This is significantly faster than copyRowAnyMaxval(). -----------------------------------------------------------------------------*/ unsigned int col; - + for (col = 0; col < outpamP->width; ++col) { unsigned int plane; - for (plane = 0; plane < outpamP->depth; ++plane) + for (plane = 0; plane < outpamP->depth; ++plane) tuplerow[col][plane] = jasperRow[plane][col]; } } @@ -410,12 +411,12 @@ copyRowAnyMaxval(jas_seqent_t ** const jasperRow, This is significantly slower than copyRowSingleMaxval(). -----------------------------------------------------------------------------*/ unsigned int col; - + for (col = 0; col < outpamP->width; ++col) { unsigned int plane; - for (plane = 0; plane < outpamP->depth; ++plane) - tuplerow[col][plane] = - jasperRow[plane][col] * + for (plane = 0; plane < outpamP->depth; ++plane) + tuplerow[col][plane] = + jasperRow[plane][col] * outpamP->maxval / jasperMaxval[plane]; } } @@ -460,11 +461,11 @@ convertToPamPnm(struct pam * const outpamP, matrix[plane]); if (rc != 0) pm_error("jas_image_readcmpt() of row %u plane %u " - "failed.", + "failed.", row, plane); jasperRow[plane] = jas_matrix_getref(matrix[plane], 0, 0); } - if (singleMaxval) + if (singleMaxval) copyRowSingleMaxval(jasperRow, tuplerow, outpamP); else copyRowAnyMaxval(jasperRow, tuplerow, outpamP, jasperMaxval); @@ -488,25 +489,25 @@ main(int argc, char **argv) struct pam outpam; int * jasperCmpt; /* malloc'ed */ /* jaspercmpt[P] is the component number for use with the - Jasper library that corresponds to Plane P of the PAM. + Jasper library that corresponds to Plane P of the PAM. */ jas_image_t * jasperP; pnm_init(&argc, argv); - + parseCommandLine(argc, argv, &cmdline); - - { + + { int rc; - + rc = jas_init(); if ( rc != 0 ) pm_error("Failed to initialize Jasper library. " "jas_init() returns rc %d", rc ); } - + jas_setdbglevel(cmdline.debuglevel); - + readJ2k(cmdline.inputFilename, &jasperP); outpam.file = stdout; @@ -516,13 +517,16 @@ main(int argc, char **argv) computeOutputParm(jasperP, &outpam, &jasperCmpt); pnm_writepaminit(&outpam); - + convertToPamPnm(&outpam, jasperP, jasperCmpt); - + free(jasperCmpt); - jas_image_destroy(jasperP); + jas_image_destroy(jasperP); pm_close(stdout); - + return 0; } + + + diff --git a/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c b/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c index 91ce6c51..a9463a57 100644 --- a/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c +++ b/converter/other/jpeg2000/libjasper/jp2/jp2_dec.c @@ -110,16 +110,6 @@ * __END_OF_JASPER_LICENSE__ */ -/* - * JP2 Library - * - * $Id$ - */ - -/******************************************************************************\ -* Includes. -\******************************************************************************/ - #include "jasper/jas_image.h" #include "jasper/jas_stream.h" #include "jasper/jas_math.h" @@ -130,520 +120,548 @@ #include "jp2_cod.h" #include "jp2_dec.h" -#define JP2_VALIDATELEN (JAS_MIN(JP2_JP_LEN + 16, JAS_STREAM_MAXPUTBACK)) - -static jp2_dec_t *jp2_dec_create(void); -static void jp2_dec_destroy(jp2_dec_t *dec); -static int jp2_getcs(jp2_colr_t *colr); -static int jp2_getct(int colorspace, int type, int assoc); -static int fromiccpcs(int cs); - -/******************************************************************************\ -* Functions. -\******************************************************************************/ - -jas_image_t *jp2_decode(jas_stream_t *in, char *optstr) -{ - jp2_box_t *box; - int found; - jas_image_t *image; - jp2_dec_t *dec; - bool samedtype; - int dtype; - int i; - jp2_cmap_t *cmapd; - jp2_pclr_t *pclrd; - jp2_cdef_t *cdefd; - int channo; - int newcmptno; - int_fast32_t *lutents; - jp2_cmapent_t *cmapent; - unsigned char *iccp; - int cs; - - dec = 0; - box = 0; - image = 0; - - if (!(dec = jp2_dec_create())) { - goto error; - } - - /* Get the first box. This should be a JP box. */ - if (!(box = jp2_box_get(in))) { - jas_eprintf("error: cannot get box\n"); - goto error; - } - if (box->type != JP2_BOX_JP) { - jas_eprintf("error: expecting signature box\n"); - goto error; - } - if (box->data.jp.magic != JP2_JP_MAGIC) { - jas_eprintf("incorrect magic number\n"); - goto error; - } - jp2_box_destroy(box); - box = 0; - - /* Get the second box. This should be a FTYP box. */ - if (!(box = jp2_box_get(in))) { - goto error; - } - if (box->type != JP2_BOX_FTYP) { - jas_eprintf("expecting file type box\n"); - goto error; - } - jp2_box_destroy(box); - box = 0; - - /* Get more boxes... */ - found = 0; - while ((box = jp2_box_get(in))) { - if (jas_getdbglevel() >= 1) { - fprintf(stderr, "box type %s\n", box->info->name); - } - switch (box->type) { - case JP2_BOX_JP2C: - found = 1; - break; - case JP2_BOX_IHDR: - if (!dec->ihdr) { - dec->ihdr = box; - box = 0; - } - break; - case JP2_BOX_BPCC: - if (!dec->bpcc) { - dec->bpcc = box; - box = 0; - } - break; - case JP2_BOX_CDEF: - if (!dec->cdef) { - dec->cdef = box; - box = 0; - } - break; - case JP2_BOX_PCLR: - if (!dec->pclr) { - dec->pclr = box; - box = 0; - } - break; - case JP2_BOX_CMAP: - if (!dec->cmap) { - dec->cmap = box; - box = 0; - } - break; - case JP2_BOX_COLR: - if (!dec->colr) { - dec->colr = box; - box = 0; - } - break; - } - if (box) { - jp2_box_destroy(box); - box = 0; - } - if (found) { - break; - } - } - - if (!found) { - jas_eprintf("error: no code stream found\n"); - goto error; - } - - if (!(dec->image = jpc_decode(in, optstr))) { - jas_eprintf("error: cannot decode code stream\n"); - goto error; - } - - /* An IHDR box must be present. */ - if (!dec->ihdr) { - jas_eprintf("error: missing IHDR box\n"); - goto error; - } - - /* Does the number of components indicated in the IHDR box match - the value specified in the code stream? */ - if (dec->ihdr->data.ihdr.numcmpts != jas_image_numcmpts(dec->image)) { - jas_eprintf("warning: number of components mismatch\n"); - } - - /* At least one component must be present. */ - if (!jas_image_numcmpts(dec->image)) { - jas_eprintf("error: no components\n"); - goto error; - } - - /* Determine if all components have the same data type. */ - samedtype = true; - dtype = jas_image_cmptdtype(dec->image, 0); - for (i = 1; i < jas_image_numcmpts(dec->image); ++i) { - if (jas_image_cmptdtype(dec->image, i) != dtype) { - samedtype = false; - break; - } - } - - /* Is the component data type indicated in the IHDR box consistent - with the data in the code stream? */ - if ((samedtype && dec->ihdr->data.ihdr.bpc != JP2_DTYPETOBPC(dtype)) || - (!samedtype && dec->ihdr->data.ihdr.bpc != JP2_IHDR_BPCNULL)) { - jas_eprintf("warning: component data type mismatch\n"); - } - - /* Can we handle the compression type? */ - if (dec->ihdr->data.ihdr.comptype != JP2_IHDR_COMPTYPE) { - jas_eprintf("error: not capable of this compression type\n"); - goto error; - } - - if (dec->bpcc) { - /* Is the number of components indicated in the BPCC box - consistent with the code stream data? */ - if (dec->bpcc->data.bpcc.numcmpts != jas_image_numcmpts( - dec->image)) { - jas_eprintf("warning: number of components mismatch\n"); - } - /* Is the component data type information indicated in the BPCC - box consistent with the code stream data? */ - if (!samedtype) { - for (i = 0; i < jas_image_numcmpts(dec->image); ++i) { - if (jas_image_cmptdtype(dec->image, i) != JP2_BPCTODTYPE(dec->bpcc->data.bpcc.bpcs[i])) { - jas_eprintf("warning: component data type mismatch\n"); - } - } - } else { - jas_eprintf("warning: superfluous BPCC box\n"); - } - } - - /* A COLR box must be present. */ - if (!dec->colr) { - jas_eprintf("error: no COLR box\n"); - goto error; - } - - switch (dec->colr->data.colr.method) { - case JP2_COLR_ENUM: - jas_image_setcolorspace(dec->image, jp2_getcs(&dec->colr->data.colr)); - break; - case JP2_COLR_ICC: - if (dec->colr->data.colr.iccplen < 128) { - abort(); - } - iccp = dec->colr->data.colr.iccp; - cs = (iccp[16] << 24) | (iccp[17] << 16) | (iccp[18] << 8) | - iccp[19]; - if (jas_getdbglevel() > 1) - jas_eprintf("ICC Profile CS %08x\n", cs); - jas_image_setcolorspace(dec->image, fromiccpcs(cs)); - break; - } - - /* If a CMAP box is present, a PCLR box must also be present. */ - if (dec->cmap && !dec->pclr) { - jas_eprintf("warning: missing PCLR box or superfluous CMAP box\n"); - jp2_box_destroy(dec->cmap); - dec->cmap = 0; - } - - /* If a CMAP box is not present, a PCLR box must not be present. */ - if (!dec->cmap && dec->pclr) { - jas_eprintf("warning: missing CMAP box or superfluous PCLR box\n"); - jp2_box_destroy(dec->pclr); - dec->pclr = 0; - } - - /* Determine the number of channels (which is essentially the number - of components after any palette mappings have been applied). */ - dec->numchans = dec->cmap ? dec->cmap->data.cmap.numchans : jas_image_numcmpts(dec->image); - - /* Perform a basic sanity check on the CMAP box if present. */ - if (dec->cmap) { - for (i = 0; i < dec->numchans; ++i) { - /* Is the component number reasonable? */ - if (dec->cmap->data.cmap.ents[i].cmptno >= jas_image_numcmpts(dec->image)) { - jas_eprintf("error: invalid component number in CMAP box\n"); - goto error; - } - /* Is the LUT index reasonable? */ - if (dec->cmap->data.cmap.ents[i].pcol >= dec->pclr->data.pclr.numchans) { - jas_eprintf("error: invalid CMAP LUT index\n"); - goto error; - } - } - } - - /* Allocate space for the channel-number to component-number LUT. */ - if (!(dec->chantocmptlut = jas_malloc(dec->numchans * sizeof(uint_fast16_t)))) { - jas_eprintf("error: no memory\n"); - goto error; - } - - if (!dec->cmap) { - for (i = 0; i < dec->numchans; ++i) { - dec->chantocmptlut[i] = i; - } - } else { - cmapd = &dec->cmap->data.cmap; - pclrd = &dec->pclr->data.pclr; - cdefd = &dec->cdef->data.cdef; - for (channo = 0; channo < cmapd->numchans; ++channo) { - cmapent = &cmapd->ents[channo]; - if (cmapent->map == JP2_CMAP_DIRECT) { - dec->chantocmptlut[channo] = channo; - } else if (cmapent->map == JP2_CMAP_PALETTE) { - lutents = jas_malloc(pclrd->numlutents * sizeof(int_fast32_t)); - for (i = 0; i < pclrd->numlutents; ++i) { - lutents[i] = pclrd->lutdata[cmapent->pcol + i * pclrd->numchans]; - } - newcmptno = jas_image_numcmpts(dec->image); - jas_image_depalettize(dec->image, cmapent->cmptno, pclrd->numlutents, lutents, JP2_BPCTODTYPE(pclrd->bpc[cmapent->pcol]), newcmptno); - dec->chantocmptlut[channo] = newcmptno; - jas_free(lutents); -#if 0 - if (dec->cdef) { - cdefent = jp2_cdef_lookup(cdefd, channo); - if (!cdefent) { - abort(); - } - jas_image_setcmpttype(dec->image, newcmptno, jp2_getct(jas_image_colorspace(dec->image), cdefent->type, cdefent->assoc)); - } else { - jas_image_setcmpttype(dec->image, newcmptno, jp2_getct(jas_image_colorspace(dec->image), 0, channo + 1)); - } -#endif - } - } - } - - /* Mark all components as being of unknown type. */ - - for (i = 0; i < jas_image_numcmpts(dec->image); ++i) { - jas_image_setcmpttype(dec->image, i, JAS_IMAGE_CT_UNKNOWN); - } - - /* Determine the type of each component. */ - if (dec->cdef) { - for (i = 0; i < dec->numchans; ++i) { - jas_image_setcmpttype(dec->image, - dec->chantocmptlut[dec->cdef->data.cdef.ents[i].channo], - jp2_getct(jas_image_colorspace(dec->image), - dec->cdef->data.cdef.ents[i].type, dec->cdef->data.cdef.ents[i].assoc)); - } - } else { - for (i = 0; i < dec->numchans; ++i) { - jas_image_setcmpttype(dec->image, dec->chantocmptlut[i], - jp2_getct(jas_image_colorspace(dec->image), 0, i + 1)); - } - } - - /* Delete any components that are not of interest. */ - for (i = jas_image_numcmpts(dec->image) - 1; i >= 0; --i) { - if (jas_image_cmpttype(dec->image, i) == JAS_IMAGE_CT_UNKNOWN) { - jas_image_delcmpt(dec->image, i); - } - } - - /* Ensure that some components survived. */ - if (!jas_image_numcmpts(dec->image)) { - jas_eprintf("error: no components\n"); - goto error; - } - - /* Prevent the image from being destroyed later. */ - image = dec->image; - dec->image = 0; - - jp2_dec_destroy(dec); - - return image; +#define JP2_VALIDATELEN (JAS_MIN(JP2_JP_LEN + 16, JAS_STREAM_MAXPUTBACK)) -error: - if (box) { - jp2_box_destroy(box); - } - if (dec) { - jp2_dec_destroy(dec); - } - return 0; + + +static jp2_dec_t * +jp2_dec_create(void) { + + jp2_dec_t *dec; + + dec = jas_malloc(sizeof(jp2_dec_t)); + if (dec) { + dec->ihdr = 0; + dec->bpcc = 0; + dec->cdef = 0; + dec->pclr = 0; + dec->image = 0; + dec->chantocmptlut = 0; + dec->cmap = 0; + dec->colr = 0; + } + return dec; } -int jp2_validate(jas_stream_t *in) -{ - char buf[JP2_VALIDATELEN]; - int i; - int n; - - assert(JAS_STREAM_MAXPUTBACK >= JP2_VALIDATELEN); - - /* Read the validation data (i.e., the data used for detecting - the format). */ - if ((n = jas_stream_read(in, buf, JP2_VALIDATELEN)) < 0) { - return -1; - } - - /* Put the validation data back onto the stream, so that the - stream position will not be changed. */ - for (i = n - 1; i >= 0; --i) { - if (jas_stream_ungetc(in, buf[i]) == EOF) { - return -1; - } - } - - /* Did we read enough data? */ - if (n < JP2_VALIDATELEN) { - return -1; - } - - /* Is the box type correct? */ - if (((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]) != - JP2_BOX_JP) - { - return -1; - } - - return 0; + + +static void +jp2_dec_destroy(jp2_dec_t *dec) { + + if (dec->ihdr) + jp2_box_destroy(dec->ihdr); + + if (dec->bpcc) + jp2_box_destroy(dec->bpcc); + + if (dec->cdef) + jp2_box_destroy(dec->cdef); + + if (dec->pclr) + jp2_box_destroy(dec->pclr); + + if (dec->image) + jas_image_destroy(dec->image); + + if (dec->cmap) + jp2_box_destroy(dec->cmap); + + if (dec->colr) + jp2_box_destroy(dec->colr); + + if (dec->chantocmptlut) + jas_free(dec->chantocmptlut); + + jas_free(dec); } -static jp2_dec_t *jp2_dec_create(void) -{ - jp2_dec_t *dec; - - if (!(dec = jas_malloc(sizeof(jp2_dec_t)))) { - return 0; - } - dec->ihdr = 0; - dec->bpcc = 0; - dec->cdef = 0; - dec->pclr = 0; - dec->image = 0; - dec->chantocmptlut = 0; - dec->cmap = 0; - dec->colr = 0; - return dec; + + +static int +jp2_getct(int colorspace, int type, int assoc) { + + if (type == 1 && assoc == 0) + return JAS_IMAGE_CT_OPACITY; + + if (type == 0 && assoc >= 1 && assoc <= 65534) { + switch (colorspace) { + case JAS_IMAGE_CS_RGB: + switch (assoc) { + case JP2_CDEF_RGB_R: + return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R); + break; + case JP2_CDEF_RGB_G: + return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G); + break; + case JP2_CDEF_RGB_B: + return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B); + break; + } + break; + case JAS_IMAGE_CS_YCBCR: + switch (assoc) { + case JP2_CDEF_YCBCR_Y: + return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_YCBCR_Y); + break; + case JP2_CDEF_YCBCR_CB: + return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_YCBCR_CB); + break; + case JP2_CDEF_YCBCR_CR: + return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_YCBCR_CR); + break; + } + break; + case JAS_IMAGE_CS_GRAY: + switch (assoc) { + case JP2_CDEF_GRAY_Y: + return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y); + break; + } + break; +#if 0 + case JAS_IMAGE_CS_ICC: +#endif + default: + return JAS_IMAGE_CT_COLOR(assoc - 1); + break; + } + } + return JAS_IMAGE_CT_UNKNOWN; } -static void jp2_dec_destroy(jp2_dec_t *dec) -{ - if (dec->ihdr) { - jp2_box_destroy(dec->ihdr); - } - if (dec->bpcc) { - jp2_box_destroy(dec->bpcc); - } - if (dec->cdef) { - jp2_box_destroy(dec->cdef); - } - if (dec->pclr) { - jp2_box_destroy(dec->pclr); - } - if (dec->image) { - jas_image_destroy(dec->image); - } - if (dec->cmap) { - jp2_box_destroy(dec->cmap); - } - if (dec->colr) { - jp2_box_destroy(dec->colr); - } - if (dec->chantocmptlut) { - jas_free(dec->chantocmptlut); - } - jas_free(dec); + + +static int +jp2_getcs(jp2_colr_t *colr) { + + if (colr->method == JP2_COLR_ENUM) { + switch (colr->csid) { + case JP2_COLR_SRGB: + return JAS_IMAGE_CS_RGB; + break; + case JP2_COLR_SYCC: + return JAS_IMAGE_CS_YCBCR; + break; + case JP2_COLR_SGRAY: + return JAS_IMAGE_CS_GRAY; + break; + } + } + return JAS_IMAGE_CS_UNKNOWN; } +static int +fromiccpcs(int cs) { + + switch (cs) { + case ICC_CS_RGB: + return JAS_IMAGE_CS_RGB; + break; + case ICC_CS_YCBCR: + return JAS_IMAGE_CS_YCBCR; + break; + case ICC_CS_GRAY: + return JAS_IMAGE_CS_GRAY; + break; + } + return JAS_IMAGE_CS_UNKNOWN; +} -static int jp2_getct(int colorspace, int type, int assoc) -{ - if (type == 1 && assoc == 0) { - return JAS_IMAGE_CT_OPACITY; - } - if (type == 0 && assoc >= 1 && assoc <= 65534) { - switch (colorspace) { - case JAS_IMAGE_CS_RGB: - switch (assoc) { - case JP2_CDEF_RGB_R: - return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R); - break; - case JP2_CDEF_RGB_G: - return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G); - break; - case JP2_CDEF_RGB_B: - return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B); - break; - } - break; - case JAS_IMAGE_CS_YCBCR: - switch (assoc) { - case JP2_CDEF_YCBCR_Y: - return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_YCBCR_Y); - break; - case JP2_CDEF_YCBCR_CB: - return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_YCBCR_CB); - break; - case JP2_CDEF_YCBCR_CR: - return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_YCBCR_CR); - break; - } - break; - case JAS_IMAGE_CS_GRAY: - switch (assoc) { - case JP2_CDEF_GRAY_Y: - return JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y); - break; - } - break; +jas_image_t * +jp2_decode(jas_stream_t *in, char *optstr) { + + jp2_box_t *box; + int found; + jas_image_t *image; + jp2_dec_t *dec; + bool samedtype; + int dtype; + int i; + jp2_cmap_t *cmapd; + jp2_pclr_t *pclrd; + int channo; + int newcmptno; + int_fast32_t *lutents; + jp2_cmapent_t *cmapent; + unsigned char *iccp; + int cs; + + dec = 0; + box = 0; + image = 0; + + if (!(dec = jp2_dec_create())) { + goto error; + } + + /* Get the first box. This should be a JP box. */ + if (!(box = jp2_box_get(in))) { + jas_eprintf("error: cannot get box\n"); + goto error; + } + if (box->type != JP2_BOX_JP) { + jas_eprintf("error: expecting signature box\n"); + goto error; + } + if (box->data.jp.magic != JP2_JP_MAGIC) { + jas_eprintf("incorrect magic number\n"); + goto error; + } + jp2_box_destroy(box); + box = 0; + + /* Get the second box. This should be a FTYP box. */ + if (!(box = jp2_box_get(in))) { + goto error; + } + if (box->type != JP2_BOX_FTYP) { + jas_eprintf("expecting file type box\n"); + goto error; + } + jp2_box_destroy(box); + box = 0; + + /* Get more boxes... */ + found = 0; + while ((box = jp2_box_get(in))) { + if (jas_getdbglevel() >= 1) { + fprintf(stderr, "box type %s\n", box->info->name); + } + switch (box->type) { + case JP2_BOX_JP2C: + found = 1; + break; + case JP2_BOX_IHDR: + if (!dec->ihdr) { + dec->ihdr = box; + box = 0; + } + break; + case JP2_BOX_BPCC: + if (!dec->bpcc) { + dec->bpcc = box; + box = 0; + } + break; + case JP2_BOX_CDEF: + if (!dec->cdef) { + dec->cdef = box; + box = 0; + } + break; + case JP2_BOX_PCLR: + if (!dec->pclr) { + dec->pclr = box; + box = 0; + } + break; + case JP2_BOX_CMAP: + if (!dec->cmap) { + dec->cmap = box; + box = 0; + } + break; + case JP2_BOX_COLR: + if (!dec->colr) { + dec->colr = box; + box = 0; + } + break; + } + if (box) { + jp2_box_destroy(box); + box = 0; + } + if (found) { + break; + } + } + + if (!found) { + jas_eprintf("error: no code stream found\n"); + goto error; + } + + if (!(dec->image = jpc_decode(in, optstr))) { + jas_eprintf("error: cannot decode code stream\n"); + goto error; + } + + /* An IHDR box must be present. */ + if (!dec->ihdr) { + jas_eprintf("error: missing IHDR box\n"); + goto error; + } + + /* Does the number of components indicated in the IHDR box match + the value specified in the code stream? */ + if (dec->ihdr->data.ihdr.numcmpts != jas_image_numcmpts(dec->image)) { + jas_eprintf("warning: number of components mismatch\n"); + } + + /* At least one component must be present. */ + if (!jas_image_numcmpts(dec->image)) { + jas_eprintf("error: no components\n"); + goto error; + } + + /* Determine if all components have the same data type. */ + samedtype = true; + dtype = jas_image_cmptdtype(dec->image, 0); + for (i = 1; i < jas_image_numcmpts(dec->image); ++i) { + if (jas_image_cmptdtype(dec->image, i) != dtype) { + samedtype = false; + break; + } + } + + /* Is the component data type indicated in the IHDR box consistent + with the data in the code stream? */ + if ((samedtype && dec->ihdr->data.ihdr.bpc != JP2_DTYPETOBPC(dtype)) || + (!samedtype && dec->ihdr->data.ihdr.bpc != JP2_IHDR_BPCNULL)) { + jas_eprintf("warning: component data type mismatch\n"); + } + + /* Can we handle the compression type? */ + if (dec->ihdr->data.ihdr.comptype != JP2_IHDR_COMPTYPE) { + jas_eprintf("error: not capable of this compression type\n"); + goto error; + } + + if (dec->bpcc) { + /* Is the number of components indicated in the BPCC box + consistent with the code stream data? */ + if (dec->bpcc->data.bpcc.numcmpts != jas_image_numcmpts( + dec->image)) { + jas_eprintf("warning: number of components mismatch\n"); + } + /* Is the component data type information indicated in the BPCC + box consistent with the code stream data? */ + if (!samedtype) { + for (i = 0; i < jas_image_numcmpts(dec->image); ++i) { + if (jas_image_cmptdtype(dec->image, i) != + JP2_BPCTODTYPE(dec->bpcc->data.bpcc.bpcs[i])) { + jas_eprintf("warning: component data type mismatch\n"); + } + } + } else { + jas_eprintf("warning: superfluous BPCC box\n"); + } + } + + /* A COLR box must be present. */ + if (!dec->colr) { + jas_eprintf("error: no COLR box\n"); + goto error; + } + + switch (dec->colr->data.colr.method) { + case JP2_COLR_ENUM: + jas_image_setcolorspace(dec->image, jp2_getcs(&dec->colr->data.colr)); + break; + case JP2_COLR_ICC: + if (dec->colr->data.colr.iccplen < 128) { + abort(); + } + iccp = dec->colr->data.colr.iccp; + cs = (iccp[16] << 24) | (iccp[17] << 16) | (iccp[18] << 8) | + iccp[19]; + if (jas_getdbglevel() > 1) + jas_eprintf("ICC Profile CS %08x\n", cs); + jas_image_setcolorspace(dec->image, fromiccpcs(cs)); + break; + } + + /* If a CMAP box is present, a PCLR box must also be present. */ + if (dec->cmap && !dec->pclr) { + jas_eprintf("warning: missing PCLR box or superfluous CMAP box\n"); + jp2_box_destroy(dec->cmap); + dec->cmap = 0; + } + + /* If a CMAP box is not present, a PCLR box must not be present. */ + if (!dec->cmap && dec->pclr) { + jas_eprintf("warning: missing CMAP box or superfluous PCLR box\n"); + jp2_box_destroy(dec->pclr); + dec->pclr = 0; + } + + /* Determine the number of channels (which is essentially the number + of components after any palette mappings have been applied). */ + dec->numchans = dec->cmap ? + dec->cmap->data.cmap.numchans : + jas_image_numcmpts(dec->image); + + /* Perform a basic sanity check on the CMAP box if present. */ + if (dec->cmap) { + for (i = 0; i < dec->numchans; ++i) { + /* Is the component number reasonable? */ + if (dec->cmap->data.cmap.ents[i].cmptno >= + jas_image_numcmpts(dec->image)) { + jas_eprintf("error: invalid component number in CMAP box\n"); + goto error; + } + /* Is the LUT index reasonable? */ + if (dec->cmap->data.cmap.ents[i].pcol >= + dec->pclr->data.pclr.numchans) { + jas_eprintf("error: invalid CMAP LUT index\n"); + goto error; + } + } + } + + /* Allocate space for the channel-number to component-number LUT. */ + dec->chantocmptlut = jas_malloc(dec->numchans * sizeof(uint_fast16_t)); + if (!dec->chantocmptlut) { + jas_eprintf("error: no memory\n"); + goto error; + } + + if (!dec->cmap) { + for (i = 0; i < dec->numchans; ++i) { + dec->chantocmptlut[i] = i; + } + } else { + cmapd = &dec->cmap->data.cmap; + pclrd = &dec->pclr->data.pclr; + for (channo = 0; channo < cmapd->numchans; ++channo) { + cmapent = &cmapd->ents[channo]; + if (cmapent->map == JP2_CMAP_DIRECT) { + dec->chantocmptlut[channo] = channo; + } else if (cmapent->map == JP2_CMAP_PALETTE) { + lutents = jas_malloc(pclrd->numlutents * sizeof(int_fast32_t)); + for (i = 0; i < pclrd->numlutents; ++i) { + lutents[i] = + pclrd->lutdata[cmapent->pcol + i * pclrd->numchans]; + } + newcmptno = jas_image_numcmpts(dec->image); + jas_image_depalettize( + dec->image, cmapent->cmptno, pclrd->numlutents, lutents, + JP2_BPCTODTYPE(pclrd->bpc[cmapent->pcol]), newcmptno); + dec->chantocmptlut[channo] = newcmptno; + jas_free(lutents); #if 0 - case JAS_IMAGE_CS_ICC: + if (dec->cdef) { + jp2_cdef_t * const cdefd = &dec->cdef->data.cdef; + cdefent = jp2_cdef_lookup(cdefd, channo); + if (!cdefent) { + abort(); + } + jas_image_setcmpttype( + dec->image, newcmptno, + jp2_getct(jas_image_colorspace(dec->image), + cdefent->type, cdefent->assoc)); + } else { + jas_image_setcmpttype( + dec->image, newcmptno, + jp2_getct(jas_image_colorspace(dec->image), + 0, + channo + 1)); + } #endif - default: - return JAS_IMAGE_CT_COLOR(assoc - 1); - break; - } - } - return JAS_IMAGE_CT_UNKNOWN; -} + } + } + } + + /* Mark all components as being of unknown type. */ + + for (i = 0; i < jas_image_numcmpts(dec->image); ++i) { + jas_image_setcmpttype(dec->image, i, JAS_IMAGE_CT_UNKNOWN); + } + + /* Determine the type of each component. */ + if (dec->cdef) { + unsigned int i; + for (i = 0; i < dec->numchans; ++i) { + jas_image_setcmpttype( + dec->image, + dec->chantocmptlut[dec->cdef->data.cdef.ents[i].channo], + jp2_getct(jas_image_colorspace(dec->image), + dec->cdef->data.cdef.ents[i].type, + dec->cdef->data.cdef.ents[i].assoc)); + } + } else { + unsigned int i; + for (i = 0; i < dec->numchans; ++i) { + jas_image_setcmpttype(dec->image, dec->chantocmptlut[i], + jp2_getct(jas_image_colorspace(dec->image), 0, i + 1)); + } + } + + /* Delete any components that are not of interest. */ + for (i = jas_image_numcmpts(dec->image) - 1; i >= 0; --i) { + if (jas_image_cmpttype(dec->image, i) == JAS_IMAGE_CT_UNKNOWN) { + jas_image_delcmpt(dec->image, i); + } + } + + /* Ensure that some components survived. */ + if (!jas_image_numcmpts(dec->image)) { + jas_eprintf("error: no components\n"); + goto error; + } + + /* Prevent the image from being destroyed later. */ + image = dec->image; + dec->image = 0; + + jp2_dec_destroy(dec); + + return image; -static int jp2_getcs(jp2_colr_t *colr) -{ - if (colr->method == JP2_COLR_ENUM) { - switch (colr->csid) { - case JP2_COLR_SRGB: - return JAS_IMAGE_CS_RGB; - break; - case JP2_COLR_SYCC: - return JAS_IMAGE_CS_YCBCR; - break; - case JP2_COLR_SGRAY: - return JAS_IMAGE_CS_GRAY; - break; - } - } - return JAS_IMAGE_CS_UNKNOWN; +error: + if (box) { + jp2_box_destroy(box); + } + if (dec) { + jp2_dec_destroy(dec); + } + return 0; } -static int fromiccpcs(int cs) -{ - switch (cs) { - case ICC_CS_RGB: - return JAS_IMAGE_CS_RGB; - break; - case ICC_CS_YCBCR: - return JAS_IMAGE_CS_YCBCR; - break; - case ICC_CS_GRAY: - return JAS_IMAGE_CS_GRAY; - break; - } - return JAS_IMAGE_CS_UNKNOWN; + + +int +jp2_validate(jas_stream_t *in) { + + char buf[JP2_VALIDATELEN]; + int i; + int n; + + assert(JAS_STREAM_MAXPUTBACK >= JP2_VALIDATELEN); + + /* Read the validation data (i.e., the data used for detecting + the format). */ + if ((n = jas_stream_read(in, buf, JP2_VALIDATELEN)) < 0) { + return -1; + } + + /* Put the validation data back onto the stream, so that the + stream position will not be changed. */ + for (i = n - 1; i >= 0; --i) { + if (jas_stream_ungetc(in, buf[i]) == EOF) { + return -1; + } + } + + /* Did we read enough data? */ + if (n < JP2_VALIDATELEN) { + return -1; + } + + /* Is the box type correct? */ + if (((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]) != + JP2_BOX_JP) + { + return -1; + } + + return 0; } + + + diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_dec.c b/converter/other/jpeg2000/libjasper/jpc/jpc_dec.c index 72bd0126..cada97f8 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_dec.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_dec.c @@ -458,6 +458,12 @@ static int jpc_dec_decode(jpc_dec_t *dec) static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms) { + /* Ignore the information in the CRG marker segment for now. + This information serves no useful purpose for decoding anyhow. + Some other parts of the code need to be changed if these lines + are enabled. + */ +#ifdef USING_CRG uint_fast16_t cmptno; jpc_dec_cmpt_t *cmpt; jpc_crg_t *crg; @@ -465,14 +471,10 @@ static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms) crg = &ms->parms.crg; for (cmptno = 0, cmpt = dec->cmpts; cmptno < dec->numcomps; ++cmptno, ++cmpt) { - /* Ignore the information in the CRG marker segment for now. - This information serves no useful purpose for decoding anyhow. - Some other parts of the code need to be changed if these lines - are uncommented. cmpt->hsubstep = crg->comps[cmptno].hoff; cmpt->vsubstep = crg->comps[cmptno].voff; - */ } +#endif return 0; } @@ -701,7 +703,6 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) uint_fast32_t tlcbgxstart; uint_fast32_t tlcbgystart; uint_fast32_t brcbgxend; - uint_fast32_t brcbgyend; uint_fast32_t cbgxstart; uint_fast32_t cbgystart; uint_fast32_t cbgxend; @@ -792,14 +793,12 @@ rlvl->bands = 0; tlcbgxstart = tlprcxstart; tlcbgystart = tlprcystart; brcbgxend = brprcxend; - brcbgyend = brprcyend; rlvl->cbgwidthexpn = rlvl->prcwidthexpn; rlvl->cbgheightexpn = rlvl->prcheightexpn; } else { tlcbgxstart = JPC_CEILDIVPOW2(tlprcxstart, 1); tlcbgystart = JPC_CEILDIVPOW2(tlprcystart, 1); brcbgxend = JPC_CEILDIVPOW2(brprcxend, 1); - brcbgyend = JPC_CEILDIVPOW2(brprcyend, 1); rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1; rlvl->cbgheightexpn = rlvl->prcheightexpn - 1; } diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c index d17e9aa3..9db41ca2 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c @@ -73,9 +73,9 @@ int ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size); static void pass_destroy(jpc_enc_pass_t *pass); void jpc_enc_dump(jpc_enc_t *enc); -/******************************************************************************\ +/*****************************************************************************\ * Local prototypes. -\******************************************************************************/ +\*****************************************************************************/ void quantize(jas_matrix_t *data, jpc_fix_t stepsize); static int jpc_enc_encodemainhdr(jpc_enc_t *enc); @@ -90,8 +90,11 @@ int setins(int numvalues, jpc_flt_t *values, jpc_flt_t value); static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image); void jpc_enc_cp_destroy(jpc_enc_cp_t *cp); -static uint_fast32_t jpc_abstorelstepsize(jpc_fix_t absdelta, int scaleexpn) -{ + + +static uint_fast32_t +jpc_abstorelstepsize(jpc_fix_t absdelta, int scaleexpn) { + int p; uint_fast32_t mant; uint_fast32_t expn; @@ -111,6 +114,8 @@ static uint_fast32_t jpc_abstorelstepsize(jpc_fix_t absdelta, int scaleexpn) return JPC_QCX_EXPN(expn) | JPC_QCX_MANT(mant); } + + typedef enum { OPT_DEBUG, OPT_IMGAREAOFFX, @@ -199,6 +204,7 @@ jas_taginfo_t modetab[] = { }; + static void tracev(const char * const fmt, va_list args) { @@ -224,12 +230,9 @@ trace(const char * const fmt, ...) { -/******************************************************************************\ -* The main encoder entry point. -\******************************************************************************/ +int +jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr) { -int jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr) -{ jpc_enc_t *enc; jpc_enc_cp_t *cp; @@ -287,12 +290,15 @@ error: return -1; } -/******************************************************************************\ + + +/*****************************************************************************\ * Option parsing code. -\******************************************************************************/ +\*****************************************************************************/ + +static jpc_enc_cp_t * +cp_create(char *optstr, jas_image_t *image) { -static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image) -{ jpc_enc_cp_t *cp; jas_tvparser_t *tvp; int ret; @@ -343,10 +349,12 @@ static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image) hsteplcm = 1; vsteplcm = 1; for (cmptno = 0; cmptno < jas_image_numcmpts(image); ++cmptno) { - if (jas_image_cmptbrx(image, cmptno) + jas_image_cmpthstep(image, cmptno) <= + if (jas_image_cmptbrx(image, cmptno) + + jas_image_cmpthstep(image, cmptno) <= jas_image_brx(image) || jas_image_cmptbry(image, cmptno) + jas_image_cmptvstep(image, cmptno) <= jas_image_bry(image)) { - fprintf(stderr, "We don't know how to interpret this image type\n"); + fprintf(stderr, + "We don't know how to interpret this image type\n"); goto error; } /* Note: We ought to be calculating the LCMs here. Fix some day. */ @@ -495,7 +503,8 @@ static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image) if (jpc_atoaf(jas_tvparser_getval(tvp), &numilyrrates, &ilyrrates)) { fprintf(stderr, - "warning: invalid intermediate layer rates specifier ignored (%s)\n", + "warning: invalid intermediate layer rates specifier " + "ignored (%s)\n", jas_tvparser_getval(tvp)); } break; @@ -552,20 +561,26 @@ static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image) if (cp->numcmpts == 3) { mctvalid = true; for (cmptno = 0; cmptno < jas_image_numcmpts(image); ++cmptno) { - if (jas_image_cmptprec(image, cmptno) != jas_image_cmptprec(image, 0) || - jas_image_cmptsgnd(image, cmptno) != jas_image_cmptsgnd(image, 0) || - jas_image_cmptwidth(image, cmptno) != jas_image_cmptwidth(image, 0) || - jas_image_cmptheight(image, cmptno) != jas_image_cmptheight(image, 0)) { + if (jas_image_cmptprec(image, cmptno) != + jas_image_cmptprec(image, 0) || + jas_image_cmptsgnd(image, cmptno) != + jas_image_cmptsgnd(image, 0) || + jas_image_cmptwidth(image, cmptno) != + jas_image_cmptwidth(image, 0) || + jas_image_cmptheight(image, cmptno) != + jas_image_cmptheight(image, 0)) { mctvalid = false; } } } else { mctvalid = false; } - if (mctvalid && enablemct && jas_image_colorspace(image) != JAS_IMAGE_CS_RGB) { + if (mctvalid && enablemct && jas_image_colorspace(image) != + JAS_IMAGE_CS_RGB) { fprintf(stderr, "warning: color model apparently not RGB\n"); } - if (mctvalid && enablemct && jas_image_colorspace(image) == JAS_IMAGE_CS_RGB) { + if (mctvalid && enablemct && jas_image_colorspace(image) == + JAS_IMAGE_CS_RGB) { tcp->mctid = (tcp->intmode) ? (JPC_MCT_RCT) : (JPC_MCT_ICT); } else { tcp->mctid = JPC_MCT_NONE; @@ -682,16 +697,20 @@ static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image) /* The intermediate layers rates must increase monotonically. */ for (lyrno = 0; lyrno + 2 < tcp->numlyrs; ++lyrno) { if (tcp->ilyrrates[lyrno] >= tcp->ilyrrates[lyrno + 1]) { - fprintf(stderr, "intermediate layer rates must increase monotonically\n"); + fprintf(stderr, + "intermediate layer rates must increase " + "monotonically\n"); goto error; } } /* The intermediate layer rates must be less than the overall rate. */ if (cp->totalsize != UINT_FAST32_MAX) { for (lyrno = 0; lyrno < tcp->numlyrs - 1; ++lyrno) { - if (jpc_fixtodbl(tcp->ilyrrates[lyrno]) > ((double) cp->totalsize) - / cp->rawsize) { - fprintf(stderr, "warning: intermediate layer rates must be less than overall rate\n"); + if (jpc_fixtodbl(tcp->ilyrrates[lyrno]) > + ((double) cp->totalsize) / cp->rawsize) { + fprintf(stderr, + "warning: intermediate layer rates must be " + "less than overall rate\n"); goto error; } } @@ -718,8 +737,11 @@ error: return 0; } -void jpc_enc_cp_destroy(jpc_enc_cp_t *cp) -{ + + +void +jpc_enc_cp_destroy(jpc_enc_cp_t *cp) { + if (cp->ccps) { if (cp->tcp.ilyrrates) { jas_free(cp->tcp.ilyrrates); @@ -729,8 +751,11 @@ void jpc_enc_cp_destroy(jpc_enc_cp_t *cp) jas_free(cp); } -int ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size) -{ + + +int +ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size) { + char *cp; jpc_flt_t f; @@ -750,12 +775,13 @@ int ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size) return 0; } -/******************************************************************************\ +/*****************************************************************************\ * Encoder constructor and destructor. -\******************************************************************************/ +\*****************************************************************************/ + +jpc_enc_t * +jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image) { -jpc_enc_t *jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image) -{ jpc_enc_t *enc; enc = 0; @@ -788,11 +814,15 @@ error: return 0; } -void jpc_enc_destroy(jpc_enc_t *enc) -{ + + +void +jpc_enc_destroy(jpc_enc_t *enc) { + /* The image object (i.e., enc->image) and output stream object - (i.e., enc->out) are created outside of the encoder. - Therefore, they must not be destroyed here. */ + (i.e., enc->out) are created outside of the encoder. + Therefore, they must not be destroyed here. + */ if (enc->curtile) { jpc_enc_tile_destroy(enc->curtile); @@ -810,24 +840,22 @@ void jpc_enc_destroy(jpc_enc_t *enc) jas_free(enc); } -/******************************************************************************\ -* Code. -\******************************************************************************/ -static int jpc_enc_encodemainhdr(jpc_enc_t *enc) -{ + +static int +jpc_enc_encodemainhdr(jpc_enc_t *enc) { + jpc_siz_t *siz; jpc_cod_t *cod; jpc_qcd_t *qcd; int i; -long startoff; -long mainhdrlen; + long startoff; + long mainhdrlen; jpc_enc_cp_t *cp; jpc_qcc_t *qcc; jpc_enc_tccp_t *tccp; uint_fast16_t cmptno; jpc_tsfb_band_t bandinfos[JPC_MAXBANDS]; - jpc_fix_t mctsynweight; jpc_enc_tcp_t *tcp; jpc_tsfb_t *tsfb; jpc_tsfb_band_t *bandinfo; @@ -841,7 +869,7 @@ long mainhdrlen; cp = enc->cp; -startoff = jas_stream_getrwcount(enc->out); + startoff = jas_stream_getrwcount(enc->out); /* Write SOC marker segment. */ if (!(enc->mrk = jpc_ms_create(JPC_MS_SOC))) { @@ -922,7 +950,6 @@ startoff = jas_stream_getrwcount(enc->out); jpc_tsfb_getbands(tsfb, 0, 0, 1 << tccp->maxrlvls, 1 << tccp->maxrlvls, bandinfos); jpc_tsfb_destroy(tsfb); - mctsynweight = jpc_mct_getsynweight(tcp->mctid, cmptno); numbands = 3 * tccp->maxrlvls - 2; for (bandno = 0, bandinfo = bandinfos; bandno < numbands; ++bandno, ++bandinfo) { @@ -953,14 +980,17 @@ startoff = jas_stream_getrwcount(enc->out); cod->prg = cp->tcp.prg; cod->numlyrs = cp->tcp.numlyrs; cod->compparms.cblkwidthval = JPC_COX_CBLKSIZEEXPN(cp->tccp.cblkwidthexpn); - cod->compparms.cblkheightval = JPC_COX_CBLKSIZEEXPN(cp->tccp.cblkheightexpn); + cod->compparms.cblkheightval = + JPC_COX_CBLKSIZEEXPN(cp->tccp.cblkheightexpn); cod->compparms.cblksty = cp->tccp.cblksty; cod->compparms.qmfbid = cp->tccp.qmfbid; cod->mctrans = (cp->tcp.mctid != JPC_MCT_NONE); if (tccp->csty & JPC_COX_PRT) { for (rlvlno = 0; rlvlno < tccp->maxrlvls; ++rlvlno) { - cod->compparms.rlvls[rlvlno].parwidthval = tccp->prcwidthexpns[rlvlno]; - cod->compparms.rlvls[rlvlno].parheightval = tccp->prcheightexpns[rlvlno]; + cod->compparms.rlvls[rlvlno].parwidthval = + tccp->prcwidthexpns[rlvlno]; + cod->compparms.rlvls[rlvlno].parheightval = + tccp->prcheightexpns[rlvlno]; } } if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { @@ -1023,17 +1053,23 @@ startoff = jas_stream_getrwcount(enc->out); return 0; } -int jpc_enc_encodetiledata(jpc_enc_t *enc) -{ -assert(enc->tmpstream); + + +int +jpc_enc_encodetiledata(jpc_enc_t *enc) { + + assert(enc->tmpstream); if (jpc_enc_encpkts(enc, enc->tmpstream)) { return -1; } return 0; } -void quantize(jas_matrix_t *data, jpc_fix_t stepsize) -{ + + +void +quantize(jas_matrix_t *data, jpc_fix_t stepsize) { + int i; int j; jpc_fix_t t; @@ -1059,8 +1095,11 @@ void quantize(jas_matrix_t *data, jpc_fix_t stepsize) } } -static void calcrdslopes(jpc_enc_cblk_t *cblk) -{ + + +static void +calcrdslopes(jpc_enc_cblk_t *cblk) { + jpc_enc_pass_t *endpasses; jpc_enc_pass_t *pass0; jpc_enc_pass_t *pass1; @@ -1113,10 +1152,12 @@ static void calcrdslopes(jpc_enc_cblk_t *cblk) #if 0 for (pass0 = cblk->passes; pass0 != endpasses; ++pass0) { -if (pass0->rdslope > 0.0) { - fprintf(stderr, "pass %02d nmsedec=%lf dec=%lf end=%d %lf\n", pass0 - cblk->passes, - fixtodbl(pass0->nmsedec), pass0->wmsedec, pass0->end, pass0->rdslope); -} + if (pass0->rdslope > 0.0) { + fprintf(stderr, "pass %02d nmsedec=%lf dec=%lf end=%d %lf\n", + pass0 - cblk->passes, + fixtodbl(pass0->nmsedec), pass0->wmsedec, + pass0->end, pass0->rdslope); + } } #endif } @@ -1196,8 +1237,8 @@ computeLayerSizes(jpc_enc_t * const encP, -static void dump_layeringinfo(jpc_enc_t *enc) -{ +static void +dump_layeringinfo(jpc_enc_t *enc) { jpc_enc_tcmpt_t *tcmpt; uint_fast16_t tcmptno; @@ -1626,12 +1667,15 @@ performTier2Coding(jpc_enc_t * const encP, JAS_DBGLOG(10, ("done doing rateallocation\n")); } + + /*****************************************************************************\ * Tile constructors and destructors. \*****************************************************************************/ -jpc_enc_tile_t *jpc_enc_tile_create(jpc_enc_cp_t *cp, jas_image_t *image, int tileno) -{ +jpc_enc_tile_t * +jpc_enc_tile_create(jpc_enc_cp_t *cp, jas_image_t *image, int tileno) { + jpc_enc_tile_t *tile; uint_fast32_t htileno; uint_fast32_t vtileno; @@ -1733,8 +1777,11 @@ error: return 0; } -void jpc_enc_tile_destroy(jpc_enc_tile_t *tile) -{ + + +void +jpc_enc_tile_destroy(jpc_enc_tile_t *tile) { + jpc_enc_tcmpt_t *tcmpt; uint_fast16_t cmptno; @@ -1754,9 +1801,14 @@ void jpc_enc_tile_destroy(jpc_enc_tile_t *tile) jas_free(tile); } -static jpc_enc_tcmpt_t *tcmpt_create(jpc_enc_tcmpt_t *tcmpt, jpc_enc_cp_t *cp, - jas_image_t *image, jpc_enc_tile_t *tile) -{ + + +static jpc_enc_tcmpt_t * +tcmpt_create(jpc_enc_tcmpt_t * const tcmpt, + jpc_enc_cp_t * const cp, + jas_image_t * const image, + jpc_enc_tile_t * const tile) { + uint_fast16_t cmptno; uint_fast16_t rlvlno; jpc_enc_rlvl_t *rlvl; @@ -1787,15 +1839,15 @@ static jpc_enc_tcmpt_t *tcmpt_create(jpc_enc_tcmpt_t *tcmpt, jpc_enc_cp_t *cp, bry = JPC_CEILDIV(tile->bry, ccp->sampgrdstepy); /* Create a sequence to hold the tile-component sample data. */ - if (!(tcmpt->data = jas_seq2d_create(tlx, tly, brx, bry))) { + tcmpt->data = jas_seq2d_create(tlx, tly, brx, bry); + if (!tcmpt->data) goto error; - } /* Get the image data associated with this tile-component. */ cmpttlx = JPC_CEILDIV(cp->imgareatlx, ccp->sampgrdstepx); cmpttly = JPC_CEILDIV(cp->imgareatly, ccp->sampgrdstepy); if (jas_image_readcmpt(image, cmptno, tlx - cmpttlx, tly - cmpttly, - brx - tlx, bry - tly, tcmpt->data)) { + brx - tlx, bry - tly, tcmpt->data)) { goto error; } @@ -1803,9 +1855,11 @@ static jpc_enc_tcmpt_t *tcmpt_create(jpc_enc_tcmpt_t *tcmpt, jpc_enc_cp_t *cp, tcmpt->qmfbid = cp->tccp.qmfbid; tcmpt->numrlvls = cp->tccp.maxrlvls; tcmpt->numbands = 3 * tcmpt->numrlvls - 2; - if (!(tcmpt->tsfb = jpc_cod_gettsfb(tcmpt->qmfbid, tcmpt->numrlvls - 1))) { + + tcmpt->tsfb = jpc_cod_gettsfb(tcmpt->qmfbid, tcmpt->numrlvls - 1); + + if (!tcmpt->tsfb) goto error; - } for (rlvlno = 0; rlvlno < tcmpt->numrlvls; ++rlvlno) { tcmpt->prcwidthexpns[rlvlno] = cp->tccp.prcwidthexpns[rlvlno]; @@ -1818,17 +1872,19 @@ static jpc_enc_tcmpt_t *tcmpt_create(jpc_enc_tcmpt_t *tcmpt, jpc_enc_cp_t *cp, tcmpt->numstepsizes = tcmpt->numbands; assert(tcmpt->numstepsizes <= JPC_MAXBANDS); - memset(tcmpt->stepsizes, 0, sizeof(tcmpt->numstepsizes * - sizeof(uint_fast16_t))); + memset(tcmpt->stepsizes, 0, + sizeof(tcmpt->numstepsizes * sizeof(uint_fast16_t))); /* Retrieve information about the various bands. */ jpc_tsfb_getbands(tcmpt->tsfb, jas_seq2d_xstart(tcmpt->data), - jas_seq2d_ystart(tcmpt->data), jas_seq2d_xend(tcmpt->data), - jas_seq2d_yend(tcmpt->data), bandinfos); + jas_seq2d_ystart(tcmpt->data), + jas_seq2d_xend(tcmpt->data), + jas_seq2d_yend(tcmpt->data), bandinfos); - if (!(tcmpt->rlvls = jas_malloc(tcmpt->numrlvls * sizeof(jpc_enc_rlvl_t)))) { + tcmpt->rlvls = jas_malloc(tcmpt->numrlvls * sizeof(jpc_enc_rlvl_t)); + if (!tcmpt->rlvls) goto error; - } + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; ++rlvlno, ++rlvl) { rlvl->bands = 0; @@ -1850,8 +1906,11 @@ error: } -static void tcmpt_destroy(jpc_enc_tcmpt_t *tcmpt) -{ + + +static void +tcmpt_destroy(jpc_enc_tcmpt_t *tcmpt) { + jpc_enc_rlvl_t *rlvl; uint_fast16_t rlvlno; @@ -1871,9 +1930,12 @@ static void tcmpt_destroy(jpc_enc_tcmpt_t *tcmpt) } } -static jpc_enc_rlvl_t *rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, - jpc_enc_tcmpt_t *tcmpt, jpc_tsfb_band_t *bandinfos) -{ + + +static jpc_enc_rlvl_t * +rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, + jpc_enc_tcmpt_t *tcmpt, jpc_tsfb_band_t *bandinfos) { + uint_fast16_t rlvlno; uint_fast32_t tlprctlx; uint_fast32_t tlprctly; @@ -1891,14 +1953,18 @@ static jpc_enc_rlvl_t *rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, /* Compute the coordinates of the top-left and bottom-right corners of the tile-component at this resolution. */ - rlvl->tlx = JPC_CEILDIVPOW2(jas_seq2d_xstart(tcmpt->data), tcmpt->numrlvls - - 1 - rlvlno); - rlvl->tly = JPC_CEILDIVPOW2(jas_seq2d_ystart(tcmpt->data), tcmpt->numrlvls - - 1 - rlvlno); - rlvl->brx = JPC_CEILDIVPOW2(jas_seq2d_xend(tcmpt->data), tcmpt->numrlvls - - 1 - rlvlno); - rlvl->bry = JPC_CEILDIVPOW2(jas_seq2d_yend(tcmpt->data), tcmpt->numrlvls - - 1 - rlvlno); + rlvl->tlx = + JPC_CEILDIVPOW2(jas_seq2d_xstart(tcmpt->data), tcmpt->numrlvls - + 1 - rlvlno); + rlvl->tly = + JPC_CEILDIVPOW2(jas_seq2d_ystart(tcmpt->data), tcmpt->numrlvls - + 1 - rlvlno); + rlvl->brx = + JPC_CEILDIVPOW2(jas_seq2d_xend(tcmpt->data), tcmpt->numrlvls - + 1 - rlvlno); + rlvl->bry = + JPC_CEILDIVPOW2(jas_seq2d_yend(tcmpt->data), tcmpt->numrlvls - + 1 - rlvlno); if (rlvl->tlx >= rlvl->brx || rlvl->tly >= rlvl->bry) { rlvl->numhprcs = 0; @@ -1917,8 +1983,10 @@ static jpc_enc_rlvl_t *rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1; rlvl->cbgheightexpn = rlvl->prcheightexpn - 1; } - rlvl->cblkwidthexpn = JAS_MIN(cp->tccp.cblkwidthexpn, rlvl->cbgwidthexpn); - rlvl->cblkheightexpn = JAS_MIN(cp->tccp.cblkheightexpn, rlvl->cbgheightexpn); + rlvl->cblkwidthexpn = + JAS_MIN(cp->tccp.cblkwidthexpn, rlvl->cbgwidthexpn); + rlvl->cblkheightexpn = + JAS_MIN(cp->tccp.cblkheightexpn, rlvl->cbgheightexpn); /* Compute the number of precincts. */ tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); @@ -1926,20 +1994,22 @@ static jpc_enc_rlvl_t *rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, brprcbrx = JPC_CEILTOMULTPOW2(rlvl->brx, rlvl->prcwidthexpn); brprcbry = JPC_CEILTOMULTPOW2(rlvl->bry, rlvl->prcheightexpn); rlvl->numhprcs = JPC_FLOORDIVPOW2(brprcbrx - tlprctlx, rlvl->prcwidthexpn); - rlvl->numvprcs = JPC_FLOORDIVPOW2(brprcbry - tlprctly, rlvl->prcheightexpn); + rlvl->numvprcs = + JPC_FLOORDIVPOW2(brprcbry - tlprctly, rlvl->prcheightexpn); rlvl->numprcs = rlvl->numhprcs * rlvl->numvprcs; - if (!(rlvl->bands = jas_malloc(rlvl->numbands * sizeof(jpc_enc_band_t)))) { + rlvl->bands = jas_malloc(rlvl->numbands * sizeof(jpc_enc_band_t)); + if (!rlvl->bands) goto error; - } + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; - ++bandno, ++band) { + ++bandno, ++band) { band->prcs = 0; band->data = 0; band->rlvl = rlvl; } for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; - ++bandno, ++band) { + ++bandno, ++band) { if (!band_create(band, cp, rlvl, bandinfos)) { goto error; } @@ -1952,8 +2022,11 @@ error: return 0; } -static void rlvl_destroy(jpc_enc_rlvl_t *rlvl) -{ + + +static void +rlvl_destroy(jpc_enc_rlvl_t *rlvl) { + jpc_enc_band_t *band; uint_fast16_t bandno; @@ -1966,9 +2039,12 @@ static void rlvl_destroy(jpc_enc_rlvl_t *rlvl) } } -static jpc_enc_band_t *band_create(jpc_enc_band_t *band, jpc_enc_cp_t *cp, - jpc_enc_rlvl_t *rlvl, jpc_tsfb_band_t *bandinfos) -{ + + +static jpc_enc_band_t * +band_create(jpc_enc_band_t *band, jpc_enc_cp_t *cp, + jpc_enc_rlvl_t *rlvl, jpc_tsfb_band_t *bandinfos) { + uint_fast16_t bandno; uint_fast16_t gblbandno; uint_fast16_t rlvlno; @@ -1989,42 +2065,46 @@ static jpc_enc_band_t *band_create(jpc_enc_band_t *band, jpc_enc_cp_t *cp, bandinfo = &bandinfos[gblbandno]; -if (bandinfo->xstart != bandinfo->xend && bandinfo->ystart != bandinfo->yend) { - if (!(band->data = jas_seq2d_create(0, 0, 0, 0))) { - goto error; + if (bandinfo->xstart != bandinfo->xend && + bandinfo->ystart != bandinfo->yend) { + band->data = jas_seq2d_create(0, 0, 0, 0); + if (!band->data) + goto error; + jas_seq2d_bindsub(band->data, tcmpt->data, bandinfo->locxstart, + bandinfo->locystart, bandinfo->locxend, + bandinfo->locyend); + jas_seq2d_setshift(band->data, bandinfo->xstart, bandinfo->ystart); } - jas_seq2d_bindsub(band->data, tcmpt->data, bandinfo->locxstart, - bandinfo->locystart, bandinfo->locxend, bandinfo->locyend); - jas_seq2d_setshift(band->data, bandinfo->xstart, bandinfo->ystart); -} band->orient = bandinfo->orient; band->analgain = JPC_NOMINALGAIN(cp->tccp.qmfbid, tcmpt->numrlvls, rlvlno, - band->orient); + band->orient); band->numbps = 0; band->absstepsize = 0; band->stepsize = 0; band->synweight = bandinfo->synenergywt; -if (band->data) { - if (!(band->prcs = jas_malloc(rlvl->numprcs * sizeof(jpc_enc_prc_t)))) { - goto error; - } - for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; ++prcno, - ++prc) { - prc->cblks = 0; - prc->incltree = 0; - prc->nlibtree = 0; - prc->savincltree = 0; - prc->savnlibtree = 0; - prc->band = band; - } - for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; ++prcno, - ++prc) { - if (!prc_create(prc, cp, band)) { + if (band->data) { + band->prcs = jas_malloc(rlvl->numprcs * sizeof(jpc_enc_prc_t)); + if (!band->prcs) goto error; + for (prcno = 0, prc = band->prcs; + prcno < rlvl->numprcs; + ++prcno, ++prc) { + prc->cblks = 0; + prc->incltree = 0; + prc->nlibtree = 0; + prc->savincltree = 0; + prc->savnlibtree = 0; + prc->band = band; + } + for (prcno = 0, prc = band->prcs; + prcno < rlvl->numprcs; + ++prcno, ++prc) { + if (!prc_create(prc, cp, band)) { + goto error; + } } } -} return band; @@ -2033,8 +2113,11 @@ error: return 0; } -static void band_destroy(jpc_enc_band_t *band) -{ + + +static void +band_destroy(jpc_enc_band_t *band) { + jpc_enc_prc_t *prc; jpc_enc_rlvl_t *rlvl; uint_fast32_t prcno; @@ -2052,8 +2135,11 @@ static void band_destroy(jpc_enc_band_t *band) } } -static jpc_enc_prc_t *prc_create(jpc_enc_prc_t *prc, jpc_enc_cp_t *cp, jpc_enc_band_t *band) -{ + + +static jpc_enc_prc_t * +prc_create(jpc_enc_prc_t *prc, jpc_enc_cp_t *cp, jpc_enc_band_t *band) { + uint_fast32_t prcno; uint_fast32_t prcxind; uint_fast32_t prcyind; @@ -2081,32 +2167,34 @@ static jpc_enc_prc_t *prc_create(jpc_enc_prc_t *prc, jpc_enc_cp_t *cp, jpc_enc_b rlvl = band->rlvl; tcmpt = rlvl->tcmpt; -rlvlno = rlvl - tcmpt->rlvls; + rlvlno = rlvl - tcmpt->rlvls; prcno = prc - band->prcs; prcxind = prcno % rlvl->numhprcs; prcyind = prcno / rlvl->numhprcs; prc->band = band; -tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); -tlprctly = JPC_FLOORTOMULTPOW2(rlvl->tly, rlvl->prcheightexpn); -if (!rlvlno) { - tlcbgtlx = tlprctlx; - tlcbgtly = tlprctly; -} else { - tlcbgtlx = JPC_CEILDIVPOW2(tlprctlx, 1); - tlcbgtly = JPC_CEILDIVPOW2(tlprctly, 1); -} + tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); + tlprctly = JPC_FLOORTOMULTPOW2(rlvl->tly, rlvl->prcheightexpn); - /* Compute the coordinates of the top-left and bottom-right - corners of the precinct. */ + if (!rlvlno) { + tlcbgtlx = tlprctlx; + tlcbgtly = tlprctly; + } else { + tlcbgtlx = JPC_CEILDIVPOW2(tlprctlx, 1); + tlcbgtly = JPC_CEILDIVPOW2(tlprctly, 1); + } + + /* Compute the coordinates of the top-left and bottom-right corners of the + precinct. + */ cbgtlx = tlcbgtlx + (prcxind << rlvl->cbgwidthexpn); cbgtly = tlcbgtly + (prcyind << rlvl->cbgheightexpn); prc->tlx = JAS_MAX(jas_seq2d_xstart(band->data), cbgtlx); prc->tly = JAS_MAX(jas_seq2d_ystart(band->data), cbgtly); prc->brx = JAS_MIN(jas_seq2d_xend(band->data), cbgtlx + - (1 << rlvl->cbgwidthexpn)); + (1 << rlvl->cbgwidthexpn)); prc->bry = JAS_MIN(jas_seq2d_yend(band->data), cbgtly + - (1 << rlvl->cbgheightexpn)); + (1 << rlvl->cbgheightexpn)); if (prc->tlx < prc->brx && prc->tly < prc->bry) { /* The precinct contains at least one code block. */ @@ -2116,33 +2204,35 @@ if (!rlvlno) { brcblkbrx = JPC_CEILTOMULTPOW2(prc->brx, rlvl->cblkwidthexpn); brcblkbry = JPC_CEILTOMULTPOW2(prc->bry, rlvl->cblkheightexpn); prc->numhcblks = JPC_FLOORDIVPOW2(brcblkbrx - tlcblktlx, - rlvl->cblkwidthexpn); + rlvl->cblkwidthexpn); prc->numvcblks = JPC_FLOORDIVPOW2(brcblkbry - tlcblktly, - rlvl->cblkheightexpn); + rlvl->cblkheightexpn); prc->numcblks = prc->numhcblks * prc->numvcblks; if (!(prc->incltree = jpc_tagtree_create(prc->numhcblks, - prc->numvcblks))) { + prc->numvcblks))) { goto error; } if (!(prc->nlibtree = jpc_tagtree_create(prc->numhcblks, - prc->numvcblks))) { + prc->numvcblks))) { goto error; } if (!(prc->savincltree = jpc_tagtree_create(prc->numhcblks, - prc->numvcblks))) { + prc->numvcblks))) { goto error; } if (!(prc->savnlibtree = jpc_tagtree_create(prc->numhcblks, - prc->numvcblks))) { + prc->numvcblks))) { goto error; } - if (!(prc->cblks = jas_malloc(prc->numcblks * sizeof(jpc_enc_cblk_t)))) { + prc->cblks = jas_malloc(prc->numcblks * sizeof(jpc_enc_cblk_t)); + + if (!prc->cblks) goto error; - } - for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; - ++cblkno, ++cblk) { + for (cblkno = 0, cblk = prc->cblks; + cblkno < prc->numcblks; + ++cblkno, ++cblk) { cblk->passes = 0; cblk->stream = 0; cblk->mqenc = 0; @@ -2150,8 +2240,9 @@ if (!rlvlno) { cblk->flags = 0; cblk->prc = prc; } - for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; - ++cblkno, ++cblk) { + for (cblkno = 0, cblk = prc->cblks; + cblkno < prc->numcblks; + ++cblkno, ++cblk) { if (!cblk_create(cblk, cp, prc)) { goto error; } @@ -2177,8 +2268,11 @@ error: return 0; } -static void prc_destroy(jpc_enc_prc_t *prc) -{ + + +static void +prc_destroy(jpc_enc_prc_t *prc) { + jpc_enc_cblk_t *cblk; uint_fast32_t cblkno; @@ -2203,8 +2297,11 @@ static void prc_destroy(jpc_enc_prc_t *prc) } } -static jpc_enc_cblk_t *cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp, jpc_enc_prc_t *prc) -{ + + +static jpc_enc_cblk_t * +cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp, jpc_enc_prc_t *prc) { + jpc_enc_band_t *band; uint_fast32_t cblktlx; uint_fast32_t cblktly; @@ -2241,18 +2338,22 @@ static jpc_enc_cblk_t *cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp, jpc_e band = prc->band; tlcblktlx = JPC_FLOORTOMULTPOW2(prc->tlx, rlvl->cblkwidthexpn); tlcblktly = JPC_FLOORTOMULTPOW2(prc->tly, rlvl->cblkheightexpn); - cblktlx = JAS_MAX(tlcblktlx + (cblkxind << rlvl->cblkwidthexpn), prc->tlx); - cblktly = JAS_MAX(tlcblktly + (cblkyind << rlvl->cblkheightexpn), prc->tly); - cblkbrx = JAS_MIN(tlcblktlx + ((cblkxind + 1) << rlvl->cblkwidthexpn), - prc->brx); - cblkbry = JAS_MIN(tlcblktly + ((cblkyind + 1) << rlvl->cblkheightexpn), - prc->bry); + cblktlx = + JAS_MAX(tlcblktlx + (cblkxind << rlvl->cblkwidthexpn), prc->tlx); + cblktly = + JAS_MAX(tlcblktly + (cblkyind << rlvl->cblkheightexpn), prc->tly); + cblkbrx = + JAS_MIN(tlcblktlx + ((cblkxind + 1) << rlvl->cblkwidthexpn), prc->brx); + cblkbry = + JAS_MIN(tlcblktly + ((cblkyind + 1) << rlvl->cblkheightexpn), + prc->bry); assert(cblktlx < cblkbrx && cblktly < cblkbry); - if (!(cblk->data = jas_seq2d_create(0, 0, 0, 0))) { + cblk->data = jas_seq2d_create(0, 0, 0, 0); + if (!cblk->data) goto error; - } - jas_seq2d_bindsub(cblk->data, band->data, cblktlx, cblktly, cblkbrx, cblkbry); + jas_seq2d_bindsub(cblk->data, band->data, + cblktlx, cblktly, cblkbrx, cblkbry); return cblk; @@ -2261,8 +2362,11 @@ error: return 0; } -static void cblk_destroy(jpc_enc_cblk_t *cblk) -{ + + +static void +cblk_destroy(jpc_enc_cblk_t *cblk) { + uint_fast16_t passno; jpc_enc_pass_t *pass; if (cblk->passes) { @@ -2286,13 +2390,19 @@ static void cblk_destroy(jpc_enc_cblk_t *cblk) } } -static void pass_destroy(jpc_enc_pass_t *pass) -{ + + +static void +pass_destroy(jpc_enc_pass_t *pass) { + /* XXX - need to free resources here */ } -void jpc_enc_dump(jpc_enc_t *enc) -{ + + +void +jpc_enc_dump(jpc_enc_t *enc) { + jpc_enc_tile_t *tile; jpc_enc_tcmpt_t *tcmpt; jpc_enc_rlvl_t *rlvl; @@ -2358,11 +2468,10 @@ void jpc_enc_dump(jpc_enc_t *enc) -static int jpc_enc_encodemainbody(jpc_enc_t *enc) -{ +static int +jpc_enc_encodemainbody(jpc_enc_t *enc) { + int tileno; - int tilex; - int tiley; int i; jpc_sot_t *sot; jpc_enc_tcmpt_t *comp; @@ -2376,7 +2485,6 @@ static int jpc_enc_encodemainbody(jpc_enc_t *enc) int adjust; int j; int absbandno; - long numbytes; long tilehdrlen; long tilelen; jpc_enc_tile_t *tile; @@ -2398,13 +2506,7 @@ static int jpc_enc_encodemainbody(jpc_enc_t *enc) cp = enc->cp; - /* Avoid compile warnings. */ - numbytes = 0; - for (tileno = 0; tileno < cp->numtiles; ++tileno) { - tilex = tileno % cp->numhtiles; - tiley = tileno / cp->numhtiles; - enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, tileno); if (!enc->curtile) abort(); @@ -2459,7 +2561,6 @@ static int jpc_enc_encodemainbody(jpc_enc_t *enc) } - endcomps = &tile->tcmpts[tile->numtcmpts]; for (cmptno = 0, comp = tile->tcmpts; comp != endcomps; @@ -2544,15 +2645,16 @@ static int jpc_enc_encodemainbody(jpc_enc_t *enc) return -1; } - if (!(enc->tmpstream = jas_stream_memopen(0, 0))) { + enc->tmpstream = jas_stream_memopen(0, 0); + if (!enc->tmpstream) { fprintf(stderr, "cannot open tmp file\n"); return -1; } /* Write the tile header. */ - if (!(enc->mrk = jpc_ms_create(JPC_MS_SOT))) { + enc->mrk = jpc_ms_create(JPC_MS_SOT); + if (!enc->mrk) return -1; - } sot = &enc->mrk->parms.sot; sot->len = 0; sot->tileno = tileno; diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c index 8aa024a9..e1af0f61 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c @@ -1,4 +1,4 @@ -/* + /* * Copyright (c) 1999-2000 Image Power, Inc. and the University of * British Columbia. * Copyright (c) 2001-2002 Michael David Adams. @@ -156,853 +156,872 @@ static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int, /* Encode all of the code blocks associated with the current tile. */ int jpc_enc_enccblks(jpc_enc_t *enc) { - jpc_enc_tcmpt_t *tcmpt; - jpc_enc_tcmpt_t *endcomps; - jpc_enc_rlvl_t *lvl; - jpc_enc_rlvl_t *endlvls; - jpc_enc_band_t *band; - jpc_enc_band_t *endbands; - jpc_enc_cblk_t *cblk; - jpc_enc_cblk_t *endcblks; - int i; - int j; - int mx; - int bmx; - int v; - jpc_enc_tile_t *tile; - uint_fast32_t prcno; - jpc_enc_prc_t *prc; - - tile = enc->curtile; - - endcomps = &tile->tcmpts[tile->numtcmpts]; - for (tcmpt = tile->tcmpts; tcmpt != endcomps; ++tcmpt) { - endlvls = &tcmpt->rlvls[tcmpt->numrlvls]; - for (lvl = tcmpt->rlvls; lvl != endlvls; ++lvl) { - if (!lvl->bands) { - continue; - } - endbands = &lvl->bands[lvl->numbands]; - for (band = lvl->bands; band != endbands; ++band) { - if (!band->data) { - continue; - } - for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) { - if (!prc->cblks) { - continue; - } - bmx = 0; - endcblks = &prc->cblks[prc->numcblks]; - for (cblk = prc->cblks; cblk != endcblks; ++cblk) { - mx = 0; - for (i = 0; i < jas_matrix_numrows(cblk->data); ++i) { - for (j = 0; j < jas_matrix_numcols(cblk->data); ++j) { - v = abs(jas_matrix_get(cblk->data, i, j)); - if (v > mx) { - mx = v; - } - } - } - if (mx > bmx) { - bmx = mx; - } - cblk->numbps = JAS_MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0); - } - - for (cblk = prc->cblks; cblk != endcblks; ++cblk) { - cblk->numimsbs = band->numbps - cblk->numbps; - assert(cblk->numimsbs >= 0); - } - - for (cblk = prc->cblks; cblk != endcblks; ++cblk) { - if (jpc_enc_enccblk(enc, cblk->stream, tcmpt, band, cblk)) { - return -1; - } - } - } - } - } - } - return 0; + jpc_enc_tcmpt_t *tcmpt; + jpc_enc_tcmpt_t *endcomps; + jpc_enc_rlvl_t *lvl; + jpc_enc_rlvl_t *endlvls; + jpc_enc_band_t *band; + jpc_enc_band_t *endbands; + jpc_enc_cblk_t *cblk; + jpc_enc_cblk_t *endcblks; + int i; + int j; + int mx; + int bmx; + int v; + jpc_enc_tile_t *tile; + uint_fast32_t prcno; + jpc_enc_prc_t *prc; + + tile = enc->curtile; + + endcomps = &tile->tcmpts[tile->numtcmpts]; + for (tcmpt = tile->tcmpts; tcmpt != endcomps; ++tcmpt) { + endlvls = &tcmpt->rlvls[tcmpt->numrlvls]; + for (lvl = tcmpt->rlvls; lvl != endlvls; ++lvl) { + if (!lvl->bands) { + continue; + } + endbands = &lvl->bands[lvl->numbands]; + for (band = lvl->bands; band != endbands; ++band) { + if (!band->data) { + continue; + } + for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) { + if (!prc->cblks) { + continue; + } + bmx = 0; + endcblks = &prc->cblks[prc->numcblks]; + for (cblk = prc->cblks; cblk != endcblks; ++cblk) { + mx = 0; + for (i = 0; i < jas_matrix_numrows(cblk->data); ++i) { + for (j = 0; j < jas_matrix_numcols(cblk->data); ++j) { + v = abs(jas_matrix_get(cblk->data, i, j)); + if (v > mx) { + mx = v; + } + } + } + if (mx > bmx) { + bmx = mx; + } + cblk->numbps = JAS_MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0); + } + + for (cblk = prc->cblks; cblk != endcblks; ++cblk) { + cblk->numimsbs = band->numbps - cblk->numbps; + assert(cblk->numimsbs >= 0); + } + + for (cblk = prc->cblks; cblk != endcblks; ++cblk) { + if (jpc_enc_enccblk(enc, cblk->stream, tcmpt, band, cblk)) { + return -1; + } + } + } + } + } + } + return 0; } static int getthebyte(jas_stream_t *in, long off) { - int c; - long oldpos; - oldpos = jas_stream_tell(in); - assert(oldpos >= 0); - jas_stream_seek(in, off, SEEK_SET); - c = jas_stream_peekc(in); - jas_stream_seek(in, oldpos, SEEK_SET); - return c; + int c; + long oldpos; + oldpos = jas_stream_tell(in); + assert(oldpos >= 0); + jas_stream_seek(in, off, SEEK_SET); + c = jas_stream_peekc(in); + jas_stream_seek(in, oldpos, SEEK_SET); + return c; } -/* Encode a single code block. */ -int jpc_enc_enccblk(jpc_enc_t *enc, jas_stream_t *out, jpc_enc_tcmpt_t *tcmpt, jpc_enc_band_t *band, jpc_enc_cblk_t *cblk) -{ - jpc_enc_pass_t *pass; - jpc_enc_pass_t *endpasses; - int bitpos; - int n; - int adjust; - int ret; - int passtype; - int t; - jpc_bitstream_t *bout; - jpc_enc_pass_t *termpass; - jpc_enc_rlvl_t *rlvl; - int vcausal; - int segsym; - int termmode; - int c; - - bout = 0; - rlvl = band->rlvl; - - cblk->stream = jas_stream_memopen(0, 0); - assert(cblk->stream); - cblk->mqenc = jpc_mqenc_create(JPC_NUMCTXS, cblk->stream); - assert(cblk->mqenc); - jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs); - - cblk->numpasses = (cblk->numbps > 0) ? (3 * cblk->numbps - 2) : 0; - if (cblk->numpasses > 0) { - cblk->passes = jas_malloc(cblk->numpasses * sizeof(jpc_enc_pass_t)); - assert(cblk->passes); - } else { - cblk->passes = 0; - } - endpasses = &cblk->passes[cblk->numpasses]; - for (pass = cblk->passes; pass != endpasses; ++pass) { - pass->start = 0; - pass->end = 0; - pass->term = JPC_ISTERMINATED(pass - cblk->passes, 0, cblk->numpasses, (tcmpt->cblksty & JPC_COX_TERMALL) != 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0); - pass->type = JPC_SEGTYPE(pass - cblk->passes, 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0); - pass->lyrno = -1; -if (pass == endpasses - 1) { -assert(pass->term == 1); - pass->term = 1; -} - } - - cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) + 2, - jas_matrix_numcols(cblk->data) + 2); - assert(cblk->flags); - - bitpos = cblk->numbps - 1; - pass = cblk->passes; - n = cblk->numpasses; - while (--n >= 0) { - if (pass->type == JPC_SEG_MQ) { - /* NOP */ - } else { - assert(pass->type == JPC_SEG_RAW); - if (!bout) { - bout = jpc_bitstream_sopen(cblk->stream, "w"); - assert(bout); - } - } +int +jpc_enc_enccblk(jpc_enc_t *enc, jas_stream_t *out, jpc_enc_tcmpt_t *tcmpt, + jpc_enc_band_t *band, jpc_enc_cblk_t *cblk) { +/*---------------------------------------------------------------------------- + Encode a single code block. +-----------------------------------------------------------------------------*/ + jpc_enc_pass_t *pass; + jpc_enc_pass_t *endpasses; + int bitpos; + int n; + int adjust; + int passtype; + int t; + jpc_bitstream_t *bout; + jpc_enc_pass_t *termpass; + int vcausal; + int segsym; + int termmode; + int c; + + bout = 0; + + cblk->stream = jas_stream_memopen(0, 0); + assert(cblk->stream); + cblk->mqenc = jpc_mqenc_create(JPC_NUMCTXS, cblk->stream); + assert(cblk->mqenc); + jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs); + + cblk->numpasses = (cblk->numbps > 0) ? (3 * cblk->numbps - 2) : 0; + if (cblk->numpasses > 0) { + cblk->passes = jas_malloc(cblk->numpasses * sizeof(jpc_enc_pass_t)); + assert(cblk->passes); + } else { + cblk->passes = 0; + } + endpasses = &cblk->passes[cblk->numpasses]; + for (pass = cblk->passes; pass != endpasses; ++pass) { + pass->start = 0; + pass->end = 0; + pass->term = + JPC_ISTERMINATED(pass - cblk->passes, 0, + cblk->numpasses, + (tcmpt->cblksty & JPC_COX_TERMALL) != 0, + (tcmpt->cblksty & JPC_COX_LAZY) != 0); + pass->type = JPC_SEGTYPE(pass - cblk->passes, 0, + (tcmpt->cblksty & JPC_COX_LAZY) != 0); + pass->lyrno = -1; + if (pass == endpasses - 1) { + assert(pass->term == 1); + pass->term = 1; + } + } + + cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) + 2, + jas_matrix_numcols(cblk->data) + 2); + assert(cblk->flags); + + + bitpos = cblk->numbps - 1; + pass = cblk->passes; + n = cblk->numpasses; + while (--n >= 0) { + + if (pass->type == JPC_SEG_MQ) { + /* NOP */ + } else { + assert(pass->type == JPC_SEG_RAW); + if (!bout) { + bout = jpc_bitstream_sopen(cblk->stream, "w"); + assert(bout); + } + } #if 1 - passtype = (pass - cblk->passes + 2) % 3; + passtype = (pass - cblk->passes + 2) % 3; #else - passtype = JPC_PASSTYPE(pass - cblk->passes + 2); + passtype = JPC_PASSTYPE(pass - cblk->passes + 2); #endif - pass->start = jas_stream_tell(cblk->stream); + pass->start = jas_stream_tell(cblk->stream); #if 0 assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream)); #endif - assert(bitpos >= 0); - vcausal = (tcmpt->cblksty & JPC_COX_VSC) != 0; - segsym = (tcmpt->cblksty & JPC_COX_SEGSYM) != 0; - if (pass->term) { - termmode = ((tcmpt->cblksty & JPC_COX_PTERM) ? - JPC_MQENC_PTERM : JPC_MQENC_DEFTERM) + 1; - } else { - termmode = 0; - } - switch (passtype) { - case JPC_SIGPASS: - ret = (pass->type == JPC_SEG_MQ) ? jpc_encsigpass(cblk->mqenc, - bitpos, band->orient, vcausal, cblk->flags, - cblk->data, termmode, &pass->nmsedec) : - jpc_encrawsigpass(bout, bitpos, vcausal, cblk->flags, - cblk->data, termmode, &pass->nmsedec); - break; - case JPC_REFPASS: - ret = (pass->type == JPC_SEG_MQ) ? jpc_encrefpass(cblk->mqenc, - bitpos, vcausal, cblk->flags, cblk->data, termmode, - &pass->nmsedec) : jpc_encrawrefpass(bout, bitpos, - vcausal, cblk->flags, cblk->data, termmode, - &pass->nmsedec); - break; - case JPC_CLNPASS: - assert(pass->type == JPC_SEG_MQ); - ret = jpc_encclnpass(cblk->mqenc, bitpos, band->orient, - vcausal, segsym, cblk->flags, cblk->data, termmode, - &pass->nmsedec); - break; - default: - assert(0); - break; - } - - if (pass->type == JPC_SEG_MQ) { - if (pass->term) { - jpc_mqenc_init(cblk->mqenc); - } - jpc_mqenc_getstate(cblk->mqenc, &pass->mqencstate); - pass->end = jas_stream_tell(cblk->stream); - if (tcmpt->cblksty & JPC_COX_RESET) { - jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs); - } - } else { - if (pass->term) { - if (jpc_bitstream_pending(bout)) { - jpc_bitstream_outalign(bout, 0x2a); - } - jpc_bitstream_close(bout); - bout = 0; - pass->end = jas_stream_tell(cblk->stream); - } else { - pass->end = jas_stream_tell(cblk->stream) + - jpc_bitstream_pending(bout); -/* NOTE - This will not work. need to adjust by # of pending output bytes */ - } - } + assert(bitpos >= 0); + vcausal = (tcmpt->cblksty & JPC_COX_VSC) != 0; + segsym = (tcmpt->cblksty & JPC_COX_SEGSYM) != 0; + if (pass->term) { + termmode = ((tcmpt->cblksty & JPC_COX_PTERM) ? + JPC_MQENC_PTERM : JPC_MQENC_DEFTERM) + 1; + } else { + termmode = 0; + } + switch (passtype) { + case JPC_SIGPASS: + if (pass->type == JPC_SEG_MQ) + jpc_encsigpass(cblk->mqenc, + bitpos, band->orient, vcausal, cblk->flags, + cblk->data, termmode, &pass->nmsedec); + else + jpc_encrawsigpass(bout, bitpos, vcausal, cblk->flags, + cblk->data, termmode, &pass->nmsedec); + break; + case JPC_REFPASS: + if (pass->type == JPC_SEG_MQ) + jpc_encrefpass( + cblk->mqenc, + bitpos, vcausal, cblk->flags, cblk->data, termmode, + &pass->nmsedec); + else + jpc_encrawrefpass(bout, bitpos, + vcausal, cblk->flags, cblk->data, termmode, + &pass->nmsedec); + break; + case JPC_CLNPASS: + assert(pass->type == JPC_SEG_MQ); + jpc_encclnpass( + cblk->mqenc, bitpos, band->orient, + vcausal, segsym, cblk->flags, cblk->data, termmode, + &pass->nmsedec); + break; + default: + assert(false); + break; + } + + if (pass->type == JPC_SEG_MQ) { + if (pass->term) { + jpc_mqenc_init(cblk->mqenc); + } + jpc_mqenc_getstate(cblk->mqenc, &pass->mqencstate); + pass->end = jas_stream_tell(cblk->stream); + if (tcmpt->cblksty & JPC_COX_RESET) { + jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs); + } + } else { + if (pass->term) { + if (jpc_bitstream_pending(bout)) { + jpc_bitstream_outalign(bout, 0x2a); + } + jpc_bitstream_close(bout); + bout = 0; + pass->end = jas_stream_tell(cblk->stream); + } else { + pass->end = jas_stream_tell(cblk->stream) + + jpc_bitstream_pending(bout); + /* NOTE - This will not work. need to adjust by # of pending + output bytes + */ + } + } #if 0 -/* XXX - This assertion fails sometimes when various coding modes are used. -This seems to be harmless, but why does it happen at all? */ -assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream)); + /* XXX - This assertion fails sometimes when various coding modes are used. + This seems to be harmless, but why does it happen at all? */ + assert(jas_stream_tell(cblk->stream) == + jas_stream_getrwcount(cblk->stream)); #endif - pass->wmsedec = jpc_fixtodbl(band->rlvl->tcmpt->synweight) * - jpc_fixtodbl(band->rlvl->tcmpt->synweight) * - jpc_fixtodbl(band->synweight) * - jpc_fixtodbl(band->synweight) * - jpc_fixtodbl(band->absstepsize) * jpc_fixtodbl(band->absstepsize) * - ((double) (1 << bitpos)) * ((double)(1 << bitpos)) * - jpc_fixtodbl(pass->nmsedec); - pass->cumwmsedec = pass->wmsedec; - if (pass != cblk->passes) { - pass->cumwmsedec += pass[-1].cumwmsedec; - } - if (passtype == JPC_CLNPASS) { - --bitpos; - } - ++pass; - } + pass->wmsedec = jpc_fixtodbl(band->rlvl->tcmpt->synweight) * + jpc_fixtodbl(band->rlvl->tcmpt->synweight) * + jpc_fixtodbl(band->synweight) * + jpc_fixtodbl(band->synweight) * + jpc_fixtodbl(band->absstepsize) * jpc_fixtodbl(band->absstepsize) * + ((double) (1 << bitpos)) * ((double)(1 << bitpos)) * + jpc_fixtodbl(pass->nmsedec); + pass->cumwmsedec = pass->wmsedec; + if (pass != cblk->passes) { + pass->cumwmsedec += pass[-1].cumwmsedec; + } + if (passtype == JPC_CLNPASS) { + --bitpos; + } + ++pass; + } #if 0 -dump_passes(cblk->passes, cblk->numpasses, cblk); + dump_passes(cblk->passes, cblk->numpasses, cblk); #endif - n = 0; - endpasses = &cblk->passes[cblk->numpasses]; - for (pass = cblk->passes; pass != endpasses; ++pass) { - if (pass->start < n) { - pass->start = n; - } - if (pass->end < n) { - pass->end = n; - } - if (!pass->term) { - termpass = pass; - while (termpass - pass < cblk->numpasses && - !termpass->term) { - ++termpass; - } - if (pass->type == JPC_SEG_MQ) { - t = (pass->mqencstate.lastbyte == 0xff) ? 1 : 0; - if (pass->mqencstate.ctreg >= 5) { - adjust = 4 + t; - } else { - adjust = 5 + t; - } - pass->end += adjust; - } - if (pass->end > termpass->end) { - pass->end = termpass->end; - } - if ((c = getthebyte(cblk->stream, pass->end - 1)) == EOF) { - abort(); - } - if (c == 0xff) { - ++pass->end; - } - n = JAS_MAX(n, pass->end); - } else { - n = JAS_MAX(n, pass->end); - } - } + n = 0; + endpasses = &cblk->passes[cblk->numpasses]; + for (pass = cblk->passes; pass != endpasses; ++pass) { + if (pass->start < n) { + pass->start = n; + } + if (pass->end < n) { + pass->end = n; + } + if (!pass->term) { + termpass = pass; + while (termpass - pass < cblk->numpasses && + !termpass->term) { + ++termpass; + } + if (pass->type == JPC_SEG_MQ) { + t = (pass->mqencstate.lastbyte == 0xff) ? 1 : 0; + if (pass->mqencstate.ctreg >= 5) { + adjust = 4 + t; + } else { + adjust = 5 + t; + } + pass->end += adjust; + } + if (pass->end > termpass->end) { + pass->end = termpass->end; + } + if ((c = getthebyte(cblk->stream, pass->end - 1)) == EOF) { + abort(); + } + if (c == 0xff) { + ++pass->end; + } + n = JAS_MAX(n, pass->end); + } else { + n = JAS_MAX(n, pass->end); + } + } #if 0 -dump_passes(cblk->passes, cblk->numpasses, cblk); + dump_passes(cblk->passes, cblk->numpasses, cblk); #endif - if (bout) { - jpc_bitstream_close(bout); - } + if (bout) { + jpc_bitstream_close(bout); + } - return 0; + return 0; } -/******************************************************************************\ + + +/*****************************************************************************\ * Code for significance pass. -\******************************************************************************/ +\*****************************************************************************/ -#define sigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, orient, mqenc, vcausalflag) \ +#define sigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, orient, mqenc, vcausalflag) \ { \ - int f; \ - int v; \ - f = *(fp); \ - if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \ - v = (abs(*(dp)) & (one)) ? 1 : 0; \ - jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \ - jpc_mqenc_putbit(mqenc, v); \ - if (v) { \ - *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \ - v = ((*(dp) < 0) ? 1 : 0); \ - jpc_mqenc_setcurctx(mqenc, JPC_GETSCCTXNO(f)); \ - jpc_mqenc_putbit(mqenc, v ^ JPC_GETSPB(f)); \ - JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \ - *(fp) |= JPC_SIG; \ - } \ - *(fp) |= JPC_VISIT; \ - } \ + int f; \ + int v; \ + f = *(fp); \ + if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \ + v = (abs(*(dp)) & (one)) ? 1 : 0; \ + jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \ + jpc_mqenc_putbit(mqenc, v); \ + if (v) { \ + *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \ + v = ((*(dp) < 0) ? 1 : 0); \ + jpc_mqenc_setcurctx(mqenc, JPC_GETSCCTXNO(f)); \ + jpc_mqenc_putbit(mqenc, v ^ JPC_GETSPB(f)); \ + JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \ + *(fp) |= JPC_SIG; \ + } \ + *(fp) |= JPC_VISIT; \ + } \ } static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec) { - int i; - int j; - int one; - int vscanlen; - int width; - int height; - int frowstep; - int drowstep; - int fstripestep; - int dstripestep; - jpc_fix_t *fstripestart; - jpc_fix_t *dstripestart; - jpc_fix_t *fp; - jpc_fix_t *dp; - jpc_fix_t *fvscanstart; - jpc_fix_t *dvscanstart; - int k; - - *nmsedec = 0; - width = jas_matrix_numcols(data); - height = jas_matrix_numrows(data); - frowstep = jas_matrix_rowstep(flags); - drowstep = jas_matrix_rowstep(data); - fstripestep = frowstep << 2; - dstripestep = drowstep << 2; - - one = 1 << (bitpos + JPC_NUMEXTRABITS); - - fstripestart = jas_matrix_getref(flags, 1, 1); - dstripestart = jas_matrix_getref(data, 0, 0); - for (i = height; i > 0; i -= 4, fstripestart += fstripestep, - dstripestart += dstripestep) { - fvscanstart = fstripestart; - dvscanstart = dstripestart; - vscanlen = JAS_MIN(i, 4); - for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { - fp = fvscanstart; - dp = dvscanstart; - k = vscanlen; - - sigpass_step(fp, frowstep, dp, bitpos, one, - nmsedec, orient, mqenc, vcausalflag); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - sigpass_step(fp, frowstep, dp, bitpos, one, - nmsedec, orient, mqenc, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - sigpass_step(fp, frowstep, dp, bitpos, one, - nmsedec, orient, mqenc, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - sigpass_step(fp, frowstep, dp, bitpos, one, - nmsedec, orient, mqenc, 0); - - } - } - - if (term) { - jpc_mqenc_flush(mqenc, term - 1); - } - - return jpc_mqenc_error(mqenc) ? (-1) : 0; + int i; + int j; + int one; + int vscanlen; + int width; + int height; + int frowstep; + int drowstep; + int fstripestep; + int dstripestep; + jpc_fix_t *fstripestart; + jpc_fix_t *dstripestart; + jpc_fix_t *fp; + jpc_fix_t *dp; + jpc_fix_t *fvscanstart; + jpc_fix_t *dvscanstart; + int k; + + *nmsedec = 0; + width = jas_matrix_numcols(data); + height = jas_matrix_numrows(data); + frowstep = jas_matrix_rowstep(flags); + drowstep = jas_matrix_rowstep(data); + fstripestep = frowstep << 2; + dstripestep = drowstep << 2; + + one = 1 << (bitpos + JPC_NUMEXTRABITS); + + fstripestart = jas_matrix_getref(flags, 1, 1); + dstripestart = jas_matrix_getref(data, 0, 0); + for (i = height; i > 0; i -= 4, fstripestart += fstripestep, + dstripestart += dstripestep) { + fvscanstart = fstripestart; + dvscanstart = dstripestart; + vscanlen = JAS_MIN(i, 4); + for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { + fp = fvscanstart; + dp = dvscanstart; + k = vscanlen; + + sigpass_step(fp, frowstep, dp, bitpos, one, + nmsedec, orient, mqenc, vcausalflag); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + sigpass_step(fp, frowstep, dp, bitpos, one, + nmsedec, orient, mqenc, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + sigpass_step(fp, frowstep, dp, bitpos, one, + nmsedec, orient, mqenc, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + sigpass_step(fp, frowstep, dp, bitpos, one, + nmsedec, orient, mqenc, 0); + + } + } + + if (term) { + jpc_mqenc_flush(mqenc, term - 1); + } + + return jpc_mqenc_error(mqenc) ? (-1) : 0; } -#define rawsigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, out, vcausalflag) \ +#define rawsigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, out, vcausalflag) \ { \ - jpc_fix_t f = *(fp); \ - jpc_fix_t v; \ - if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \ - v = (abs(*(dp)) & (one)) ? 1 : 0; \ - if ((jpc_bitstream_putbit((out), v)) == EOF) { \ - return -1; \ - } \ - if (v) { \ - *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \ - v = ((*(dp) < 0) ? 1 : 0); \ - if (jpc_bitstream_putbit(out, v) == EOF) { \ - return -1; \ - } \ - JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \ - *(fp) |= JPC_SIG; \ - } \ - *(fp) |= JPC_VISIT; \ - } \ + jpc_fix_t f = *(fp); \ + jpc_fix_t v; \ + if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \ + v = (abs(*(dp)) & (one)) ? 1 : 0; \ + if ((jpc_bitstream_putbit((out), v)) == EOF) { \ + return -1; \ + } \ + if (v) { \ + *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \ + v = ((*(dp) < 0) ? 1 : 0); \ + if (jpc_bitstream_putbit(out, v) == EOF) { \ + return -1; \ + } \ + JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \ + *(fp) |= JPC_SIG; \ + } \ + *(fp) |= JPC_VISIT; \ + } \ } static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec) { - int i; - int j; - int k; - int one; - int vscanlen; - int width; - int height; - int frowstep; - int drowstep; - int fstripestep; - int dstripestep; - jpc_fix_t *fstripestart; - jpc_fix_t *dstripestart; - jpc_fix_t *fp; - jpc_fix_t *dp; - jpc_fix_t *fvscanstart; - jpc_fix_t *dvscanstart; - - *nmsedec = 0; - width = jas_matrix_numcols(data); - height = jas_matrix_numrows(data); - frowstep = jas_matrix_rowstep(flags); - drowstep = jas_matrix_rowstep(data); - fstripestep = frowstep << 2; - dstripestep = drowstep << 2; - - one = 1 << (bitpos + JPC_NUMEXTRABITS); - - fstripestart = jas_matrix_getref(flags, 1, 1); - dstripestart = jas_matrix_getref(data, 0, 0); - for (i = height; i > 0; i -= 4, fstripestart += fstripestep, - dstripestart += dstripestep) { - fvscanstart = fstripestart; - dvscanstart = dstripestart; - vscanlen = JAS_MIN(i, 4); - for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { - fp = fvscanstart; - dp = dvscanstart; - k = vscanlen; - - rawsigpass_step(fp, frowstep, dp, bitpos, one, - nmsedec, out, vcausalflag); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - - rawsigpass_step(fp, frowstep, dp, bitpos, one, - nmsedec, out, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - - rawsigpass_step(fp, frowstep, dp, bitpos, one, - nmsedec, out, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - - rawsigpass_step(fp, frowstep, dp, bitpos, one, - nmsedec, out, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - - } - } - - if (term) { - jpc_bitstream_outalign(out, 0x2a); - } - - return 0; + int i; + int j; + int k; + int one; + int vscanlen; + int width; + int height; + int frowstep; + int drowstep; + int fstripestep; + int dstripestep; + jpc_fix_t *fstripestart; + jpc_fix_t *dstripestart; + jpc_fix_t *fp; + jpc_fix_t *dp; + jpc_fix_t *fvscanstart; + jpc_fix_t *dvscanstart; + + *nmsedec = 0; + width = jas_matrix_numcols(data); + height = jas_matrix_numrows(data); + frowstep = jas_matrix_rowstep(flags); + drowstep = jas_matrix_rowstep(data); + fstripestep = frowstep << 2; + dstripestep = drowstep << 2; + + one = 1 << (bitpos + JPC_NUMEXTRABITS); + + fstripestart = jas_matrix_getref(flags, 1, 1); + dstripestart = jas_matrix_getref(data, 0, 0); + for (i = height; i > 0; i -= 4, fstripestart += fstripestep, + dstripestart += dstripestep) { + fvscanstart = fstripestart; + dvscanstart = dstripestart; + vscanlen = JAS_MIN(i, 4); + for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { + fp = fvscanstart; + dp = dvscanstart; + k = vscanlen; + + rawsigpass_step(fp, frowstep, dp, bitpos, one, + nmsedec, out, vcausalflag); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + + rawsigpass_step(fp, frowstep, dp, bitpos, one, + nmsedec, out, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + + rawsigpass_step(fp, frowstep, dp, bitpos, one, + nmsedec, out, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + + rawsigpass_step(fp, frowstep, dp, bitpos, one, + nmsedec, out, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + + } + } + + if (term) { + jpc_bitstream_outalign(out, 0x2a); + } + + return 0; } /******************************************************************************\ * Code for refinement pass. \******************************************************************************/ -#define refpass_step(fp, dp, bitpos, one, nmsedec, mqenc, vcausalflag) \ +#define refpass_step(fp, dp, bitpos, one, nmsedec, mqenc, vcausalflag) \ { \ - int v; \ - if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \ - (d) = *(dp); \ - *(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \ - jpc_mqenc_setcurctx((mqenc), JPC_GETMAGCTXNO(*(fp))); \ - v = (abs(d) & (one)) ? 1 : 0; \ - jpc_mqenc_putbit((mqenc), v); \ - *(fp) |= JPC_REFINE; \ - } \ + int v; \ + if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \ + (d) = *(dp); \ + *(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \ + jpc_mqenc_setcurctx((mqenc), JPC_GETMAGCTXNO(*(fp))); \ + v = (abs(d) & (one)) ? 1 : 0; \ + jpc_mqenc_putbit((mqenc), v); \ + *(fp) |= JPC_REFINE; \ + } \ } static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec) { - int i; - int j; - int one; - int vscanlen; - int d; - int width; - int height; - int frowstep; - int drowstep; - int fstripestep; - int dstripestep; - jpc_fix_t *fstripestart; - jpc_fix_t *dstripestart; - jpc_fix_t *fvscanstart; - jpc_fix_t *dvscanstart; - jpc_fix_t *dp; - jpc_fix_t *fp; + int i; + int j; + int one; + int vscanlen; + int d; + int width; + int height; + int frowstep; + int drowstep; + int fstripestep; + int dstripestep; + jpc_fix_t *fstripestart; + jpc_fix_t *dstripestart; + jpc_fix_t *fvscanstart; + jpc_fix_t *dvscanstart; + jpc_fix_t *dp; + jpc_fix_t *fp; int k; - *nmsedec = 0; - width = jas_matrix_numcols(data); - height = jas_matrix_numrows(data); - frowstep = jas_matrix_rowstep(flags); - drowstep = jas_matrix_rowstep(data); - fstripestep = frowstep << 2; - dstripestep = drowstep << 2; - - one = 1 << (bitpos + JPC_NUMEXTRABITS); - - fstripestart = jas_matrix_getref(flags, 1, 1); - dstripestart = jas_matrix_getref(data, 0, 0); - for (i = height; i > 0; i -= 4, fstripestart += fstripestep, - dstripestart += dstripestep) { - fvscanstart = fstripestart; - dvscanstart = dstripestart; - vscanlen = JAS_MIN(i, 4); - for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { - fp = fvscanstart; - dp = dvscanstart; - k = vscanlen; - - refpass_step(fp, dp, bitpos, one, nmsedec, - mqenc, vcausalflag); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - refpass_step(fp, dp, bitpos, one, nmsedec, - mqenc, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - refpass_step(fp, dp, bitpos, one, nmsedec, - mqenc, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - refpass_step(fp, dp, bitpos, one, nmsedec, - mqenc, 0); - - } - } - - if (term) { - jpc_mqenc_flush(mqenc, term - 1); - } - - return jpc_mqenc_error(mqenc) ? (-1) : 0; + *nmsedec = 0; + width = jas_matrix_numcols(data); + height = jas_matrix_numrows(data); + frowstep = jas_matrix_rowstep(flags); + drowstep = jas_matrix_rowstep(data); + fstripestep = frowstep << 2; + dstripestep = drowstep << 2; + + one = 1 << (bitpos + JPC_NUMEXTRABITS); + + fstripestart = jas_matrix_getref(flags, 1, 1); + dstripestart = jas_matrix_getref(data, 0, 0); + for (i = height; i > 0; i -= 4, fstripestart += fstripestep, + dstripestart += dstripestep) { + fvscanstart = fstripestart; + dvscanstart = dstripestart; + vscanlen = JAS_MIN(i, 4); + for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { + fp = fvscanstart; + dp = dvscanstart; + k = vscanlen; + + refpass_step(fp, dp, bitpos, one, nmsedec, + mqenc, vcausalflag); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + refpass_step(fp, dp, bitpos, one, nmsedec, + mqenc, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + refpass_step(fp, dp, bitpos, one, nmsedec, + mqenc, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + refpass_step(fp, dp, bitpos, one, nmsedec, + mqenc, 0); + + } + } + + if (term) { + jpc_mqenc_flush(mqenc, term - 1); + } + + return jpc_mqenc_error(mqenc) ? (-1) : 0; } -#define rawrefpass_step(fp, dp, bitpos, one, nmsedec, out, vcausalflag) \ +#define rawrefpass_step(fp, dp, bitpos, one, nmsedec, out, vcausalflag) \ { \ - jpc_fix_t d; \ - jpc_fix_t v; \ - if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \ - d = *(dp); \ - *(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \ - v = (abs(d) & (one)) ? 1 : 0; \ - if (jpc_bitstream_putbit((out), v) == EOF) { \ - return -1; \ - } \ - *(fp) |= JPC_REFINE; \ - } \ + jpc_fix_t d; \ + jpc_fix_t v; \ + if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \ + d = *(dp); \ + *(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \ + v = (abs(d) & (one)) ? 1 : 0; \ + if (jpc_bitstream_putbit((out), v) == EOF) { \ + return -1; \ + } \ + *(fp) |= JPC_REFINE; \ + } \ } static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec) { - int i; - int j; - int k; - int one; - int vscanlen; - int width; - int height; - int frowstep; - int drowstep; - int fstripestep; - int dstripestep; - jpc_fix_t *fstripestart; - jpc_fix_t *dstripestart; - jpc_fix_t *fvscanstart; - jpc_fix_t *dvscanstart; - jpc_fix_t *dp; - jpc_fix_t *fp; - - *nmsedec = 0; - width = jas_matrix_numcols(data); - height = jas_matrix_numrows(data); - frowstep = jas_matrix_rowstep(flags); - drowstep = jas_matrix_rowstep(data); - fstripestep = frowstep << 2; - dstripestep = drowstep << 2; - - one = 1 << (bitpos + JPC_NUMEXTRABITS); - - fstripestart = jas_matrix_getref(flags, 1, 1); - dstripestart = jas_matrix_getref(data, 0, 0); - for (i = height; i > 0; i -= 4, fstripestart += fstripestep, - dstripestart += dstripestep) { - fvscanstart = fstripestart; - dvscanstart = dstripestart; - vscanlen = JAS_MIN(i, 4); - for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { - fp = fvscanstart; - dp = dvscanstart; - k = vscanlen; - - rawrefpass_step(fp, dp, bitpos, one, nmsedec, - out, vcausalflag); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - rawrefpass_step(fp, dp, bitpos, one, nmsedec, - out, vcausalflag); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - rawrefpass_step(fp, dp, bitpos, one, nmsedec, - out, vcausalflag); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - rawrefpass_step(fp, dp, bitpos, one, nmsedec, - out, vcausalflag); - - } - } - - if (term) { - jpc_bitstream_outalign(out, 0x2a); - } - - return 0; + int i; + int j; + int k; + int one; + int vscanlen; + int width; + int height; + int frowstep; + int drowstep; + int fstripestep; + int dstripestep; + jpc_fix_t *fstripestart; + jpc_fix_t *dstripestart; + jpc_fix_t *fvscanstart; + jpc_fix_t *dvscanstart; + jpc_fix_t *dp; + jpc_fix_t *fp; + + *nmsedec = 0; + width = jas_matrix_numcols(data); + height = jas_matrix_numrows(data); + frowstep = jas_matrix_rowstep(flags); + drowstep = jas_matrix_rowstep(data); + fstripestep = frowstep << 2; + dstripestep = drowstep << 2; + + one = 1 << (bitpos + JPC_NUMEXTRABITS); + + fstripestart = jas_matrix_getref(flags, 1, 1); + dstripestart = jas_matrix_getref(data, 0, 0); + for (i = height; i > 0; i -= 4, fstripestart += fstripestep, + dstripestart += dstripestep) { + fvscanstart = fstripestart; + dvscanstart = dstripestart; + vscanlen = JAS_MIN(i, 4); + for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { + fp = fvscanstart; + dp = dvscanstart; + k = vscanlen; + + rawrefpass_step(fp, dp, bitpos, one, nmsedec, + out, vcausalflag); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + rawrefpass_step(fp, dp, bitpos, one, nmsedec, + out, vcausalflag); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + rawrefpass_step(fp, dp, bitpos, one, nmsedec, + out, vcausalflag); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + rawrefpass_step(fp, dp, bitpos, one, nmsedec, + out, vcausalflag); + + } + } + + if (term) { + jpc_bitstream_outalign(out, 0x2a); + } + + return 0; } /******************************************************************************\ * Code for cleanup pass. \******************************************************************************/ -#define clnpass_step(fp, frowstep, dp, bitpos, one, orient, nmsedec, mqenc, label1, label2, vcausalflag) \ +#define clnpass_step(fp, frowstep, dp, bitpos, one, orient, nmsedec, mqenc, label1, label2, vcausalflag) \ { \ - int f; \ - int v; \ + int f; \ + int v; \ label1 \ - f = *(fp); \ - if (!(f & (JPC_SIG | JPC_VISIT))) { \ - jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \ - v = (abs(*(dp)) & (one)) ? 1 : 0; \ - jpc_mqenc_putbit((mqenc), v); \ - if (v) { \ + f = *(fp); \ + if (!(f & (JPC_SIG | JPC_VISIT))) { \ + jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \ + v = (abs(*(dp)) & (one)) ? 1 : 0; \ + jpc_mqenc_putbit((mqenc), v); \ + if (v) { \ label2 \ - f = *(fp); \ - /* Coefficient is significant. */ \ - *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \ - jpc_mqenc_setcurctx((mqenc), JPC_GETSCCTXNO(f)); \ - v = ((*(dp) < 0) ? 1 : 0); \ - jpc_mqenc_putbit((mqenc), v ^ JPC_GETSPB(f)); \ - JPC_UPDATEFLAGS4((fp), (frowstep), v, vcausalflag); \ - *(fp) |= JPC_SIG; \ - } \ - } \ - *(fp) &= ~JPC_VISIT; \ + f = *(fp); \ + /* Coefficient is significant. */ \ + *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \ + jpc_mqenc_setcurctx((mqenc), JPC_GETSCCTXNO(f)); \ + v = ((*(dp) < 0) ? 1 : 0); \ + jpc_mqenc_putbit((mqenc), v ^ JPC_GETSPB(f)); \ + JPC_UPDATEFLAGS4((fp), (frowstep), v, vcausalflag); \ + *(fp) |= JPC_SIG; \ + } \ + } \ + *(fp) &= ~JPC_VISIT; \ } static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int vcausalflag, int segsymflag, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec) { - int i; - int j; - int k; - int vscanlen; - int v; - int runlen; - jpc_fix_t *fp; - int width; - int height; - jpc_fix_t *dp; - int one; - int frowstep; - int drowstep; - int fstripestep; - int dstripestep; - jpc_fix_t *fstripestart; - jpc_fix_t *dstripestart; - jpc_fix_t *fvscanstart; - jpc_fix_t *dvscanstart; - - *nmsedec = 0; - width = jas_matrix_numcols(data); - height = jas_matrix_numrows(data); - frowstep = jas_matrix_rowstep(flags); - drowstep = jas_matrix_rowstep(data); - fstripestep = frowstep << 2; - dstripestep = drowstep << 2; - - one = 1 << (bitpos + JPC_NUMEXTRABITS); - - fstripestart = jas_matrix_getref(flags, 1, 1); - dstripestart = jas_matrix_getref(data, 0, 0); - for (i = height; i > 0; i -= 4, fstripestart += fstripestep, - dstripestart += dstripestep) { - fvscanstart = fstripestart; - dvscanstart = dstripestart; - vscanlen = JAS_MIN(i, 4); - for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { - - fp = fvscanstart; - if (vscanlen >= 4 && !((*fp) & (JPC_SIG | JPC_VISIT | - JPC_OTHSIGMSK)) && (fp += frowstep, !((*fp) & (JPC_SIG | - JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) & - (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, - !((*fp) & (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK)))) { - dp = dvscanstart; - for (k = 0; k < vscanlen; ++k) { - v = (abs(*dp) & one) ? 1 : 0; - if (v) { - break; - } - dp += drowstep; - } - runlen = k; - if (runlen >= 4) { - jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO); - jpc_mqenc_putbit(mqenc, 0); - continue; - } - jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO); - jpc_mqenc_putbit(mqenc, 1); - jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO); - jpc_mqenc_putbit(mqenc, runlen >> 1); - jpc_mqenc_putbit(mqenc, runlen & 1); - fp = fvscanstart + frowstep * runlen; - dp = dvscanstart + drowstep * runlen; - k = vscanlen - runlen; - switch (runlen) { - case 0: - goto clnpass_partial0; - break; - case 1: - goto clnpass_partial1; - break; - case 2: - goto clnpass_partial2; - break; - case 3: - goto clnpass_partial3; - break; - } - } else { - runlen = 0; - fp = fvscanstart; - dp = dvscanstart; - k = vscanlen; - goto clnpass_full0; - } - clnpass_step(fp, frowstep, dp, bitpos, one, - orient, nmsedec, mqenc, clnpass_full0:, clnpass_partial0:, vcausalflag); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - clnpass_step(fp, frowstep, dp, bitpos, one, - orient, nmsedec, mqenc, ;, clnpass_partial1:, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - clnpass_step(fp, frowstep, dp, bitpos, one, - orient, nmsedec, mqenc, ;, clnpass_partial2:, 0); - if (--k <= 0) { - continue; - } - fp += frowstep; - dp += drowstep; - clnpass_step(fp, frowstep, dp, bitpos, one, - orient, nmsedec, mqenc, ;, clnpass_partial3:, 0); - } - } - - if (segsymflag) { - jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO); - jpc_mqenc_putbit(mqenc, 1); - jpc_mqenc_putbit(mqenc, 0); - jpc_mqenc_putbit(mqenc, 1); - jpc_mqenc_putbit(mqenc, 0); - } - - if (term) { - jpc_mqenc_flush(mqenc, term - 1); - } - - return jpc_mqenc_error(mqenc) ? (-1) : 0; + int i; + int j; + int k; + int vscanlen; + int v; + int runlen; + jpc_fix_t *fp; + int width; + int height; + jpc_fix_t *dp; + int one; + int frowstep; + int drowstep; + int fstripestep; + int dstripestep; + jpc_fix_t *fstripestart; + jpc_fix_t *dstripestart; + jpc_fix_t *fvscanstart; + jpc_fix_t *dvscanstart; + + *nmsedec = 0; + width = jas_matrix_numcols(data); + height = jas_matrix_numrows(data); + frowstep = jas_matrix_rowstep(flags); + drowstep = jas_matrix_rowstep(data); + fstripestep = frowstep << 2; + dstripestep = drowstep << 2; + + one = 1 << (bitpos + JPC_NUMEXTRABITS); + + fstripestart = jas_matrix_getref(flags, 1, 1); + dstripestart = jas_matrix_getref(data, 0, 0); + for (i = height; i > 0; i -= 4, fstripestart += fstripestep, + dstripestart += dstripestep) { + fvscanstart = fstripestart; + dvscanstart = dstripestart; + vscanlen = JAS_MIN(i, 4); + for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) { + + fp = fvscanstart; + if (vscanlen >= 4 && !((*fp) & (JPC_SIG | JPC_VISIT | + JPC_OTHSIGMSK)) && (fp += frowstep, !((*fp) & (JPC_SIG | + JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) & + (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, + !((*fp) & (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK)))) { + dp = dvscanstart; + for (k = 0; k < vscanlen; ++k) { + v = (abs(*dp) & one) ? 1 : 0; + if (v) { + break; + } + dp += drowstep; + } + runlen = k; + if (runlen >= 4) { + jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO); + jpc_mqenc_putbit(mqenc, 0); + continue; + } + jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO); + jpc_mqenc_putbit(mqenc, 1); + jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO); + jpc_mqenc_putbit(mqenc, runlen >> 1); + jpc_mqenc_putbit(mqenc, runlen & 1); + fp = fvscanstart + frowstep * runlen; + dp = dvscanstart + drowstep * runlen; + k = vscanlen - runlen; + switch (runlen) { + case 0: + goto clnpass_partial0; + break; + case 1: + goto clnpass_partial1; + break; + case 2: + goto clnpass_partial2; + break; + case 3: + goto clnpass_partial3; + break; + } + } else { + runlen = 0; + fp = fvscanstart; + dp = dvscanstart; + k = vscanlen; + goto clnpass_full0; + } + clnpass_step(fp, frowstep, dp, bitpos, one, + orient, nmsedec, mqenc, clnpass_full0:, clnpass_partial0:, vcausalflag); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + clnpass_step(fp, frowstep, dp, bitpos, one, + orient, nmsedec, mqenc, ;, clnpass_partial1:, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + clnpass_step(fp, frowstep, dp, bitpos, one, + orient, nmsedec, mqenc, ;, clnpass_partial2:, 0); + if (--k <= 0) { + continue; + } + fp += frowstep; + dp += drowstep; + clnpass_step(fp, frowstep, dp, bitpos, one, + orient, nmsedec, mqenc, ;, clnpass_partial3:, 0); + } + } + + if (segsymflag) { + jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO); + jpc_mqenc_putbit(mqenc, 1); + jpc_mqenc_putbit(mqenc, 0); + jpc_mqenc_putbit(mqenc, 1); + jpc_mqenc_putbit(mqenc, 0); + } + + if (term) { + jpc_mqenc_flush(mqenc, term - 1); + } + + return jpc_mqenc_error(mqenc) ? (-1) : 0; } diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_util.c b/converter/other/jpeg2000/libjasper/jpc/jpc_util.c index ecc4b914..fede2bef 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_util.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_util.c @@ -6,14 +6,14 @@ */ /* __START_OF_JASPER_LICENSE__ - * + * * JasPer Software License - * + * * IMAGE POWER JPEG-2000 PUBLIC LICENSE * ************************************ - * + * * GRANT: - * + * * Permission is hereby granted, free of charge, to any person (the "User") * obtaining a copy of this software and associated documentation, to deal * in the JasPer Software without restriction, including without limitation @@ -21,22 +21,22 @@ * and/or sell copies of the JasPer Software (in source and binary forms), * and to permit persons to whom the JasPer Software is furnished to do so, * provided further that the License Conditions below are met. - * + * * License Conditions * ****************** - * + * * A. Redistributions of source code must retain the above copyright notice, * and this list of conditions, and the following disclaimer. - * + * * B. Redistributions in binary form must reproduce the above copyright * notice, and this list of conditions, and the following disclaimer in * the documentation and/or other materials provided with the distribution. - * + * * C. Neither the name of Image Power, Inc. nor any other contributor * (including, but not limited to, the University of British Columbia and * Michael David Adams) may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * D. User agrees that it shall not commence any action against Image Power, * Inc., the University of British Columbia, Michael David Adams, or any * other contributors (collectively "Licensors") for infringement of any @@ -56,17 +56,17 @@ * trade dress, or service mark rights); and (v) divisions, continuations, * renewals, reissues and extensions of the foregoing (as and to the extent * applicable) now existing, hereafter filed, issued or acquired. - * + * * E. If User commences an infringement action against any Licensor(s) then * such Licensor(s) shall have the right to terminate User's license and * all sublicenses that have been granted hereunder by User to other parties. - * + * * F. This software is for use only in hardware or software products that * are compliant with ISO/IEC 15444-1 (i.e., JPEG-2000 Part 1). No license * or right to this Software is granted for products that do not comply * with ISO/IEC 15444-1. The JPEG-2000 Part 1 standard can be purchased * from the ISO. - * + * * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. * NO USE OF THE JASPER SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER * THIS DISCLAIMER. THE JASPER SOFTWARE IS PROVIDED BY THE LICENSORS AND @@ -106,7 +106,7 @@ * TECHNOLOGY OR PRODUCTS FOR HIGH RISK ACTIVITIES AND WILL ENSURE THAT ITS * CUSTOMERS AND END-USERS OF ITS PRODUCTS ARE PROVIDED WITH A COPY OF THE * NOTICE SPECIFIED IN THIS SECTION. - * + * * __END_OF_JASPER_LICENSE__ */ diff --git a/converter/other/jpeg2000/pamtojpeg2k.c b/converter/other/jpeg2000/pamtojpeg2k.c index 142e452f..4d73316a 100644 --- a/converter/other/jpeg2000/pamtojpeg2k.c +++ b/converter/other/jpeg2000/pamtojpeg2k.c @@ -8,6 +8,7 @@ *****************************************************************************/ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ /* In 2014.09, this was _XOPEN_SOURCE 600, with a comment saying it was @@ -97,7 +98,7 @@ parseCommandLine(int argc, char ** argv, char * modeOpt; unsigned int option_def_index; - + MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ @@ -133,25 +134,25 @@ parseCommandLine(int argc, char ** argv, &numrlvlsSpec, 0); OPTENT3(0, "numgbits", OPT_UINT, &cmdlineP->numgbits, &numgbitsSpec, 0); - OPTENT3(0, "nomct", OPT_FLAG, NULL, + OPTENT3(0, "nomct", OPT_FLAG, NULL, &cmdlineP->nomct, 0); - OPTENT3(0, "sop", OPT_FLAG, NULL, + OPTENT3(0, "sop", OPT_FLAG, NULL, &cmdlineP->sop, 0); - OPTENT3(0, "eph", OPT_FLAG, NULL, + OPTENT3(0, "eph", OPT_FLAG, NULL, &cmdlineP->eph, 0); - OPTENT3(0, "lazy", OPT_FLAG, NULL, + OPTENT3(0, "lazy", OPT_FLAG, NULL, &cmdlineP->lazy, 0); - OPTENT3(0, "termall", OPT_FLAG, NULL, + OPTENT3(0, "termall", OPT_FLAG, NULL, &cmdlineP->termall, 0); - OPTENT3(0, "segsym", OPT_FLAG, NULL, + OPTENT3(0, "segsym", OPT_FLAG, NULL, &cmdlineP->segsym, 0); - OPTENT3(0, "vcausal", OPT_FLAG, NULL, + OPTENT3(0, "vcausal", OPT_FLAG, NULL, &cmdlineP->vcausal, 0); - OPTENT3(0, "pterm", OPT_FLAG, NULL, + OPTENT3(0, "pterm", OPT_FLAG, NULL, &cmdlineP->pterm, 0); - OPTENT3(0, "resetprob", OPT_FLAG, NULL, + OPTENT3(0, "resetprob", OPT_FLAG, NULL, &cmdlineP->resetprob, 0); - OPTENT3(0, "verbose", OPT_FLAG, NULL, + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); OPTENT3(0, "debuglevel", OPT_UINT, &cmdlineP->debuglevel, &debuglevelSpec, 0); @@ -222,7 +223,7 @@ parseCommandLine(int argc, char ** argv, cmdlineP->inputFilename = strdup("-"); /* he wants stdin */ else if (argc - 1 == 1) cmdlineP->inputFilename = strdup(argv[1]); - else + else pm_error("Too many arguments. The only argument accepted\n" "is the input file specification"); @@ -231,7 +232,7 @@ parseCommandLine(int argc, char ** argv, static void -createJasperRaster(struct pam * const inpamP, +createJasperRaster(struct pam * const inpamP, jas_image_t * const jasperP) { /*---------------------------------------------------------------------------- Create the raster in the *jasperP object, reading the raster from the @@ -253,7 +254,7 @@ createJasperRaster(struct pam * const inpamP, if (matrix[plane] == NULL) pm_error("Unable to create matrix for plane %u. " "jas_matrix_create() failed.", plane); - } + } tuplerow = pnm_allocpamrow(inpamP); jasperMaxval = pm_bitstomaxval(pm_maxvaltobits(inpamP->maxval)); @@ -270,7 +271,7 @@ createJasperRaster(struct pam * const inpamP, unsigned int jasperSample; if (oddMaxval) - jasperSample = tuplerow[col][plane] * + jasperSample = tuplerow[col][plane] * jasperMaxval / inpamP->maxval; else jasperSample = tuplerow[col][plane]; @@ -278,16 +279,16 @@ createJasperRaster(struct pam * const inpamP, jas_matrix_set(matrix[plane], 0, col, jasperSample); } } - { + { unsigned int plane; for (plane = 0; plane < inpamP->depth; ++plane) { int rc; - rc = jas_image_writecmpt(jasperP, plane, 0, row, + rc = jas_image_writecmpt(jasperP, plane, 0, row, inpamP->width, 1, matrix[plane]); if (rc != 0) - pm_error("jas_image_writecmpt() of plane %u failed.", + pm_error("jas_image_writecmpt() of plane %u failed.", plane); } } @@ -296,14 +297,14 @@ createJasperRaster(struct pam * const inpamP, pnm_freepamrow(tuplerow); for (plane = 0; plane < inpamP->depth; ++plane) jas_matrix_destroy(matrix[plane]); - + free(matrix); } static void -createJasperImage(struct pam * const inpamP, +createJasperImage(struct pam * const inpamP, jas_image_t ** const jasperPP) { jas_image_cmptparm_t * cmptparms; @@ -321,7 +322,7 @@ createJasperImage(struct pam * const inpamP, cmptparms[plane].prec = pm_maxvaltobits(inpamP->maxval); cmptparms[plane].sgnd = 0; } - *jasperPP = + *jasperPP = jas_image_create(inpamP->depth, cmptparms, JAS_CLRSPC_UNKNOWN); if (*jasperPP == NULL) pm_error("Unable to create jasper image structure. " @@ -340,7 +341,7 @@ convertToJasperImage(struct pam * const inpamP, createJasperImage(inpamP, &jasperP); - if (strncmp(inpamP->tuple_type, "RGB", 3) == 0) { + if (strneq(inpamP->tuple_type, "RGB", 3)) { if (inpamP->depth < 3) pm_error("Input tuple type is RGB*, but depth is only %d. " "It should be at least 3.", inpamP->depth); @@ -354,8 +355,8 @@ convertToJasperImage(struct pam * const inpamP, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B)); } } else { - if (strncmp(inpamP->tuple_type, "GRAYSCALE", 9) == 0 || - strncmp(inpamP->tuple_type, "BLACKANDWHITE", 13) == 0) { + if (strneq(inpamP->tuple_type, "GRAYSCALE", 9) || + strneq(inpamP->tuple_type, "BLACKANDWHITE", 13)) { jas_image_setclrspc(jasperP, JAS_CLRSPC_GENGRAY); jas_image_setcmpttype(jasperP, 0, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y)); @@ -370,7 +371,7 @@ convertToJasperImage(struct pam * const inpamP, static void -writeJpc(jas_image_t * const jasperP, +writeJpc(jas_image_t * const jasperP, struct cmdlineInfo const cmdline, FILE * const ofP) { @@ -382,8 +383,8 @@ writeJpc(jas_image_t * const jasperP, /* Note: ilyrrates is a hack because we're too lazy to properly parse command line options to get the information and then compose - a proper input to Jasper. So the user can screw things up by - specifying garbage for the -ilyrrates option + a proper input to Jasper. So the user can screw things up by + specifying garbage for the -ilyrrates option */ if (strlen(cmdline.ilyrrates) > 0) pm_asprintf(&ilyrratesOpt, "ilyrrates=%s", cmdline.ilyrrates); @@ -409,7 +410,7 @@ writeJpc(jas_image_t * const jasperP, */ rateOpt[0] = '\0'; } - pm_asprintf(&options, + pm_asprintf(&options, "imgareatlx=%u " "imgareatly=%u " "tilegrdtlx=%u " @@ -427,7 +428,7 @@ writeJpc(jas_image_t * const jasperP, "numrlvls=%u " "numgbits=%u " "%s %s %s %s %s %s %s %s %s", - + cmdline.imgareatlx, cmdline.imgareatly, cmdline.tilegrdtlx, @@ -470,8 +471,8 @@ writeJpc(jas_image_t * const jasperP, pm_message("Using Jasper to encode to 'jpc' format with options " "'%s'", options); - rc = jas_image_encode(jasperP, outStreamP, - jas_image_strtofmt((char*)"jpc"), + rc = jas_image_encode(jasperP, outStreamP, + jas_image_strtofmt((char*)"jpc"), (char *)options); if (rc != 0) pm_error("jas_image_encode() failed to encode the JPEG 2000 " @@ -483,11 +484,11 @@ writeJpc(jas_image_t * const jasperP, int rc; rc = jas_stream_close(outStreamP); - + if (rc != 0) pm_error("Failed to close output stream, " "jas_stream_close() rc = %d", rc); - } + } jas_image_clearfmts(); @@ -505,33 +506,33 @@ main(int argc, char **argv) jas_image_t * jasperP; pnm_init(&argc, argv); - + parseCommandLine(argc, argv, &cmdline); - - { + + { int rc; - + rc = jas_init(); if ( rc != 0 ) pm_error("Failed to initialize Jasper library. " "jas_init() returns rc %d", rc ); } - + jas_setdbglevel(cmdline.debuglevel); - + ifP = pm_openr(cmdline.inputFilename); - + pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); - + convertToJasperImage(&inpam, &jasperP); - + writeJpc(jasperP, cmdline, stdout); - + jas_image_destroy(jasperP); pm_close(ifP); pm_close(stdout); - + return 0; } diff --git a/converter/other/jpegtopnm.c b/converter/other/jpegtopnm.c index ab3b18e5..98552c00 100644 --- a/converter/other/jpegtopnm.c +++ b/converter/other/jpegtopnm.c @@ -48,6 +48,7 @@ *****************************************************************************/ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ diff --git a/converter/other/pamtogif.c b/converter/other/pamtogif.c index aabf7fc2..8d432da1 100644 --- a/converter/other/pamtogif.c +++ b/converter/other/pamtogif.c @@ -8,6 +8,7 @@ #include <assert.h> #include <string.h> +#include <stdbool.h> #include "pm_c_util.h" #include "mallocvar.h" @@ -23,7 +24,7 @@ static unsigned int const gifMaxval = 255; static bool verbose; -typedef int stringCode; +typedef unsigned int StringCode; /* A code to be place in the GIF raster. It represents a string of one or more pixels. You interpret this in the context of a current code size. The lower half of the values representable @@ -34,15 +35,11 @@ typedef int stringCode; strings. The mapping between value and the sequence of pixels changes throughout the image. - A variable of this type sometimes has the value -1 instead of - a string code because of cheesy programming. - - Ergo, this data structure must be signed and at least BITS bits - wide plus sign bit. + Ergo, this data structure must be at least BITS bits wide. */ -struct cmap { +struct Cmap { /* This is the information for the GIF colormap (aka palette). */ struct pam pam; @@ -67,7 +64,7 @@ struct cmap { /* A hash table to translate color to GIF colormap index. */ }; -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -79,6 +76,7 @@ struct cmdlineInfo { const char *transparent; /* -transparent option value. NULL if none. */ const char *comment; /* -comment option value; NULL if none */ unsigned int nolzw; /* -nolzw option */ + unsigned int noclear; /* -noclear option */ float aspect; /* -aspect option value (the ratio). */ unsigned int verbose; }; @@ -100,7 +98,7 @@ pamAlphaPlane(struct pam * const pamP) { alphaPlane = 2; else alphaPlane = 0; - + if (alphaPlane >= pamP->depth) pm_error("Tuple type is '%s', but depth (%u) is less than %u", pamP->tuple_type, pamP->depth, alphaPlane + 1); @@ -112,7 +110,7 @@ pamAlphaPlane(struct pam * const pamP) { static void parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { + struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Parse the program arguments (given by argc and argv) into a form the program can deal with more easily -- a cmdline_info structure. @@ -131,30 +129,32 @@ parseCommandLine(int argc, char ** argv, MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "interlace", OPT_FLAG, + OPTENT3(0, "interlace", OPT_FLAG, NULL, &cmdlineP->interlace, 0); - OPTENT3(0, "sort", OPT_FLAG, + OPTENT3(0, "sort", OPT_FLAG, NULL, &cmdlineP->sort, 0); - OPTENT3(0, "nolzw", OPT_FLAG, + OPTENT3(0, "nolzw", OPT_FLAG, NULL, &cmdlineP->nolzw, 0); - OPTENT3(0, "mapfile", OPT_STRING, + OPTENT3(0, "noclear", OPT_FLAG, + NULL, &cmdlineP->noclear, 0); + OPTENT3(0, "mapfile", OPT_STRING, &cmdlineP->mapfile, NULL, 0); - OPTENT3(0, "transparent", OPT_STRING, + OPTENT3(0, "transparent", OPT_STRING, &cmdlineP->transparent, NULL, 0); - OPTENT3(0, "comment", OPT_STRING, + OPTENT3(0, "comment", OPT_STRING, &cmdlineP->comment, NULL, 0); - OPTENT3(0, "alphacolor", OPT_STRING, + OPTENT3(0, "alphacolor", OPT_STRING, &cmdlineP->alphacolor, NULL, 0); - OPTENT3(0, "aspect", OPT_FLOAT, + OPTENT3(0, "aspect", OPT_FLOAT, &cmdlineP->aspect, &aspectSpec, 0); - OPTENT3(0, "verbose", OPT_FLAG, + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); - + /* Set the defaults */ cmdlineP->mapfile = NULL; cmdlineP->transparent = NULL; /* no transparency */ cmdlineP->comment = NULL; /* no comment */ - cmdlineP->alphacolor = "rgb:0/0/0"; + cmdlineP->alphacolor = "rgb:0/0/0"; /* We could say "black" here, but then we depend on the color names database existing. */ @@ -166,15 +166,15 @@ parseCommandLine(int argc, char ** argv, pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - if (argc-1 == 0) + if (argc-1 == 0) cmdlineP->input_filespec = "-"; else if (argc-1 != 1) pm_error("Program takes zero or one argument (filename). You " "specified %d", argc-1); else cmdlineP->input_filespec = argv[1]; - - if (aspectSpec) { + + if (aspectSpec) { if (cmdlineP->aspect < 0.25 || cmdlineP->aspect > 4.21875) pm_error("Invalid -aspect value: %f. " "GIF allows only the range 0.25-4.0 .", @@ -205,10 +205,10 @@ Putword(int const w, FILE * const fp) { static int closestColor(tuple const color, struct pam * const pamP, - struct cmap * const cmapP) { + struct Cmap * const cmapP) { /*---------------------------------------------------------------------------- Return the colormap index of the color in the colormap *cmapP - that is closest to the color 'color', whose format is specified by + that is closest to the color 'color', whose format is specified by *pamP. Also add 'color' to the colormap hash, with the colormap index we @@ -217,7 +217,7 @@ closestColor(tuple const color, -----------------------------------------------------------------------------*/ unsigned int const nComp = pamP->depth >= 3 ? 3 : 1; /* Number of color components (not alpha) in 'color' */ - + unsigned int i; unsigned int imin, dmin; int fits; @@ -234,8 +234,8 @@ closestColor(tuple const color, if (distance < dmin) { dmin = distance; - imin = i; - } + imin = i; + } } pnm_addtotuplehash(pamP, cmapP->tuplehash, color, imin, &fits); @@ -268,16 +268,16 @@ typedef struct { /* A bitbucket for rows we read in order to advance the file position. */ -} rowReader; +} RowReader; -static rowReader * +static RowReader * rowReader_create(struct pam * const pamP, pm_filepos const rasterPos, bool const interlace) { - rowReader * rdrP; + RowReader * rdrP; MALLOCVAR_NOFAIL(rdrP); @@ -298,7 +298,7 @@ rowReader_create(struct pam * const pamP, static void -rowReader_destroy(rowReader * const rdrP) { +rowReader_destroy(RowReader * const rdrP) { pnm_freepamrow(rdrP->discardBuffer); free(rdrP); @@ -307,7 +307,7 @@ rowReader_destroy(rowReader * const rdrP) { static void -rowReaderSkipRows(rowReader * const rdrP, +rowReaderSkipRows(RowReader * const rdrP, unsigned int const rowCount, bool * const eofP) { /*---------------------------------------------------------------------------- @@ -338,7 +338,7 @@ rowReaderSkipRows(rowReader * const rdrP, static void -rowReaderGotoNextInterlaceRow(rowReader * const rdrP) { +rowReaderGotoNextInterlaceRow(RowReader * const rdrP) { /*---------------------------------------------------------------------------- Position reader to the next row in the interlace pattern, assuming it is now positioned immediately after the current row. @@ -351,7 +351,7 @@ rowReaderGotoNextInterlaceRow(rowReader * const rdrP) { MULT4PLUS2: Rows 2, 6, 10, 14, etc. MULT2PLUS1: Rows 1, 3, 5, 7, 9, etc. */ - + switch (rdrP->pass) { case MULT8PLUS0: rowReaderSkipRows(rdrP, 7, &endOfPass); @@ -399,7 +399,7 @@ rowReaderGotoNextInterlaceRow(rowReader * const rdrP) { static void -rowReaderGotoNextStraightRow(rowReader * const rdrP) { +rowReaderGotoNextStraightRow(RowReader * const rdrP) { /*---------------------------------------------------------------------------- Position reader to the next row in a straight, non-interlace pattern, assuming the file is now positioned immediately after the @@ -415,7 +415,7 @@ rowReaderGotoNextStraightRow(rowReader * const rdrP) { static void -rowReader_read(rowReader * const rdrP, +rowReader_read(RowReader * const rdrP, tuple * const tuplerow) { if (rdrP->eof) @@ -424,7 +424,7 @@ rowReader_read(rowReader * const rdrP, pnm_readpamrow(&rdrP->pam, tuplerow); ++rdrP->nextRow; - + if (rdrP->interlace) rowReaderGotoNextInterlaceRow(rdrP); else @@ -437,8 +437,8 @@ static unsigned int gifPixel(struct pam * const pamP, tuple const tuple, unsigned int const alphaPlane, - sample const alphaThreshold, - struct cmap * const cmapP) { + sample const alphaThreshold, + struct Cmap * const cmapP) { /*---------------------------------------------------------------------------- Return as *colorIndexP the colormap index of the tuple 'tuple', whose format is described by *pamP, using colormap *cmapP. @@ -456,7 +456,7 @@ gifPixel(struct pam * const pamP, pnm_lookuptuple(pamP, cmapP->tuplehash, tuple, &found, &colorIndex); - + if (!found) colorIndex = closestColor(tuple, pamP, cmapP); } @@ -493,13 +493,13 @@ writeCommentExtension(FILE * const ofP, unsigned int const maxSegmentSize = 255; const char * segment; - + fputc('!', ofP); /* Identifies an extension */ fputc(0xfe, ofP); /* Identifies a comment */ /* Write it out in segments no longer than 255 characters */ - for (segment = &comment[0]; - segment < comment + strlen(comment); + for (segment = &comment[0]; + segment < comment + strlen(comment); segment += maxSegmentSize) { unsigned int const lengthThisSegment = @@ -546,20 +546,30 @@ writeCommentExtension(FILE * const ofP, */ -static stringCode const maxCodeLimitLzw = (stringCode)1 << BITS; - /* One beyond the largest string code that can exist in GIF */ +static StringCode const maxCodeLimitLzw = (StringCode)1 << BITS; + /* One beyond the largest string code that can exist in GIF */ /* Used only in assertions */ -struct hashTableEntry { - stringCode fcode; /* -1 means unused slot */ - unsigned int ent; -}; +struct HashTableEntry { + /* This is an entry in the string table, which is a hash table. It says + that the string code 'combinedString' represents the string which is + the single pixel 'additionalPixel' appended to 'baseString', where + 'baseString' may represent a multi-pixel string. + */ + bool present; + /* There is an entry here. Following members are meaningless if + not. + */ + StringCode baseString; + StringCode additionalPixel; + StringCode combinedString; +}; /*************************************************************************** -* BYTE OUTPUTTER +* BYTE OUTPUTTER ***************************************************************************/ typedef struct { @@ -568,14 +578,14 @@ typedef struct { /* Number of bytes so far in the current data block */ unsigned char buffer[256]; /* The current data block, under construction */ -} byteBuffer; +} ByteBuffer; -static byteBuffer * +static ByteBuffer * byteBuffer_create(FILE * const fileP) { - byteBuffer * byteBufferP; + ByteBuffer * byteBufferP; MALLOCVAR_NOFAIL(byteBufferP); @@ -588,7 +598,7 @@ byteBuffer_create(FILE * const fileP) { static void -byteBuffer_destroy(byteBuffer * const byteBufferP) { +byteBuffer_destroy(ByteBuffer * const byteBufferP) { free(byteBufferP); } @@ -596,9 +606,9 @@ byteBuffer_destroy(byteBuffer * const byteBufferP) { static void -byteBuffer_flush(byteBuffer * const byteBufferP) { +byteBuffer_flush(ByteBuffer * const byteBufferP) { /*---------------------------------------------------------------------------- - Write the current data block to the output file, then reset the current + Write the current data block to the output file, then reset the current data block to empty. -----------------------------------------------------------------------------*/ if (byteBufferP->count > 0 ) { @@ -613,10 +623,10 @@ byteBuffer_flush(byteBuffer * const byteBufferP) { static void -byteBuffer_flushFile(byteBuffer * const byteBufferP) { - +byteBuffer_flushFile(ByteBuffer * const byteBufferP) { + fflush(byteBufferP->fileP); - + if (ferror(byteBufferP->fileP)) pm_error("error writing output file"); } @@ -624,7 +634,7 @@ byteBuffer_flushFile(byteBuffer * const byteBufferP) { static void -byteBuffer_out(byteBuffer * const byteBufferP, +byteBuffer_out(ByteBuffer * const byteBufferP, unsigned char const c) { /*---------------------------------------------------------------------------- Add a byte to the end of the current data block, and if it is now 255 @@ -638,39 +648,40 @@ byteBuffer_out(byteBuffer * const byteBufferP, /*************************************************************************** -* GIF CODE OUTPUTTER +* GIF CODE OUTPUTTER ***************************************************************************/ typedef struct { - byteBuffer * byteBufferP; + ByteBuffer * byteBufferP; unsigned int initBits; unsigned int nBits; /* Number of bits to put in output for each code */ - stringCode maxCode; /* maximum code, given n_bits */ - stringCode maxCodeLimit; + StringCode maxCode; /* maximum code, given n_bits */ + StringCode maxCodeLimit; /* LZW: One beyond the largest string code that can exist in GIF. Uncompressed: a ceiling to prevent code size from ratcheting up. In either case, output code never reaches this value. - */ + */ unsigned long curAccum; - int curBits; - unsigned int codeCount; - /* Number of codes that have been output to this buffer (doesn't - matter if they have gone out the other side yet or not) since - the last flush (or ever, if no last flush). The main use of this - is debugging -- when something fails, you can see in a debugger - where in the image it was, then set a trap for there. + unsigned int curBits; + unsigned int stringCount; + /* Number of strings that have been output to this buffer (by writing + a string code) since the last flush (or ever, if no last flush). + Note that this counts only strings that go into the buffer; it + doesn't matter if they have gone out the other side yet. The main + use of this is debugging -- when something fails, you can see in a + debugger where in the image it was, then set a trap for there. */ -} codeBuffer; +} CodeBuffer; -static codeBuffer * +static CodeBuffer * codeBuffer_create(FILE * const ofP, unsigned int const initBits, bool const lzw) { - codeBuffer * codeBufferP; + CodeBuffer * codeBufferP; MALLOCVAR_NOFAIL(codeBufferP); @@ -678,11 +689,11 @@ codeBuffer_create(FILE * const ofP, codeBufferP->nBits = codeBufferP->initBits; codeBufferP->maxCode = (1 << codeBufferP->nBits) - 1; codeBufferP->maxCodeLimit = lzw ? - (stringCode)1 << BITS : (stringCode) (1 << codeBufferP->nBits) - 1; + (StringCode)1 << BITS : (StringCode) (1 << codeBufferP->nBits) - 1; codeBufferP->byteBufferP = byteBuffer_create(ofP); codeBufferP->curAccum = 0; codeBufferP->curBits = 0; - codeBufferP->codeCount = 0; + codeBufferP->stringCount = 0; return codeBufferP; } @@ -690,7 +701,7 @@ codeBuffer_create(FILE * const ofP, static void -codeBuffer_destroy(codeBuffer * const codeBufferP) { +codeBuffer_destroy(CodeBuffer * const codeBufferP) { byteBuffer_destroy(codeBufferP->byteBufferP); @@ -700,7 +711,7 @@ codeBuffer_destroy(codeBuffer * const codeBufferP) { static void -codeBuffer_resetCodeSize(codeBuffer * const codeBufferP) { +codeBuffer_resetCodeSize(CodeBuffer * const codeBufferP) { codeBufferP->nBits = codeBufferP->initBits; @@ -712,7 +723,7 @@ codeBuffer_resetCodeSize(codeBuffer * const codeBufferP) { static void -codeBuffer_increaseCodeSize(codeBuffer * const codeBufferP) { +codeBuffer_increaseCodeSize(CodeBuffer * const codeBufferP) { ++codeBufferP->nBits; @@ -721,18 +732,16 @@ codeBuffer_increaseCodeSize(codeBuffer * const codeBufferP) { codeBufferP->maxCode = (1 << codeBufferP->nBits) - 1; } + + static void -codeBuffer_output(codeBuffer * const codeBufferP, - stringCode const code) { +codeBuffer_output(CodeBuffer * const codeBufferP, + StringCode const code) { /*---------------------------------------------------------------------------- Output one GIF code to the file, through the code buffer. The code is represented as N bits in the file -- the lower N bits of 'code'. N is a the current code size of *codeBufferP. - - Id 'code' is the maximum possible code for the current code size - for *codeBufferP, increase that code size (unless it's already - maxed out). -----------------------------------------------------------------------------*/ assert (code <= codeBufferP->maxCode); @@ -752,13 +761,13 @@ codeBuffer_output(codeBuffer * const codeBufferP, codeBufferP->curBits -= 8; } - ++codeBufferP->codeCount; + ++codeBufferP->stringCount; } static void -codeBuffer_flush(codeBuffer * const codeBufferP) { +codeBuffer_flush(CodeBuffer * const codeBufferP) { /* Output the possible partial byte in the buffer */ @@ -768,19 +777,19 @@ codeBuffer_flush(codeBuffer * const codeBufferP) { codeBufferP->curBits = 0; } byteBuffer_flush(codeBufferP->byteBufferP); - + byteBuffer_flushFile(codeBufferP->byteBufferP); if (verbose) pm_message("%u strings of pixels written to file", - codeBufferP->codeCount); - codeBufferP->codeCount = 0; + codeBufferP->stringCount); + codeBufferP->stringCount = 0; } typedef struct { - codeBuffer * codeBufferP; + CodeBuffer * codeBufferP; /* The place to which we write our string codes. Constant. @@ -791,12 +800,16 @@ typedef struct { proper data, but always using one code per pixel, and therefore not effecting any compression and not using the LZW patent. */ + bool noclear; + /* Never put a clear code in the output. Ergo don't recompute the + string table from current input. When the string table fills up, + continue using that table for the rest of the image. + */ unsigned int hsize; /* The number of slots in the hash table. This variable to enhance overall performance by reducing memory use when - encoding smaller gifs. + encoding smaller gifs. */ - unsigned int hshift; /* This is how many bits we shift left a string code in forming the primary hash of the concatenation of that string with another. @@ -810,37 +823,32 @@ typedef struct { represents a string of pixels that is defined by the preceding stream. */ - stringCode clearCode; + StringCode clearCode; /* The code in an LZW stream that means to clear the string dictionary and start fresh. Constant. */ - stringCode eofCode; + StringCode eofCode; /* The code in an LZW stream that means there's no more coming Constant. */ - stringCode initCodeLimit; + StringCode initCodeLimit; /* The value of 'codeLimit' at the start of a block. Constant. */ - - stringCode codeLimit; + StringCode codeLimit; /* One beyond the maximum code possible with the current code size. */ - - struct hashTableEntry * hashTable; - stringCode nextUnusedCode; - /* Numerically next code available to assign to a a multi-pixel - string. Note that codes for multi-pixel strings are in the - upper half of the range of codes, always greater than - 'clearCode'. + struct HashTableEntry * hashTable; + StringCode nextCodeToDefine; + /* The next string code the GIF protocol will define. It will do this + the next time we emit a string code. */ - - stringCode stringSoFar; + StringCode stringSoFar; /* The code for the string we have built so far. This code indicates one or more pixels that we have encoded but not yet output because we're hoping to match an even longer string. @@ -853,16 +861,20 @@ typedef struct { /* We are in the middle of building a string; 'stringSoFar' describes the pixels in it so far. The only time this is false is at the very beginning of the stream. - - Ignored in the non-lzw case. + + Ignored in the non-lzw case. + */ + bool reportedNoclear; + /* We have reported to Standard Error that the string table filled up + and we elected not to clear it. */ -} lzwCompressor; +} LzwCompressor; static unsigned int -nSignificantBits( unsigned int const arg ){ +nSignificantBits(unsigned int const arg){ #if HAVE_GCC_BITCOUNT @@ -880,37 +892,39 @@ nSignificantBits( unsigned int const arg ){ -static lzwCompressor * +static LzwCompressor * lzw_create(FILE * const ofP, unsigned int const initBits, bool const lzw, + bool const noclear, unsigned int const pixelCount) { unsigned int const hsizeTable[] = {257, 521, 1031, 2053, 4099, 5003}; /* If the image has 4096 or fewer pixels we use prime numbers slightly above powers of two between 8 and 12. In this case the hash table never fills up; clear code is never emitted. - + Above that we use a table with 4096 slots plus 20% extra. When this is not enough the clear code is emitted. Because of the extra 20% the table itself never fills up. - + lzw.hsize and lzw.hshift stay constant through the image. Variable hsize is a performance enhancement based on the fact that the encoder never needs more codes than the number of pixels in the image. Typically, the ratio of pixels to codes is around 10:1 to 20:1. - + Logic works with fixed values lzw.hsize=5003 and t=13. */ - lzwCompressor * lzwP; - + LzwCompressor * lzwP; + MALLOCVAR_NOFAIL(lzwP); /* Constants */ - lzwP->lzw = lzw; + lzwP->lzw = lzw; + lzwP->noclear = noclear; lzwP->clearCode = 1 << (initBits - 1); lzwP->eofCode = lzwP->clearCode + 1; @@ -920,18 +934,18 @@ lzw_create(FILE * const ofP, unsigned int const t = MIN(13, MAX(8, nSignificantBits(pixelCount +lzwP->eofCode - 2))); /* Index into hsizeTable */ - + lzwP->hsize = hsizeTable[t-8]; lzwP->hshift = (t == 13 ? 12 : t) - nSignificantBits(MAXCMAPSIZE-1); MALLOCARRAY(lzwP->hashTable, lzwP->hsize); - + if (lzwP->hashTable == NULL) pm_error("Couldn't get memory for %u-entry hash table.", lzwP->hsize); } else { - /* No LZW compression. We don't need a stringcode hash table */ + /* No LZW compression. We don't need a stringcode hash table */ lzwP->hashTable = NULL; lzwP->hsize = 0; } @@ -940,13 +954,15 @@ lzw_create(FILE * const ofP, lzwP->codeBufferP = codeBuffer_create(ofP, initBits, lzw); + lzwP->reportedNoclear = false; + return lzwP; } static void -lzw_destroy(lzwCompressor * const lzwP) { +lzw_destroy(LzwCompressor * const lzwP) { codeBuffer_destroy(lzwP->codeBufferP); @@ -958,24 +974,38 @@ lzw_destroy(lzwCompressor * const lzwP) { static void -lzwHashClear(lzwCompressor * const lzwP) { +lzwHashClear(LzwCompressor * const lzwP) { /* Empty the code table */ unsigned int i; for (i = 0; i < lzwP->hsize; ++i) - lzwP->hashTable[i].fcode = -1; + lzwP->hashTable[i].present = false; + + lzwP->nextCodeToDefine = lzwP->clearCode + 2; +} + + - lzwP->nextUnusedCode = lzwP->clearCode + 2; +static void +lzw_reportNoclear(LzwCompressor * const lzwP) { + + if (verbose && !lzwP->reportedNoclear) { + pm_message("String table filled up. Not starting a new one " + "because of noclear mode"); + lzwP->reportedNoclear = true; + } } static void -lzw_clearBlock(lzwCompressor * const lzwP) { +lzw_clearBlock(LzwCompressor * const lzwP) { /*---------------------------------------------------------------------------- - + Insert a string table clear in the stream. Clear our table and set it up to + start building again, and emit the code to tell the decoder we're doing it + so he can do the same. -----------------------------------------------------------------------------*/ lzwHashClear(lzwP); @@ -989,8 +1019,8 @@ lzw_clearBlock(lzwCompressor * const lzwP) { static void -lzwAdjustCodeSize(lzwCompressor * const lzwP, - stringCode const newCode) { +lzwAdjustCodeSize(LzwCompressor * const lzwP, + StringCode const newCode) { /*---------------------------------------------------------------------------- Assuming we just defined code 'newCode', increase the code size as required so that this code fits. @@ -1011,64 +1041,67 @@ lzwAdjustCodeSize(lzwCompressor * const lzwP, static void -lzwOutputCurrentString(lzwCompressor * const lzwP) { +lzwOutputCurrentString(LzwCompressor * const lzwP) { /*---------------------------------------------------------------------------- Put a code for the currently built-up string in the output stream. - Doing this causes a new string code to be defined (code is - lzwP->nextUnusedCode), so Caller must add that to the hash. If - that code's size is beyond the overall limit, we reset the hash - (which means future codes will start back at the minimum size) and - put a clear code in the stream to tell the decompressor to do the - same. So Caller must add it to the hash _before_ calling us. - - Note that in the non-compressing case, the overall limit is small - enough to prevent us from ever defining string codes; we'll always - reset the hash. - - There's an odd case that always screws up any attempt to make this - code cleaner: At the end of the LZW stream, you have to output the - code for the final string even though you don't have a following - pixel that would make a longer string. So there's nothing to add - to the hash table and no point in allocating a new string code. - But the decompressor doesn't know that we're done, so he allocates - the next string code and may therefore increase his code length. - If we don't do the same, we will write our one last code -- the EOF - code -- in a code length smaller than what the decompressor is - expecting, and he will have a premature end of stream. - - So this subroutine does run for that final code flush and does some - of the motions of defining a new string code, but this subroutine - can't update the hash because in that particular case, there's - nothing to add. + Doing this causes the protocol to define a new string code, defined as the + string we put plus the first pixel of the next string we put. (It almost + seems to violate causality, especially since the next string we put can + legally be the very string code that gets defined here, but it actually + works). + + The code that gets defined is lzwP->nextCodeToDefine. Caller is + responsible for figuring out the value for the code (i.e. what we just said + above) so it can use the code in the future. + + BUT: if the string table has reached its maximum size, issue a clear code + instead to cause the protocol to forget all the defined string coes and + start its table over (so Caller must start its own table over too). + EXCEPT: if we're running in no-clear mode; then we skip the clear code (so + the protocol maintains all the string code definitions and caller will have + to do so as well). + + Note that in the non-compressing case, the overall limit is small enough to + prevent us from ever defining string codes; we'll always issue the clear + code. + + Note that there is a case where Caller can just ignore the fact that we + cause the protocol to define a new string code: where the string we're + outputting is the last one in the stream. In that case, the new string + code we define is irrelevant; it will never be used. -----------------------------------------------------------------------------*/ codeBuffer_output(lzwP->codeBufferP, lzwP->stringSoFar); - if (lzwP->nextUnusedCode < lzwP->codeBufferP->maxCodeLimit) { - /* Allocate the code for the extended string, which Caller - should have already put in the hash so he can use it in the - future. Decompressor knows when it sees the code output - above to define a string on its end too, using the same - string code we do. - */ - stringCode const newCode = lzwP->nextUnusedCode++; - /* This code may be too big to fit in the current code size, in - which case we have to increase the code size (and decompressor - will do the same). + if (lzwP->nextCodeToDefine < lzwP->codeBufferP->maxCodeLimit) { + /* Record that the protocol defined a new string code, to wit + the numerically next one, when we did the output to the stream + above, and adjust the code size if this code is too wide to + fit in the current size. */ + StringCode const newCode = lzwP->nextCodeToDefine++; + lzwAdjustCodeSize(lzwP, newCode); } else { - /* Forget all the strings so far; start building again; tell - decompressor to do the same. - */ - lzw_clearBlock(lzwP); + if (lzwP->noclear) + lzw_reportNoclear(lzwP); + else { + /* Forget all the strings so far; start building again; tell + decompressor to do the same. + */ + lzw_clearBlock(lzwP); + + if (verbose) + pm_message("String table filled up. " + "Clearing and starting over"); + } } } static void -lzw_flush(lzwCompressor * const lzwP) { +lzw_flush(LzwCompressor * const lzwP) { if (lzwP->lzw) lzwOutputCurrentString(lzwP); @@ -1082,8 +1115,8 @@ lzw_flush(lzwCompressor * const lzwP) { static unsigned int -primaryHash(stringCode const baseString, - stringCode const additionalPixel, +primaryHash(StringCode const baseString, + StringCode const additionalPixel, unsigned int const hshift) { unsigned int hash; @@ -1092,71 +1125,76 @@ primaryHash(stringCode const baseString, assert(additionalPixel < MAXCMAPSIZE); hash = (additionalPixel << hshift) ^ baseString; - + return hash; } - + static void -lookupInHash(lzwCompressor * const lzwP, +lookupInHash(LzwCompressor * const lzwP, unsigned int const gifPixel, - stringCode const fcode, bool * const foundP, - unsigned short * const codeP, + StringCode * const codeP, unsigned int * const hashP) { - int disp; + unsigned int disp; /* secondary hash stride (after G. Knott) */ - int i; + unsigned int hash; /* Index into hash table */ - i = primaryHash(lzwP->stringSoFar, gifPixel, lzwP->hshift); - disp = (i == 0) ? 1 : lzwP->hsize - i; - - while (lzwP->hashTable[i].fcode != fcode && - lzwP->hashTable[i].fcode >= 0) { - i -= disp; - if (i < 0) - i += lzwP->hsize; + hash = primaryHash(lzwP->stringSoFar, gifPixel, lzwP->hshift); + assert(hash < lzwP->hsize); + disp = (hash == 0) ? 1 : lzwP->hsize - hash; + + while (lzwP->hashTable[hash].present && + (lzwP->hashTable[hash].baseString != lzwP->stringSoFar || + lzwP->hashTable[hash].additionalPixel != gifPixel)) { + if (hash < disp) + hash += lzwP->hsize; + assert(hash >= disp); + hash -= disp; + assert(hash < lzwP->hsize); } - if (lzwP->hashTable[i].fcode == fcode) { + if (lzwP->hashTable[hash].present) { /* Found fcode in hash table */ - *foundP = TRUE; - *codeP = lzwP->hashTable[i].ent; + *foundP = true; + *codeP = lzwP->hashTable[hash].combinedString; } else { /* Found where it _should_ be (but it's not) with primary hash */ - *foundP = FALSE; - *hashP = i; + *foundP = false; + *hashP = hash; } } static void -lzw_encodePixel(lzwCompressor * const lzwP, +lzw_encodePixel(LzwCompressor * const lzwP, unsigned int const gifPixel) { - bool found; - unsigned short code; - unsigned int hash; - /* Index into hash table where the value should go */ - assert(gifPixel < 256); if (!lzwP->buildingString) { /* Start a new string with just this pixel */ lzwP->stringSoFar = gifPixel; - lzwP->buildingString = TRUE; + lzwP->buildingString = true; } else { - stringCode const fcode = - ((stringCode) gifPixel << BITS) + lzwP->stringSoFar; - /* The encoding of the string we've already recognized plus the - instant pixel, to be looked up in the hash of known strings. + bool found; + /* There's a code for the current string in the string table */ + StringCode code; + /* Existing code for the current string in the string table, if + any + */ + unsigned int hash; + /* Index into hash table where the entry for the new string code + should go; meaningless if we don't need a new string code + (because there's already one in the hash table for the + current string) */ - - lookupInHash(lzwP, gifPixel, fcode, &found, &code, &hash); + + lookupInHash(lzwP, gifPixel, &found, &code, &hash); if (found) /* With this new pixel, it is still a known string; 'code' is @@ -1164,14 +1202,22 @@ lzw_encodePixel(lzwCompressor * const lzwP, */ lzwP->stringSoFar = code; else { - /* It's no longer a known string. Output the code for the - known prefix of the string, thus defining a new string - code for possible later use. Warning: - lzwOutputCurrentString() does more than you think. + /* We've found the longest prefix of the rest of the image for + which we have a string code defined. Output the code for that + prefix, thus defining a new string code in the protocol for + possible later use. The new code is defined as this string + plus the first pixel of the next string. + + But if there aren't any unused string codes left, outputting + our string doesn't define any new string code. */ - lzwP->hashTable[hash].ent = lzwP->nextUnusedCode; - lzwP->hashTable[hash].fcode = fcode; + if (lzwP->nextCodeToDefine < lzwP->codeBufferP->maxCodeLimit) { + lzwP->hashTable[hash].present = true; + lzwP->hashTable[hash].baseString = lzwP->stringSoFar; + lzwP->hashTable[hash].additionalPixel = gifPixel; + lzwP->hashTable[hash].combinedString = lzwP->nextCodeToDefine; + } lzwOutputCurrentString(lzwP); @@ -1184,8 +1230,6 @@ lzw_encodePixel(lzwCompressor * const lzwP, /* - * compress stdin to stdout - * * Algorithm: use open addressing double hashing (no chaining) on the * prefix code / next character combination. We do a variant of Knuth's * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime @@ -1200,23 +1244,25 @@ lzw_encodePixel(lzwCompressor * const lzwP, */ static void -writePixelUncompressed(lzwCompressor * const lzwP, +writePixelUncompressed(LzwCompressor * const lzwP, unsigned int const gifPixel) { - + lzwP->stringSoFar = gifPixel; lzwOutputCurrentString(lzwP); -} +} + static void writeRaster(struct pam * const pamP, - rowReader * const rowReaderP, + RowReader * const rowReaderP, unsigned int const alphaPlane, unsigned int const alphaThreshold, - struct cmap * const cmapP, + struct Cmap * const cmapP, unsigned int const initBits, FILE * const ofP, - bool const lzw) { + bool const lzw, + bool const noclear) { /*---------------------------------------------------------------------------- Write the raster to file 'ofP'. @@ -1228,8 +1274,12 @@ writeRaster(struct pam * const pamP, Write the raster using LZW compression, or uncompressed depending on 'lzw'. + + If 'noclear', don't use any GIF clear codes in the output; i.e. don't + recompute the string table from current input. Once the string table gets + to maximum size, just keep using that table for the rest of the image. -----------------------------------------------------------------------------*/ - lzwCompressor * lzwP; + LzwCompressor * lzwP; tuple * tuplerow; unsigned int nRowsDone; /* Number of rows we have read so far from the the input (the @@ -1237,15 +1287,15 @@ writeRaster(struct pam * const pamP, in case of interlace, this is not the same thing as the row number of the current row. */ - - lzwP = lzw_create(ofP, initBits, lzw, pamP->height * pamP->width); + + lzwP = lzw_create(ofP, initBits, lzw, noclear, pamP->height * pamP->width); tuplerow = pnm_allocpamrow(pamP); lzw_clearBlock(lzwP); nRowsDone = 0; - + while (nRowsDone < pamP->height) { unsigned int col; @@ -1255,14 +1305,14 @@ writeRaster(struct pam * const pamP, unsigned int const colorIndex = gifPixel(pamP, tuplerow[col], alphaPlane, alphaThreshold, cmapP); - + /* The value for the pixel in the GIF image. I.e. the colormap index. */ if (lzw) lzw_encodePixel(lzwP, colorIndex); else - writePixelUncompressed(lzwP, colorIndex); + writePixelUncompressed(lzwP, colorIndex); } ++nRowsDone; } @@ -1272,7 +1322,7 @@ writeRaster(struct pam * const pamP, lzw_flush(lzwP); pnm_freepamrow(tuplerow); - + lzw_destroy(lzwP); } @@ -1280,7 +1330,7 @@ writeRaster(struct pam * const pamP, static void writeGlobalColorMap(FILE * const ofP, - const struct cmap * const cmapP, + const struct Cmap * const cmapP, unsigned int const bitsPerPixel) { /*---------------------------------------------------------------------------- Write out the Global Color Map @@ -1326,16 +1376,16 @@ writeGlobalColorMap(FILE * const ofP, } pnm_freepamtuple(tupleRgb255); } - + static void writeGifHeader(FILE * const ofP, unsigned int const width, - unsigned int const height, - unsigned int const background, + unsigned int const height, + unsigned int const background, unsigned int const bitsPerPixel, - const struct cmap * const cmapP, + const struct Cmap * const cmapP, char const comment[], float const aspect) { @@ -1371,12 +1421,12 @@ writeGifHeader(FILE * const ofP, { int const aspectValue = aspect == 1.0 ? 0 : ROUND(aspect * 64) - 15; - assert(0 <= aspectValue && aspectValue <= 255); + assert(0 <= aspectValue && aspectValue <= 255); fputc(aspectValue, ofP); } writeGlobalColorMap(ofP, cmapP, bitsPerPixel); - if (cmapP->haveTransparent) + if (cmapP->haveTransparent) writeTransparentColorIndexExtension(ofP, cmapP->transparent); if (comment) @@ -1430,15 +1480,16 @@ reportImageInfo(bool const interlace, static void gifEncode(struct pam * const pamP, - FILE * const ofP, + FILE * const ofP, pm_filepos const rasterPos, bool const gInterlace, - int const background, + int const background, unsigned int const bitsPerPixel, - struct cmap * const cmapP, + struct Cmap * const cmapP, char const comment[], float const aspect, - bool const lzw) { + bool const lzw, + bool const noclear) { unsigned int const leftOffset = 0; unsigned int const topOffset = 0; @@ -1453,14 +1504,14 @@ gifEncode(struct pam * const pamP, unsigned int const alphaPlane = pamAlphaPlane(pamP); - rowReader * rowReaderP; + RowReader * rowReaderP; reportImageInfo(gInterlace, background, bitsPerPixel); if (pamP->width > 65535) pm_error("Image width %u too large for GIF format. (Max 65535)", pamP->width); - + if (pamP->height > 65535) pm_error("Image height %u too large for GIF format. (Max 65535)", pamP->height); @@ -1479,7 +1530,7 @@ gifEncode(struct pam * const pamP, /* Write the actual raster */ writeRaster(pamP, rowReaderP, alphaPlane, alphaThreshold, - cmapP, initCodeSize + 1, ofP, lzw); + cmapP, initCodeSize + 1, ofP, lzw, noclear); rowReader_destroy(rowReaderP); @@ -1493,7 +1544,7 @@ gifEncode(struct pam * const pamP, static void -reportTransparent(struct cmap * const cmapP) { +reportTransparent(struct Cmap * const cmapP) { if (verbose) { if (cmapP->haveTransparent) { @@ -1511,10 +1562,10 @@ reportTransparent(struct cmap * const cmapP) { static void -computeTransparent(char const colorarg[], +computeTransparent(char const colorarg[], bool const usingFakeTrans, unsigned int const fakeTransparent, - struct cmap * const cmapP) { + struct Cmap * const cmapP) { /*---------------------------------------------------------------------------- Figure out the color index (index into the colormap) of the color that is to be transparent in the GIF. @@ -1546,7 +1597,7 @@ computeTransparent(char const colorarg[], tuple transcolor; int found; int colorindex; - + if (colorarg[0] == '=') { colorspec = &colorarg[1]; exact = TRUE; @@ -1558,7 +1609,7 @@ computeTransparent(char const colorarg[], transcolor = pnm_parsecolor(colorspec, cmapP->pam.maxval); pnm_lookuptuple(&cmapP->pam, cmapP->tuplehash, transcolor, &found, &colorindex); - + if (found) { cmapP->haveTransparent = TRUE; cmapP->transparent = colorindex; @@ -1602,7 +1653,7 @@ sortCompareColor(const void * const entry1P, struct tupleint * const * const tupleint1PP = entry1P; struct tupleint * const * const tupleint2PP = entry2P; - return (sortOrderColor((*tupleint1PP)->tuple) + return (sortOrderColor((*tupleint1PP)->tuple) - sortOrderColor((*tupleint2PP)->tuple)); } @@ -1640,15 +1691,15 @@ sortTupletable(struct pam * const mapPamP, if (mapPamP->depth < 3) qsort(tuplefreq, colors, sizeof(tuplefreq[0]), sortCompareGray); else - qsort(tuplefreq, colors, sizeof(tuplefreq[0]), sortCompareColor); + qsort(tuplefreq, colors, sizeof(tuplefreq[0]), sortCompareColor); } static void -addToColormap(struct cmap * const cmapP, - const char * const colorspec, +addToColormap(struct Cmap * const cmapP, + const char * const colorspec, unsigned int * const newIndexP) { /*---------------------------------------------------------------------------- Add a new entry to the colormap. Make the color that specified by @@ -1685,7 +1736,7 @@ addToColormap(struct cmap * const cmapP, static void colormapFromFile(char const filespec[], unsigned int const maxcolors, - tupletable * const tupletableP, + tupletable * const tupletableP, struct pam * const mapPamP, unsigned int * const colorCountP) { /*---------------------------------------------------------------------------- @@ -1703,13 +1754,13 @@ colormapFromFile(char const filespec[], pm_close(mapfileP); pm_message("computing other colormap ..."); - - *tupletableP = + + *tupletableP = pnm_computetuplefreqtable(mapPamP, colors, maxcolors, &colorCount); *colorCountP = colorCount; - pnm_freepamarray(colors, mapPamP); + pnm_freepamarray(colors, mapPamP); } @@ -1717,7 +1768,7 @@ colormapFromFile(char const filespec[], static void readAndValidateColormapFromFile(char const filename[], unsigned int const maxcolors, - tupletable * const tuplefreqP, + tupletable * const tuplefreqP, struct pam * const mapPamP, unsigned int * const colorCountP, unsigned int const nInputComp, @@ -1753,7 +1804,7 @@ computeColormapBw(struct pam * const pamP, $ pbmmake -w 600 400 | pamtogif -sort > canvas.gif -----------------------------------------------------------------------------*/ tupletable const colormap = pnm_alloctupletable(pamP, 2); - + *mapPamP = *pamP; mapPamP->depth = 1; @@ -1761,12 +1812,12 @@ computeColormapBw(struct pam * const pamP, colormap[0]->tuple[0] = PAM_BLACK; colormap[1]->value = 1; colormap[1]->tuple[0] = PAM_BW_WHITE; - + *tuplefreqP = colormap; *colorCountP = 2; } - - + + static void computeColormapFromInput(struct pam * const pamP, @@ -1775,7 +1826,7 @@ computeColormapFromInput(struct pam * const pamP, struct pam * const mapPamP, unsigned int * const colorCountP, tupletable * const tuplefreqP) { - + tupletable tuplefreq; pm_message("computing colormap..."); @@ -1842,9 +1893,9 @@ computeLibnetpbmColormap(struct pam * const pamP, pamP->height * pamP->width > 1) computeColormapBw(pamP, mapPamP, &colorCount, &tuplefreq); else - computeColormapFromInput(pamP, maxcolors, nInputComp, + computeColormapFromInput(pamP, maxcolors, nInputComp, mapPamP, &colorCount, &tuplefreq); - + if (tuplefreq == NULL) pm_error("too many colors - try doing a 'pnmquant %u'", maxcolors); @@ -1870,10 +1921,10 @@ computeLibnetpbmColormap(struct pam * const pamP, static void -destroyCmap(struct cmap * const cmapP) { +destroyCmap(struct Cmap * const cmapP) { unsigned int colorIndex; - + for (colorIndex = 0; colorIndex < cmapP->cmapSize; ++colorIndex) pnm_freepamtuple(cmapP->color[colorIndex]); @@ -1884,41 +1935,41 @@ destroyCmap(struct cmap * const cmapP) { int main(int argc, char *argv[]) { - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; FILE * ifP; struct pam pam; unsigned int bitsPerPixel; pm_filepos rasterPos; - struct cmap cmap; + struct Cmap cmap; /* The colormap, with all its accessories */ unsigned int fakeTransparent; /* colormap index of the fake transparency color we're using to implement the alpha mask. Undefined if we're not doing an alpha mask. */ - + pnm_init(&argc, argv); - + parseCommandLine(argc, argv, &cmdline); - + verbose = cmdline.verbose; - + ifP = pm_openr_seekable(cmdline.input_filespec); - + pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type)); - + pm_tell2(ifP, &rasterPos, sizeof(rasterPos)); - - computeLibnetpbmColormap(&pam, !!pamAlphaPlane(&pam), cmdline.mapfile, + + computeLibnetpbmColormap(&pam, !!pamAlphaPlane(&pam), cmdline.mapfile, cmap.color, &cmap.tuplehash, &cmap.pam, &cmap.cmapSize, cmdline.sort); - + assert(cmap.pam.maxval == pam.maxval); if (pamAlphaPlane(&pam)) { - /* Add a fake entry to the end of the colormap for transparency. - Make its color black. + /* Add a fake entry to the end of the colormap for transparency. + Make its color black. */ addToColormap(&cmap, cmdline.alphacolor, &fakeTransparent); } @@ -1931,13 +1982,13 @@ main(int argc, char *argv[]) { /* All set, let's do it. */ gifEncode(&pam, stdout, rasterPos, cmdline.interlace, 0, bitsPerPixel, &cmap, cmdline.comment, - cmdline.aspect, !cmdline.nolzw); - + cmdline.aspect, !cmdline.nolzw, cmdline.noclear); + destroyCmap(&cmap); pm_close(ifP); pm_close(stdout); - + return 0; } @@ -1955,21 +2006,21 @@ main(int argc, char *argv[]) { JPEG Group's djpeg on 2001.09.29. In 2006.12 the output subroutines were rewritten; now no uncompressed output subroutines are derived from the Independent JPEG Group's source code. - + 2007.01 Changed sort routine to qsort. (afu) 2007.03 Implemented variable hash table size, PBM color table shortcut and "-aspect" command line option. (afu) - + Copyright (C) 1989 by Jef Poskanzer. - + 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. - + The Graphics Interchange Format(c) is the Copyright property of CompuServe Incorporated. GIF(sm) is a Service Mark property of CompuServe Incorporated. diff --git a/converter/other/pamtopdbimg.c b/converter/other/pamtopdbimg.c index 6454292e..ce2f7659 100644 --- a/converter/other/pamtopdbimg.c +++ b/converter/other/pamtopdbimg.c @@ -38,6 +38,7 @@ #include "mallocvar.h" #include "nstring.h" #include "shhopt.h" +#include "runlength.h" #include "pam.h" #include "ipdb.h" @@ -128,6 +129,8 @@ parseCommandLine(int argc, const char ** argv, cmdlineP->inputFileName = argv[1]; else pm_error("Program takes at most one argument: input file name"); + + free(option_def); } @@ -238,91 +241,6 @@ textWrite(TEXT * const textP, -typedef struct { - unsigned int match; - uint8_t buf[128]; - int mode; - size_t len; - size_t used; - uint8_t * p; -} RLE; -#define MODE_MATCH 0 -#define MODE_LIT 1 -#define MODE_NONE 2 - -#define reset(r) { \ - (r)->match = 0xffff; \ - (r)->mode = MODE_NONE; \ - (r)->len = 0; \ - } - - - -static void -putMatch(RLE * const rleP, - size_t const n) { - - *rleP->p++ = 0x80 + n - 1; - *rleP->p++ = rleP->match; - rleP->used += 2; - reset(rleP); -} - - - -static void -putLit(RLE * const rleP, - size_t const n) { - - *rleP->p++ = n - 1; - rleP->p = (uint8_t *)memcpy(rleP->p, rleP->buf, n) + n; - rleP->used += n + 1; - reset(rleP); -} - - - -static size_t -compress(const uint8_t * const inData, - size_t const n_in, - uint8_t * const out) { - - static void (*put[])(RLE *, size_t) = {putMatch, putLit}; - RLE rle; - size_t i; - const uint8_t * p; - - MEMSZERO(&rle); - rle.p = out; - reset(&rle); - - for (i = 0, p = &inData[0]; i < n_in; ++i, ++p) { - if (*p == rle.match) { - if (rle.mode == MODE_LIT && rle.len > 1) { - putLit(&rle, rle.len - 1); - ++rle.len; - rle.match = *p; - } - rle.mode = MODE_MATCH; - ++rle.len; - } else { - if (rle.mode == MODE_MATCH) - putMatch(&rle, rle.len); - rle.mode = MODE_LIT; - rle.match = *p; - rle.buf[rle.len++] = *p; - } - if (rle.len == 128) - put[rle.mode](&rle, rle.len); - } - if (rle.len != 0) - put[rle.mode](&rle, rle.len); - - return rle.used; -} - - - static void compressIfRequired(IPDB * const pdbP, int const comp, @@ -334,38 +252,29 @@ compressIfRequired(IPDB * const pdbP, *compressedSizeP = ipdb_img_size(pdbP->i); } else { int const uncompressedSz = ipdb_img_size(pdbP->i); - - /* Allocate for the worst case. */ - size_t const allocSz = (3 * uncompressedSz + 2)/2; - uint8_t * data; - - data = pdbP->i->data; + unsigned char * outbuf; + size_t compressedSz; - MALLOCARRAY(data, allocSz); - - if (data == NULL) - pm_error("Could not get %lu bytes of memory to decompress", - (unsigned long)allocSz); - else { - size_t compressedSz; - compressedSz = compress(pdbP->i->data, uncompressedSz, data); - if (comp == IPDB_COMPMAYBE && compressedSz >= uncompressedSz) { - /* Return the uncompressed data */ - free(data); - *compressedDataP = pdbP->i->data; - *compressedSizeP = uncompressedSz; - } else { - pdbP->i->compressed = TRUE; - if (pdbP->i->type == IMG_GRAY16) - pdbP->i->version = 9; - else - pdbP->i->version = 1; - if (pdbP->t != NULL) - pdbP->t->r->offset -= uncompressedSz - compressedSz; - *compressedDataP = data; - *compressedSizeP = compressedSz; - } + pm_rlenc_allocoutbuf(&outbuf, uncompressedSz, PM_RLE_PALMPDB); + + pm_rlenc_compressbyte(pdbP->i->data, outbuf, PM_RLE_PALMPDB, + uncompressedSz, &compressedSz); + if (comp == IPDB_COMPMAYBE && compressedSz >= uncompressedSz) { + /* Return the uncompressed data */ + free(outbuf); + *compressedDataP = pdbP->i->data; + *compressedSizeP = uncompressedSz; + } else { + pdbP->i->compressed = TRUE; + if (pdbP->i->type == IMG_GRAY16) + pdbP->i->version = 9; + else + pdbP->i->version = 1; + if (pdbP->t != NULL) + pdbP->t->r->offset -= uncompressedSz - compressedSz; + *compressedDataP = outbuf; + *compressedSizeP = compressedSz; } } } @@ -742,6 +651,14 @@ readtxt(IPDB * const pdbP, pm_error("stat of '%s' failed, errno = %d (%s)", noteFileName, errno, strerror(errno)); + /* The maximum size of a memory block that a Palm can allocate is 64K. + Abort with error if specified note file is any larger. + */ + + if (st.st_size + 1 >= 65535) + pm_error("Note file is too large: %lu bytes", + (unsigned long) st.st_size); + fP = pm_openr(noteFileName); MALLOCARRAY(fileContent, st.st_size + 1); @@ -758,6 +675,8 @@ readtxt(IPDB * const pdbP, pm_close(fP); + fileContent[st.st_size] = 0x00; /* add terminating NUL char */ + /* Chop of trailing newlines */ for (n = strlen(fileContent) - 1; n >= 0 && fileContent[n] == '\n'; --n) fileContent[n] = '\0'; @@ -787,6 +706,9 @@ main(int argc, const char **argv) { case MAYBE: comp = IPDB_COMPMAYBE; break; } + if (strlen(cmdline.title) > 31) + pm_error("Title too long. Max length is 31 characters."); + pdbP = ipdb_alloc(cmdline.title); if (pdbP == NULL) diff --git a/converter/other/pamtopng.c b/converter/other/pamtopng.c index fdeb6582..a323844f 100644 --- a/converter/other/pamtopng.c +++ b/converter/other/pamtopng.c @@ -1,21 +1,8 @@ -/* -** read a PNM/PAM image and produce a Portable Network Graphics (PNG) file -** -** derived from pnmtorast.c by Jef Poskanzer and pamrgbatopng.c by Bryan -** Henderson <bryanh@giraffe-data.com> and probably some other sources -** -** Copyright (C) 1995-1998 by Alexander Lehmann <alex@hal.rhein-main.de> -** and Willem van Schaik <willem@schaik.com> -** Copyright (C) 1999,2001 by Greg Roelofs <newt@pobox.com> -** Copyright (C) 2015 by 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. -*/ +/*============================================================================= + pamtopng +=============================================================================== + Read a Netpbm image and produce a PNG (Portable Network Graphics) image. +=============================================================================*/ /* This Netpbm program pamtopng was derived in 2015 from the Netpbm program @@ -29,18 +16,19 @@ had become rather complex. This program is roughly 1/3 the size of pnmtopng.c that it replaces. - - In 1995 bandwith was limited and therefore filesize had to be kept + - In 1995, bandwith was limited and therefore filesize had to be kept small. The original program tried to optimize for that by applying - many "clever tricks". Today that isn't an issue anymore, so gone + many "clever tricks". Today that isn't an issue anymore, so gone are filters, palettes, etc. Also, image conversions were removed, because those should be done with other NetPBM tools. - Add ability to create iTXt (international language) chunks. */ - +#include <assert.h> #include <stdio.h> #include <stdlib.h> +#include <time.h> #include <png.h> /* setjmp.h needs to be included after png.h */ #include <setjmp.h> @@ -61,6 +49,7 @@ static bool verbose; struct CmdlineInfo { const char * inputFileName; unsigned int verbose; + unsigned int interlace; unsigned int transparencySpec; const char * transparency; unsigned int chromaSpec; @@ -88,7 +77,7 @@ parseChromaOpt(const char * const chromaOpt, struct pngx_chroma * const chromaP) { int count; - + count = sscanf(chromaOpt, "%f %f %f %f %f %f %f %f", &chromaP->wx, &chromaP->wy, &chromaP->rx, &chromaP->ry, @@ -107,7 +96,7 @@ parseChromaOpt(const char * const chromaOpt, static void parseSrgbintentOpt(const char * const srgbintentOpt, pngx_srgbIntent * const srgbintentP) { - + if (streq(srgbintentOpt, "perceptual")) *srgbintentP = PNGX_PERCEPTUAL; else if (streq(srgbintentOpt, "relativecolorimetric")) @@ -145,7 +134,7 @@ parseTimeOpt(const char * const timeOpt, if (count != 6) pm_error("Invalid value for -time '%s'. It should have " "the form [yy]yy-mm-dd hh:mm:ss.", timeOpt); - + if (year < 0) pm_error("Year is negative in -time value '%s'", timeOpt); if (year > 9999) @@ -192,7 +181,7 @@ static void parseCommandLine (int argc, const char ** argv, struct CmdlineInfo * const cmdlineP) { - + optEntry * option_def; optStruct3 opt; unsigned int option_def_index = 0; /* incremented by OPTENT3 */ @@ -205,6 +194,8 @@ parseCommandLine (int argc, OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); + OPTENT3(0, "interlace", OPT_FLAG, NULL, + &cmdlineP->interlace, 0); OPTENT3(0, "transparency", OPT_STRING, &cmdlineP->transparency, &cmdlineP->transparencySpec, 0); OPTENT3(0, "chroma", OPT_STRING, &chroma, @@ -239,7 +230,7 @@ parseCommandLine (int argc, if (cmdlineP->timeSpec) parseTimeOpt(time, &cmdlineP->time); - + /* get the input-file or stdin pipe */ if (argc-1 < 1) cmdlineP->inputFileName = "-"; @@ -256,7 +247,7 @@ parseCommandLine (int argc, static png_byte colorTypeFromInputType(const struct pam * const pamP) { /*---------------------------------------------------------------------------- - Analyse the Netpbm image for color-type and bit-depth + Analyze the Netpbm image for color-type and bit-depth -----------------------------------------------------------------------------*/ png_byte retval; @@ -286,7 +277,7 @@ colorTypeFromInputType(const struct pam * const pamP) { if (pamP->depth == 2) retval = PNG_COLOR_TYPE_GRAY_ALPHA; else - pm_error("Input tupel type is GRAYSCALE_ALPHA, " + pm_error("Input tuple type is GRAYSCALE_ALPHA, " "but number of planes is %u instread of 2", pamP->depth); } else if (strneq(pamP->tuple_type, "GRAYSCALE", 9)) { @@ -385,6 +376,8 @@ sigBitsFmImgType(unsigned int const pnmBitDepth, retval.gray = pnmBitDepth; retval.alpha = pnmBitDepth; break; + default: + assert(false); } } else { /* PNG can (so presumably will) use original bit depth */ @@ -404,7 +397,7 @@ doTrnsChunk(const struct pam * const pamP, struct pngx * const pngxP, const char * const trans) { - if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA || + if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA || pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA) pm_error("Both alpha channel and transparency chunk not allowed."); else { @@ -434,13 +427,13 @@ doTrnsChunk(const struct pam * const pamP, static void doChrmChunk(struct pngx * const pngxP, struct pngx_chroma const chroma) { - + pngx_setChrm(pngxP, chroma); if (verbose) { pm_message("writing cHRM chunk { wx, wy, rx, ry, gx, gy, bx, by } = " "{ %4.2f, %4.2f, %4.2f, %4.2f, " - "%4.2f, %4.2f, %4.2f, %4.2f }", + "%4.2f, %4.2f, %4.2f, %4.2f }", chroma.wx, chroma.wy, chroma.rx, chroma.ry, chroma.gx, chroma.gy, @@ -450,7 +443,7 @@ doChrmChunk(struct pngx * const pngxP, -static void +static void doGamaChunk(struct pngx * const pngxP, float const gamma) { @@ -500,9 +493,9 @@ doTextChunkSet(struct pngx * const pngxP, FILE * tfP; tfP = pm_openr(textFileName); - + pngtxt_addChunk(pngxP, tfP, ztxt, itxt, verbose); - + pm_close(tfP); } @@ -518,9 +511,9 @@ doZtxtChunkSet(struct pngx * const pngxP, FILE * tfP; tfP = pm_openr(textFileName); - + pngtxt_addChunk(pngxP, tfP, ztxt, itxt, verbose); - + pm_close(tfP); } @@ -556,11 +549,11 @@ doBkgdChunk (const struct pam * const pamP, pngx_setBkgdRgb(pngxP, pngColor); if (verbose) { - if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY || + if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY || pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA) { pm_message("writing bKGD chunk with gray level = %u", pngColor.gray); - } else if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB || + } else if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB || pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA) { pm_message("writing bKGD chunk with color {red, green, blue} = " "{%u, %u, %u}", @@ -591,24 +584,10 @@ doTimeChunk(struct pngx * const pngxP, static void -setShift(struct pngx * const pngxP, - png_color_8 const sigBits) { - - if (sigBits.red + sigBits.green + sigBits.blue + - sigBits.gray + sigBits.alpha > 0) { - - /* Move the 1, 2, 4 bits to most significant bits */ - pngx_setShift(pngxP, sigBits); - } -} - - - -static void -convertRaster(const struct pam * const pamP, - const tuple * const tuplerow, - png_byte * const pngRow, - unsigned int const bitDepth) { +convertRow(const struct pam * const pamP, + const tuple * const tuplerow, + png_byte * const pngRow, + unsigned int const bitDepth) { unsigned int col; @@ -637,9 +616,12 @@ convertRaster(const struct pam * const pamP, static void -writeRaster(const struct pam * const pamP, - struct pngx * const pngxP, - int const bitDepth) { +writeRasterRowByRow(const struct pam * const pamP, + struct pngx * const pngxP, + int const bitDepth) { + + unsigned int const rowSz = + pamP->width * pamP->depth * (MAX(1, bitDepth/8)); tuple * tupleRow; png_byte * pngRow; @@ -649,8 +631,7 @@ writeRaster(const struct pam * const pamP, tupleRow = pnm_allocpamrow(pamP); - MALLOCARRAY(pngRow, pamP->width * 8); - /* sufficient to store a 16-bit RGB+A row */ + MALLOCARRAY(pngRow, rowSz); if (pngRow == NULL) pm_error("Unable to allocate space for PNG pixel row for " @@ -659,9 +640,9 @@ writeRaster(const struct pam * const pamP, for (row = 0; row < pamP->height; ++row) { pnm_readpamrow(pamP, tupleRow); - convertRaster(pamP, tupleRow, pngRow, bitDepth); + convertRow(pamP, tupleRow, pngRow, bitDepth); - png_write_row(pngxP->png_ptr, pngRow); + pngx_writeRow(pngxP, pngRow); } free(pngRow); } @@ -670,40 +651,160 @@ writeRaster(const struct pam * const pamP, +static png_bytep +mallocPngImage(unsigned int const rowSize, + unsigned int const height) { + + png_bytep pngImage; + + if (UINT_MAX / rowSize < height) + pm_error("Image is uncomputably large at %u rows of %u bytes", + height, rowSize); + + MALLOCARRAY(pngImage, height * rowSize); + + if (!pngImage) + pm_error("could not allocate %u bytes for a PNG image buffer", + height * rowSize); + + return pngImage; +} + + + +static unsigned int +pngLineSize(struct pngx * const pngxP) { + + unsigned int const bytesPerSample = pngx_bitDepth(pngxP) == 16 ? 2 : 1; + + unsigned int samplesPerPixel; + + switch (pngx_colorType(pngxP)) { + case PNG_COLOR_TYPE_GRAY: + samplesPerPixel = 1; + break; + 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: + assert(false); + } + + if (UINT_MAX / bytesPerSample / samplesPerPixel < pngx_imageWidth(pngxP)) { + pm_error("pngcopy: width %u of PNG is uncomputably large\n", + pngx_imageWidth(pngxP)); + } + + return pngx_imageWidth(pngxP) * bytesPerSample * samplesPerPixel; +} + + + static void -writePng(const struct pam * const pamP, - FILE * const ofP, - struct CmdlineInfo const cmdline) { +writeRasterWholeImg(struct pam * const pamP, + struct pngx * const pngxP, + unsigned int const bitDepth) { - unsigned int const pnmBitDepth = pm_maxvaltobits(pamP->maxval); - int const pngColorType = colorTypeFromInputType(pamP); + unsigned int const pngRowSize = pngLineSize(pngxP); - struct pngx * pngxP; - unsigned int pngBitDepth; - png_color_8 sBit; + tuple * tupleRow; + png_bytep pngImage; + /* A one-dimensional malloc'ed array of all pixels in image */ + png_bytep * pngRowP; + /* A malloc'ed array of row pointers into pngImage[] */ + unsigned int row; - pngx_create(&pngxP, PNGX_WRITE, NULL); + tupleRow = pnm_allocpamrow(pamP); + + pngImage = mallocPngImage(pngRowSize, pamP->height); + + MALLOCARRAY(pngRowP, pamP->height); + + if (!pngRowP) + pm_error("Failed to allocate an array for %u PNG row pointers", + pamP->height); + for (row = 0; row < pamP->height; ++row) { + png_bytep const thisPngRowP = &pngImage[row * pngRowSize]; + pnm_readpamrow(pamP, tupleRow); + + convertRow(pamP, tupleRow, thisPngRowP, bitDepth); + + pngRowP[row] = thisPngRowP; + } + + pngx_writeImage(pngxP, pngRowP); + + free(pngRowP); + free(pngImage); + pnm_freepamrow(tupleRow); +} + + + +static void +reportInputFormat(const struct pam * const pamP) { + + const char * formatDesc; + + if (pamP->format == PBM_FORMAT || pamP->format == RPBM_FORMAT) + formatDesc = "PBM"; + else if (pamP->format == PGM_FORMAT || pamP->format == RPGM_FORMAT) + formatDesc = "PGM"; + else if (pamP->format == PPM_FORMAT || pamP->format == RPPM_FORMAT) + formatDesc = "PPM"; + else if (pamP->format == PAM_FORMAT) + formatDesc = "PAM"; + else + formatDesc = NULL; + + if (formatDesc) + pm_message("Input format = %s", formatDesc); + else + pm_message("Unrecognized input format, format code = 0x%x", + pamP->format); + + pm_message("Input tuple type = '%s'", pamP->tuple_type); + pm_message("Input depth = %u", pamP->depth); + pm_message("Input maxval = %u", (unsigned int) pamP->maxval); +} + + + +static unsigned int +pngBitDepth(unsigned int const pnmBitDepth, + int const pngColorType) { + + unsigned int retval; if ((pngColorType == PNG_COLOR_TYPE_RGB || pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) && pnmBitDepth < 8) { - pngBitDepth = 8; + retval = 8; } else - pngBitDepth = pnmBitDepth; + retval = pnmBitDepth; - png_init_io(pngxP->png_ptr, ofP); + return retval; +} - pngx_setIhdr(pngxP, pamP->width, pamP->height, - pngBitDepth, pngColorType, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, - PNG_FILTER_TYPE_BASE); - sBit = sigBitsFmImgType(pnmBitDepth, pngColorType); - /* Where requested, add ancillary chunks */ +static void +addAncillaryChunks(struct pam * const pamP, + struct pngx * const pngxP, + struct CmdlineInfo const cmdline, + png_color_8 const sigBits) { +/*---------------------------------------------------------------------------- + Where requested, add ancillary chunks. +-----------------------------------------------------------------------------*/ if (cmdline.transparencySpec) doTrnsChunk(pamP, pngxP,cmdline.transparency); @@ -715,7 +816,7 @@ writePng(const struct pam * const pamP, /* no iccp */ - doSbitChunk(pamP, pngxP, sBit); + doSbitChunk(pamP, pngxP, sigBits); if (cmdline.srgbintentSpec) doSrgbChunk(pngxP, cmdline.srgbintent); @@ -741,54 +842,96 @@ writePng(const struct pam * const pamP, if (cmdline.timeSpec) doTimeChunk(pngxP, cmdline.time); - setShift(pngxP, sBit); - - /* Write the ancillary chunks to PNG file */ + /* Write the ancillary chunks to PNG image */ pngx_writeInfo(pngxP); +} + + + +static void +setShift(struct pngx * const pngxP, + png_color_8 const sigBits) { + + if (sigBits.red + sigBits.green + sigBits.blue + + sigBits.gray + sigBits.alpha > 0) { - if (pngColorType != PNG_COLOR_TYPE_GRAY && pnmBitDepth < 8) { /* Move the 1, 2, 4 bits to most significant bits */ - pngx_setShift(pngxP, sBit); - } - if ((pngColorType == PNG_COLOR_TYPE_GRAY) && (pnmBitDepth < 8)) { - /* Pack multiple pixels in a byte */ - pngx_setPacking(pngxP); + pngx_setShift(pngxP, sigBits); } +} - writeRaster(pamP, pngxP, pnmBitDepth); - pngx_writeEnd(pngxP); - pngx_destroy(pngxP); -} +static void +doIhdrChunk(struct pngx * const pngxP, + unsigned int const width, + unsigned int const height, + unsigned int const pnmBitDepth, + int const pngColorType, + bool const interlace) { + + int const interlaceMethod = + interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE; + + pngx_setIhdr(pngxP, width, height, + pngBitDepth(pnmBitDepth, pngColorType), pngColorType, + interlaceMethod, PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); +} static void -reportInputFormat(const struct pam * const pamP) { +pamtopng(FILE * const ifP, + FILE * const ofP, + struct CmdlineInfo const cmdline) { - const char * formatDesc; + unsigned int pnmBitDepth; + int pngColorType; + struct pngx * pngxP; + png_color_8 sigBits; + struct pam pam; - if (pamP->format == PBM_FORMAT || pamP->format == RPBM_FORMAT) - formatDesc = "PBM"; - else if (pamP->format == PGM_FORMAT || pamP->format == RPGM_FORMAT) - formatDesc = "PGM"; - else if (pamP->format == PPM_FORMAT || pamP->format == RPPM_FORMAT) - formatDesc = "PPM"; - else if (pamP->format == PAM_FORMAT) - formatDesc = "PAM"; - else - formatDesc = NULL; + pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type)); - if (formatDesc) - pm_message("Input format = %s", formatDesc); - else - pm_message("Unrecognized input format, format code = 0x%x", - pamP->format); + if (verbose) + reportInputFormat(&pam); - pm_message("Input tuple type = '%s'", pamP->tuple_type); - pm_message("Input depth = %u", pamP->depth); - pm_message("Input maxval = %u", (unsigned int) pamP->maxval); + pnmBitDepth = pm_maxvaltobits(pam.maxval); + + pngColorType = colorTypeFromInputType(&pam); + + pngx_create(&pngxP, PNGX_WRITE, NULL); + + png_init_io(pngxP->png_ptr, ofP); + + doIhdrChunk(pngxP, pam.width, pam.height, + pnmBitDepth, pngColorType, cmdline.interlace > 0); + + sigBits = sigBitsFmImgType(pnmBitDepth, pngColorType); + + addAncillaryChunks(&pam, pngxP, cmdline, sigBits); + + setShift(pngxP, sigBits); + + if ((pngColorType == PNG_COLOR_TYPE_GRAY) && (pnmBitDepth < 8)) { + /* Pack multiple pixels in a byte */ + pngx_setPacking(pngxP); + } + + if (cmdline.interlace) { + /* Libpng will expect us to provide pixels in interlaced sequence + if we write row-by-row, and that is much to difficult, so we + do whole-image-at-once and let Libpng do the work. + */ + writeRasterWholeImg(&pam, pngxP, pnmBitDepth); + } else { + /* We save memory by going row-by-row */ + writeRasterRowByRow(&pam, pngxP, pnmBitDepth); + } + + pngx_writeEnd(pngxP); + pngx_destroy(pngxP); } @@ -799,7 +942,6 @@ main(int argc, FILE * ifP; struct CmdlineInfo cmdline; - struct pam pam; pm_proginit(&argc, argv); @@ -809,12 +951,7 @@ main(int argc, ifP = pm_openr(cmdline.inputFileName); - pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type)); - - if (verbose) - reportInputFormat(&pam); - - writePng(&pam, stdout, cmdline); + pamtopng(ifP, stdout, cmdline); pm_close(ifP); @@ -823,3 +960,18 @@ main(int argc, +/* Derived from pnmtorast.c by Jef Poskanzer and pamrgbatopng.c by Bryan +** Henderson <bryanh@giraffe-data.com> and probably some other sources +** +** Copyright (C) 1995-1998 by Alexander Lehmann <alex@hal.rhein-main.de> +** and Willem van Schaik <willem@schaik.com> +** Copyright (C) 1999,2001 by Greg Roelofs <newt@pobox.com> +** Copyright (C) 2015 by 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. +*/ diff --git a/converter/other/pamtopnm.c b/converter/other/pamtopnm.c index f043d721..f0ad451a 100644 --- a/converter/other/pamtopnm.c +++ b/converter/other/pamtopnm.c @@ -96,7 +96,7 @@ validateTupleType(struct pam const inpam, /* It's a PPMable image */ } else pm_error("PAM image does not have a depth and tuple_type " - "consistent with a PNM image." + "consistent with a PNM image. " "According to its " "header, depth is %d and tuple_type is '%s'. " "Use the -assume option to convert anyway.", diff --git a/converter/other/pamtosvg/pxl-outline.c b/converter/other/pamtosvg/pxl-outline.c index 456f41e1..19451c04 100644 --- a/converter/other/pamtosvg/pxl-outline.c +++ b/converter/other/pamtosvg/pxl-outline.c @@ -206,10 +206,8 @@ next_unmarked_pixel(unsigned int * const row, direction_type const orig_dir = *dir; direction_type test_dir; - pixel color; test_dir = *dir; /* initial value */ - color = getBitmapColor(bitmap, *row, *col); do { if (is_valid_dir(orig_row, orig_col, test_dir, bitmap, *marked)) { diff --git a/converter/other/pamtosvg/vector.c b/converter/other/pamtosvg/vector.c index 0a5ef3a9..771e5f27 100644 --- a/converter/other/pamtosvg/vector.c +++ b/converter/other/pamtosvg/vector.c @@ -1,6 +1,6 @@ /* vector.c: vector/point operations. */ -#define _XOPEN_SOURCE /* Make sure M_PI is in <math.h> */ +#define _XOPEN_SOURCE 500 /* get M_PI in math.h */ #include <math.h> #include <errno.h> #include <assert.h> diff --git a/converter/other/pamtotga.c b/converter/other/pamtotga.c index aca93015..1daa1e25 100644 --- a/converter/other/pamtotga.c +++ b/converter/other/pamtotga.c @@ -10,9 +10,11 @@ ** implied warranty. */ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _BSD_SOURCE /* Make sure string.h contains strdup() */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ +#include <assert.h> #include <string.h> #include "pm_c_util.h" @@ -26,22 +28,24 @@ /* Max number of colors allowed for colormapped output. */ #define MAXCOLORS 256 -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char *inputFilespec; /* Filespec of input file */ - char *outName; + const char * inputFileName; + const char * outName; enum TGAbaseImageType imgType; - bool defaultFormat; - unsigned int norle; + enum TGAmapType mapType; + bool defaultFormat; + unsigned int norle; + unsigned int verbose; }; static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { +parseCommandLine(int argc, const char ** argv, + struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Parse the program arguments (given by argc and argv) into a form the program can deal with more easily -- a cmdline_info structure. @@ -56,38 +60,47 @@ parseCommandLine(int argc, char ** argv, unsigned int option_def_index; unsigned int outNameSpec; - unsigned int cmap, mono, rgb; + unsigned int cmap, cmap16, mono, rgb; option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "name", OPT_STRING, + OPTENT3(0, "name", OPT_STRING, &cmdlineP->outName, &outNameSpec, 0); - OPTENT3(0, "cmap", OPT_FLAG, + OPTENT3(0, "cmap", OPT_FLAG, NULL, &cmap, 0); - OPTENT3(0, "mono", OPT_FLAG, + OPTENT3(0, "cmap16", OPT_FLAG, + NULL, &cmap16, 0); + OPTENT3(0, "mono", OPT_FLAG, NULL, &mono, 0); - OPTENT3(0, "rgb", OPT_FLAG, + OPTENT3(0, "rgb", OPT_FLAG, NULL, &rgb, 0); - OPTENT3(0, "norle", OPT_FLAG, + OPTENT3(0, "norle", OPT_FLAG, NULL, &cmdlineP->norle, 0); - + OPTENT3(0, "verbose", OPT_FLAG, + NULL, &cmdlineP->verbose, 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 */ - pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdline_p and others. */ - if (cmap + mono + rgb > 1) - pm_error("You may specify only one of -cmap, -mono, and -rgb."); + if (cmap + cmap16 + mono + rgb > 1) + pm_error("You may specify only one of -cmap, -cmap16, " + "-mono, and -rgb."); - if (cmap + mono + rgb == 0) + if (cmap + cmap16 + mono + rgb == 0) cmdlineP->defaultFormat = TRUE; else { cmdlineP->defaultFormat = FALSE; - - if (cmap) + + if (cmap) { cmdlineP->imgType = TGA_MAP_TYPE; - else if (mono) + cmdlineP->mapType = TGA_MAPTYPE_LONG; + } else if (cmap16) { + cmdlineP->imgType = TGA_MAP_TYPE; + cmdlineP->mapType = TGA_MAPTYPE_SHORT; + } else if (mono) cmdlineP->imgType = TGA_MONO_TYPE; else if (rgb) cmdlineP->imgType = TGA_RGB_TYPE; @@ -95,56 +108,22 @@ parseCommandLine(int argc, char ** argv, if (!outNameSpec) cmdlineP->outName = NULL; - - if (argc-1 == 0) - cmdlineP->inputFilespec = "-"; + + if (argc-1 == 0) + cmdlineP->inputFileName = "-"; else if (argc-1 != 1) pm_error("Program takes zero or one argument (filename). You " "specified %d", argc-1); else - cmdlineP->inputFilespec = argv[1]; - -} - - -static void -writeTgaHeader(struct ImageHeader const tgaHeader) { - - unsigned char flags; - - putchar(tgaHeader.IdLength); - putchar(tgaHeader.CoMapType); - putchar(tgaHeader.ImgType); - putchar(tgaHeader.Index_lo); - putchar(tgaHeader.Index_hi); - putchar(tgaHeader.Length_lo); - putchar(tgaHeader.Length_hi); - putchar(tgaHeader.CoSize); - putchar(tgaHeader.X_org_lo); - putchar(tgaHeader.X_org_hi); - putchar(tgaHeader.Y_org_lo); - putchar(tgaHeader.Y_org_hi); - putchar(tgaHeader.Width_lo); - putchar(tgaHeader.Width_hi); - putchar(tgaHeader.Height_lo); - putchar(tgaHeader.Height_hi); - putchar(tgaHeader.PixelSize); - flags = (tgaHeader.AttBits & 0xf) | - ((tgaHeader.Rsrvd & 0x1) << 4) | - ((tgaHeader.OrgBit & 0x1) << 5) | - ((tgaHeader.OrgBit & 0x3) << 6); - putchar(flags); + cmdlineP->inputFileName = argv[1]; - if (tgaHeader.IdLength > 0) - fwrite(tgaHeader.Id, 1, (int) tgaHeader.IdLength, stdout); } - static void putPixel(struct pam * const pamP, - tuple const tuple, - enum TGAbaseImageType const imgType, + tuple const tuple, + enum TGAbaseImageType const imgType, bool const withAlpha, tuplehash const cht) { /*---------------------------------------------------------------------------- @@ -166,22 +145,22 @@ putPixel(struct pam * const pamP, if (imgType == TGA_RGB_TYPE && pamP->depth < 3) { /* Make RGB pixel out of a single input plane */ unsigned int plane; - - for (plane = 0; plane < 3; ++plane) - putchar(pnm_scalesample(tuple[0], + + for (plane = 0; plane < 3; ++plane) + putchar(pnm_scalesample(tuple[0], pamP->maxval, TGA_MAXVAL)); } else if (imgType == TGA_MONO_TYPE) - putchar(pnm_scalesample(tuple[0], + putchar(pnm_scalesample(tuple[0], pamP->maxval, TGA_MAXVAL)); else { - putchar(pnm_scalesample(tuple[PAM_BLU_PLANE], + putchar(pnm_scalesample(tuple[PAM_BLU_PLANE], pamP->maxval, TGA_MAXVAL)); - putchar(pnm_scalesample(tuple[PAM_GRN_PLANE], + putchar(pnm_scalesample(tuple[PAM_GRN_PLANE], pamP->maxval, TGA_MAXVAL)); - putchar(pnm_scalesample(tuple[PAM_RED_PLANE], + putchar(pnm_scalesample(tuple[PAM_RED_PLANE], pamP->maxval, TGA_MAXVAL)); if (withAlpha) - putchar(pnm_scalesample(tuple[PAM_TRN_PLANE], + putchar(pnm_scalesample(tuple[PAM_TRN_PLANE], pamP->maxval, TGA_MAXVAL)); } } @@ -190,39 +169,47 @@ putPixel(struct pam * const pamP, static void -putMapEntry(struct pam * const pamP, - tuple const value, +putMapEntry(struct pam * const pamP, + tuple const value, int const size) { - if (size == 15 || size == 16) { - /* 5 bits each of red, green, and blue. Watch for byte order */ - + if (size == 8) + putchar(pnm_scalesample(value[0], + pamP->maxval, TGA_MAXVAL)); + else if (size == 15 || size == 16) { tuple const tuple31 = pnm_allocpamtuple(pamP); + assert(pamP->depth >= 3); + pnm_scaletuple(pamP, tuple31, value, 31); { - int const mapentry = + unsigned int const trn = + size == 16 && tuple31[PAM_TRN_PLANE] > 0 ? 1 : 0; + + unsigned int const mapentry = tuple31[PAM_BLU_PLANE] << 0 | tuple31[PAM_GRN_PLANE] << 5 | - tuple31[PAM_RED_PLANE] << 10; - + tuple31[PAM_RED_PLANE] << 10 | + trn << 15; + + /* Note little-endian byte swapping */ putchar(mapentry % 256); putchar(mapentry / 256); } pnm_freepamtuple(tuple31); - } else if (size == 8) - putchar(pnm_scalesample(value[0], - pamP->maxval, TGA_MAXVAL)); - else { - /* Must be 24 or 32 */ - putchar(pnm_scalesample(value[PAM_BLU_PLANE], + } else { + assert(size == 24 || size == 32); + + assert(pamP->depth >= 3); + + putchar(pnm_scalesample(value[PAM_BLU_PLANE], pamP->maxval, TGA_MAXVAL)); - putchar(pnm_scalesample(value[PAM_GRN_PLANE], + putchar(pnm_scalesample(value[PAM_GRN_PLANE], pamP->maxval, TGA_MAXVAL)); - putchar(pnm_scalesample(value[PAM_RED_PLANE], + putchar(pnm_scalesample(value[PAM_RED_PLANE], pamP->maxval, TGA_MAXVAL)); if (size == 32) - putchar(pnm_scalesample(value[PAM_TRN_PLANE], + putchar(pnm_scalesample(value[PAM_TRN_PLANE], pamP->maxval, TGA_MAXVAL)); } } @@ -230,8 +217,8 @@ putMapEntry(struct pam * const pamP, static void -computeRunlengths(struct pam * const pamP, - tuple * const tuplerow, +computeRunlengths(struct pam * const pamP, + tuple * const tuplerow, int * const runlength) { int col, start; @@ -239,7 +226,7 @@ computeRunlengths(struct pam * const pamP, /* Initialize all run lengths to 0. (This is just an error check.) */ for (col = 0; col < pamP->width; ++col) runlength[col] = 0; - + /* Find runs of identical pixels. */ for ( col = 0; col < pamP->width; ) { start = col; @@ -250,7 +237,7 @@ computeRunlengths(struct pam * const pamP, pnm_tupleequal(pamP, tuplerow[col], tuplerow[start])); runlength[start] = col - start; } - + /* Now look for runs of length-1 runs, and turn them into negative runs. */ for (col = 0; col < pamP->width; ) { if (runlength[col] == 1) { @@ -270,23 +257,23 @@ computeRunlengths(struct pam * const pamP, static void -computeOutName(struct cmdlineInfo const cmdline, +computeOutName(struct CmdlineInfo const cmdline, const char ** const outNameP) { - + char * workarea; if (cmdline.outName) workarea = strdup(cmdline.outName); - else if (streq(cmdline.inputFilespec, "-")) + else if (streq(cmdline.inputFileName, "-")) workarea = NULL; else { char * cp; - workarea = strdup(cmdline.inputFilespec); + workarea = strdup(cmdline.inputFileName); cp = strchr(workarea, '.'); if (cp != NULL) *cp = '\0'; /* remove extension */ } - + if (workarea == NULL) *outNameP = NULL; else { @@ -305,16 +292,16 @@ validateTupleType(struct pam * const pamP) { if (streq(pamP->tuple_type, "RGB_ALPHA")) { if (pamP->depth < 4) pm_error("Invalid depth for tuple type RGB_ALPHA. " - "Should have at least 4 planes, but has %d.", + "Should have at least 4 planes, but has %d.", pamP->depth); } else if (streq(pamP->tuple_type, "RGB")) { if (pamP->depth < 3) pm_error("Invalid depth for tuple type RGB. " - "Should have at least 3 planes, but has %d.", + "Should have at least 3 planes, but has %d.", pamP->depth); } else if (streq(pamP->tuple_type, "GRAYSCALE")) { } else if (streq(pamP->tuple_type, "BLACKANDWHITE")) { - } else + } else pm_error("Invalid type of input. PAM tuple type is '%s'. " "This programs understands only RGB_ALPHA, RGB, GRAYSCALE, " "and BLACKANDWHITE.", pamP->tuple_type); @@ -324,69 +311,76 @@ validateTupleType(struct pam * const pamP) { static void computeImageType_cht(struct pam * const pamP, - struct cmdlineInfo const cmdline, + struct CmdlineInfo const cmdline, tuple ** const tuples, enum TGAbaseImageType * const baseImgTypeP, + enum TGAmapType * const mapTypeP, bool * const withAlphaP, tupletable * const chvP, - tuplehash * const chtP, + tuplehash * const chtP, int * const ncolorsP) { - unsigned int ncolors; + unsigned int ncolors; enum TGAbaseImageType baseImgType; - bool withAlpha; + enum TGAmapType mapType; + bool withAlpha; validateTupleType(pamP); - withAlpha = (streq(pamP->tuple_type, "RGB_ALPHA")); - if (cmdline.defaultFormat) { /* default the image type */ - if (withAlpha) { + if (streq(pamP->tuple_type, "RGB_ALPHA")) { baseImgType = TGA_RGB_TYPE; *chvP = NULL; - } else if (pamP->depth > 1) { + withAlpha = true; + } else if (streq(pamP->tuple_type, "RGB")) { pm_message("computing colormap..."); - *chvP = + *chvP = pnm_computetuplefreqtable(pamP, tuples, MAXCOLORS, &ncolors); if (*chvP == NULL) { pm_message("Too many colors for colormapped TGA. Doing RGB."); baseImgType = TGA_RGB_TYPE; - } else + } else { baseImgType = TGA_MAP_TYPE; + mapType = TGA_MAPTYPE_LONG; + } + withAlpha = false; } else { baseImgType = TGA_MONO_TYPE; *chvP = NULL; + withAlpha = false; } } else { + withAlpha = (streq(pamP->tuple_type, "RGB_ALPHA")); + baseImgType = cmdline.imgType; if (baseImgType == TGA_MAP_TYPE) { + mapType = cmdline.mapType; + if (withAlpha) pm_error("Can't do a colormap because image has transparency " "information"); pm_message("computing colormap..."); - *chvP = + *chvP = pnm_computetuplefreqtable(pamP, tuples, MAXCOLORS, &ncolors); - if (*chvP == NULL) + if (*chvP == NULL) pm_error("Too many colors for colormapped TGA. " - "Use 'pnmquant %d' to reduce the number of colors.", + "Use 'pnmquant %d' to reduce the number of colors.", MAXCOLORS); } else *chvP = NULL; - if (baseImgType == TGA_MONO_TYPE && pamP->depth > 1) - pm_error("For Mono TGA output, input must be " - "GRAYSCALE or BLACKANDWHITE PAM or PBM or PGM"); } - + if (baseImgType == TGA_MAP_TYPE) { - pm_message("%d colors found.", ncolors); + pm_message("%u colors found.", ncolors); /* Make a hash table for fast color lookup. */ *chtP = pnm_computetupletablehash(pamP, *chvP, ncolors); } else *chtP = NULL; *baseImgTypeP = baseImgType; + *mapTypeP = mapType; *withAlphaP = withAlpha; *ncolorsP = ncolors; } @@ -396,8 +390,9 @@ computeImageType_cht(struct pam * const pamP, static void computeTgaHeader(struct pam * const pamP, enum TGAbaseImageType const baseImgType, + enum TGAmapType const mapType, bool const withAlpha, - bool const rle, + bool const rle, int const ncolors, unsigned char const orgBit, const char * const id, @@ -416,7 +411,7 @@ computeTgaHeader(struct pam * const pamP, case TGA_RGB_TYPE: tgaHeaderP->ImgType = TGA_RGB; break; } } - + if (id) { tgaHeaderP->IdLength = strlen(id); tgaHeaderP->Id = strdup(id); @@ -428,7 +423,18 @@ computeTgaHeader(struct pam * const pamP, tgaHeaderP->CoMapType = 1; tgaHeaderP->Length_lo = ncolors % 256; tgaHeaderP->Length_hi = ncolors / 256; - tgaHeaderP->CoSize = 8 * pamP->depth; + if (pamP->depth < 3) + tgaHeaderP->CoSize = 8; + else { + switch (mapType) { + case TGA_MAPTYPE_SHORT: + tgaHeaderP->CoSize = withAlpha ? 16 : 15; + break; + case TGA_MAPTYPE_LONG: + tgaHeaderP->CoSize = withAlpha ? 32 : 24; + break; + } + } } else { tgaHeaderP->CoMapType = 0; tgaHeaderP->Length_lo = 0; @@ -440,7 +446,7 @@ computeTgaHeader(struct pam * const pamP, tgaHeaderP->PixelSize = 8; break; case TGA_RGB_TYPE: - tgaHeaderP->PixelSize = 8 * MAX((withAlpha ? 4: 3), pamP->depth); + tgaHeaderP->PixelSize = 8 * (withAlpha ? 4: 3); break; case TGA_MONO_TYPE: tgaHeaderP->PixelSize = 8; @@ -460,6 +466,70 @@ computeTgaHeader(struct pam * const pamP, static void +reportTgaHeader(struct ImageHeader const tgaHeader) { + + switch (tgaHeader.ImgType) { + case TGA_RLEMono: + pm_message("Generating monochrome, run-length encoded"); + break; + case TGA_RLEMap: + pm_message("Generating colormapped, run-length encoded"); + pm_message("%u bits per colormap entry", tgaHeader.CoSize); + break; + case TGA_RLERGB: + pm_message("Generating RGB truecolor, run-length encoded"); + break; + case TGA_Mono: + pm_message("Generating monochrome, uncompressed"); + break; + case TGA_Map: + pm_message("Generating colormapped, uncompressed"); + pm_message("%u bits per colormap entry", tgaHeader.CoSize); + break; + case TGA_RGB: + pm_message("Generating RGB truecolor, uncompressed"); + break; + } + pm_message("%u bits per pixel", tgaHeader.PixelSize); +} + + + +static void +writeTgaHeader(struct ImageHeader const tgaHeader) { + + unsigned char flags; + + putchar(tgaHeader.IdLength); + putchar(tgaHeader.CoMapType); + putchar(tgaHeader.ImgType); + putchar(tgaHeader.Index_lo); + putchar(tgaHeader.Index_hi); + putchar(tgaHeader.Length_lo); + putchar(tgaHeader.Length_hi); + putchar(tgaHeader.CoSize); + putchar(tgaHeader.X_org_lo); + putchar(tgaHeader.X_org_hi); + putchar(tgaHeader.Y_org_lo); + putchar(tgaHeader.Y_org_hi); + putchar(tgaHeader.Width_lo); + putchar(tgaHeader.Width_hi); + putchar(tgaHeader.Height_lo); + putchar(tgaHeader.Height_hi); + putchar(tgaHeader.PixelSize); + flags = (tgaHeader.AttBits & 0xf) | + ((tgaHeader.Rsrvd & 0x1) << 4) | + ((tgaHeader.OrgBit & 0x1) << 5) | + ((tgaHeader.OrgBit & 0x3) << 6); + putchar(flags); + + if (tgaHeader.IdLength > 0) + fwrite(tgaHeader.Id, 1, (int) tgaHeader.IdLength, stdout); +} + + + +static void releaseTgaHeader(struct ImageHeader const tgaHeader) { if (tgaHeader.IdLength > 0) @@ -468,9 +538,9 @@ releaseTgaHeader(struct ImageHeader const tgaHeader) { -static void +static void writeTgaRaster(struct pam * const pamP, - tuple ** const tuples, + tuple ** const tuples, tuplehash const cht, enum TGAbaseImageType const imgType, bool const withAlpha, @@ -499,7 +569,7 @@ writeTgaRaster(struct pam * const pamP, int i; putchar(-runlength[col] - 1); for (i = 0; i < -runlength[col]; ++i) - putPixel(pamP, tuples[realrow][col+i], + putPixel(pamP, tuples[realrow][col+i], imgType, withAlpha, cht); col += -runlength[col]; } else @@ -518,47 +588,53 @@ writeTgaRaster(struct pam * const pamP, int -main(int argc, char *argv[]) { +main(int argc, const char **argv) { - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; FILE * ifP; tuple ** tuples; struct pam pam; - int ncolors; + int colorCt; tupletable chv; tuplehash cht; struct ImageHeader tgaHeader; enum TGAbaseImageType baseImgType; + enum TGAmapType mapType; bool withAlpha; - const char *outName; + const char * outName; - pnm_init( &argc, argv ); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); - ifP = pm_openr(cmdline.inputFilespec); + ifP = pm_openr(cmdline.inputFileName); computeOutName(cmdline, &outName); tuples = pnm_readpam(ifP, &pam, PAM_STRUCT_SIZE(tuple_type)); pm_close(ifP); - computeImageType_cht(&pam, cmdline, tuples, - &baseImgType, &withAlpha, &chv, &cht, &ncolors); + computeImageType_cht(&pam, cmdline, tuples, + &baseImgType, &mapType, + &withAlpha, &chv, &cht, &colorCt); /* Do the Targa header */ - computeTgaHeader(&pam, baseImgType, withAlpha, !cmdline.norle, - ncolors, 0, outName, &tgaHeader); + computeTgaHeader(&pam, baseImgType, mapType, withAlpha, !cmdline.norle, + colorCt, 0, outName, &tgaHeader); + + if (cmdline.verbose) + reportTgaHeader(tgaHeader); + writeTgaHeader(tgaHeader); - + if (baseImgType == TGA_MAP_TYPE) { /* Write out the Targa colormap. */ - int i; - for (i = 0; i < ncolors; ++i) + unsigned int i; + for (i = 0; i < colorCt; ++i) putMapEntry(&pam, chv[i]->tuple, tgaHeader.CoSize); } - writeTgaRaster(&pam, tuples, cht, baseImgType, withAlpha, + writeTgaRaster(&pam, tuples, cht, baseImgType, withAlpha, !cmdline.norle, 0); if (cht) diff --git a/converter/other/pamtotiff.c b/converter/other/pamtotiff.c index 7b645b23..115b8b4a 100644 --- a/converter/other/pamtotiff.c +++ b/converter/other/pamtotiff.c @@ -22,7 +22,6 @@ */ #define _XOPEN_SOURCE /* Make sure stdio.h contains fileno() */ -#define _BSD_SOURCE /* Make sure string.h contains strcasecmp() */ #include <unistd.h> #include <stdio.h> @@ -135,6 +134,44 @@ validateTagList(struct optNameValue const taglist[]) { static void +parseIndexbits(bool const indexbitsSpec, + char ** const indexbits, + CmdlineInfo * const cmdlineP) { + + if (indexbitsSpec) { + unsigned int i; + + /* Set initial values */ + cmdlineP->indexsizeAllowed.b1 = false; + cmdlineP->indexsizeAllowed.b2 = false; + cmdlineP->indexsizeAllowed.b4 = false; + cmdlineP->indexsizeAllowed.b8 = false; + + for (i = 0; indexbits[i]; ++i) { + const char * const thisItem = indexbits[i]; + if (streq(thisItem, "1")) + cmdlineP->indexsizeAllowed.b1 = true; + else if (streq(thisItem, "2")) + cmdlineP->indexsizeAllowed.b2 = true; + else if (streq(thisItem, "4")) + cmdlineP->indexsizeAllowed.b4 = true; + else if (streq(thisItem, "8")) + cmdlineP->indexsizeAllowed.b8 = true; + else + pm_error("Invalid item in -indexbits list: '%s'. " + "We recognize only 1, 2, 4, and 8", thisItem); + } + } else { + cmdlineP->indexsizeAllowed.b1 = false; + cmdlineP->indexsizeAllowed.b2 = false; + cmdlineP->indexsizeAllowed.b4 = false; + cmdlineP->indexsizeAllowed.b8 = true; + } +} + + + +static void parseCommandLine(int argc, const char ** const argv, CmdlineInfo * const cmdlineP) { @@ -148,7 +185,7 @@ parseCommandLine(int argc, unsigned int none, packbits, lzw, g3, g4, msb2lsb, lsb2msb, opt_2d, fill; unsigned int flate, adobeflate; - char * indexbits; + char ** indexbits; char * resolutionunit; unsigned int appendSpec, outputSpec, predictorSpec, rowsperstripSpec, @@ -191,13 +228,13 @@ parseCommandLine(int argc, &yresolutionSpec, 0); OPTENT3(0, "resolutionunit", OPT_STRING, &resolutionunit, &resolutionunitSpec, 0); - OPTENT3(0, "indexbits", OPT_STRING, &indexbits, + OPTENT3(0, "indexbits", OPT_STRINGLIST, &indexbits, &indexbitsSpec, 0); OPTENT3(0, "tag", OPT_NAMELIST, &cmdlineP->taglist, &tagSpec, 0); opt.opt_table = option_def; - opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ - opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + opt.short_allowed = false; /* We have no short (old-fashioned) options */ + opt.allowNegNum = false; /* We have no parms that are negative numbers */ pm_optParseOptions3(&argc, (char**)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ @@ -301,35 +338,16 @@ parseCommandLine(int argc, } else cmdlineP->resolutionunit = RESUNIT_INCH; - if (indexbitsSpec) { - if (strstr(indexbits, "1")) - cmdlineP->indexsizeAllowed.b1 = TRUE; - else - cmdlineP->indexsizeAllowed.b1 = FALSE; - if (strstr(indexbits, "2")) - cmdlineP->indexsizeAllowed.b2 = TRUE; - else - cmdlineP->indexsizeAllowed.b2 = FALSE; - if (strstr(indexbits, "4")) - cmdlineP->indexsizeAllowed.b4 = TRUE; - else - cmdlineP->indexsizeAllowed.b4 = FALSE; - if (strstr(indexbits, "8")) - cmdlineP->indexsizeAllowed.b8 = TRUE; - else - cmdlineP->indexsizeAllowed.b8 = FALSE; - } else { - cmdlineP->indexsizeAllowed.b1 = FALSE; - cmdlineP->indexsizeAllowed.b2 = FALSE; - cmdlineP->indexsizeAllowed.b4 = FALSE; - cmdlineP->indexsizeAllowed.b8 = TRUE; - } + parseIndexbits(indexbitsSpec, indexbits, cmdlineP); + + if (indexbitsSpec) + free(indexbits); if (tagSpec) validateTagList(cmdlineP->taglist); else { MALLOCARRAY_NOFAIL(cmdlineP->taglist, 1); - cmdlineP->taglist[0].name = NULL; + cmdlineP->taglist[0].name = NULL; cmdlineP->taglist[0].value = NULL; } @@ -345,6 +363,14 @@ parseCommandLine(int argc, static void +freeCmdline(CmdlineInfo const cmdline) { + + pm_optDestroyNameValueList(cmdline.taglist); +} + + + +static void fillRowOfSubBytePixels(struct pam * const pamP, const tuple * const tuplerow, unsigned char * const buf, @@ -517,7 +543,7 @@ writeScanLines(struct pam * const pamP, The samples form pixel values according to the pixel format indicated by the TIFF photometric. E.g. if it is MINISWHITE, then a pixel is - one sample and a value of 0 for that sample means white. + grayscale, composed of one sample where a value of 0 means white. */ MALLOCARRAY(buf, bytesperrow); @@ -577,14 +603,14 @@ analyzeColorsInRgbInput(struct pam * const pamP, CmdlineInfo const cmdline, int const maxcolors, tupletable * const chvP, - unsigned int * const colorsP, + unsigned int * const colorCtP, bool * const grayscaleP) { /*---------------------------------------------------------------------------- Same as analyzeColors(), except assuming input image has R/G/B tuples. -----------------------------------------------------------------------------*/ if (cmdline.color && cmdline.truecolor) { *chvP = NULL; - *grayscaleP = FALSE; + *grayscaleP = false; } else { tupletable chv; bool grayscale; @@ -592,17 +618,17 @@ analyzeColorsInRgbInput(struct pam * const pamP, pm_message("computing colormap..."); chv = pnm_computetuplefreqtable2(pamP, NULL, maxcolors, pamP->maxval, - colorsP); + colorCtP); if (chv == NULL) { - grayscale = FALSE; + grayscale = false; } else { unsigned int i; pm_message("%u color%s found", - *colorsP, *colorsP == 1 ? "" : "s"); - grayscale = TRUE; /* initial assumption */ - for (i = 0; i < *colorsP && grayscale; ++i) { + *colorCtP, *colorCtP == 1 ? "" : "s"); + grayscale = true; /* initial assumption */ + for (i = 0; i < *colorCtP && grayscale; ++i) { if (!pnm_rgbtupleisgray(chv[i]->tuple)) - grayscale = FALSE; + grayscale = false; } } *grayscaleP = grayscale; @@ -634,21 +660,22 @@ analyzeColors(struct pam * const pamP, CmdlineInfo const cmdline, int const maxcolors, tupletable * const chvP, - unsigned int * const colorsP, + unsigned int * const colorCtP, bool * const grayscaleP) { /*---------------------------------------------------------------------------- Analyze the colors in the input image described by 'pamP', whose file is positioned to the raster. - If the colors, combined with command line options 'cmdline', indicate - a colormapped TIFF should be generated, return as *chvP the address - of a color map (in newly malloc'ed space). If a colormapped TIFF is - not indicated, return *chvP == NULL. - Return *grayscaleP == true iff the image should be stored as a grayscale image (which means the image is monochromatic and the user doesn't insist on color format). + If *grayscaleP is false and the colors, combined with command line options + 'cmdline', indicate a colormapped TIFF should be generated, return as *chvP + the address of a color map (in newly malloc'ed space) and the number of + colors in it as *colorCtP. If a colormapped color TIFF is not indicated, + return *chvP == NULL and nothing as *colorCtP. + Leave the file position undefined. -----------------------------------------------------------------------------*/ if (pamP->depth >= 3) @@ -656,10 +683,28 @@ analyzeColors(struct pam * const pamP, (tuple type RGB or RGB_ALPHA) */ analyzeColorsInRgbInput(pamP, cmdline, maxcolors, - chvP, colorsP, grayscaleP); + chvP, colorCtP, grayscaleP); else { *chvP = NULL; - *grayscaleP = TRUE; + *grayscaleP = true; + } +} + + + +static void +reportTiffType(bool const grayscale, + bool const colormapped, + unsigned int const colorCt, + bool const verbose) { + + if (verbose) { + pm_message("Generating %s TIFF", grayscale ? "grayscale" : "color"); + + if (colormapped) + pm_message("TIFF will have palette of %u colors", colorCt); + else + pm_message("TIFF will be truecolor (24 bit RGB)"); } } @@ -668,7 +713,7 @@ analyzeColors(struct pam * const pamP, static void computeRasterParm(struct pam * const pamP, tupletable const chv, - int const colors, + int const colorCt, bool const grayscale, int const compression, bool const minisblack, @@ -682,7 +727,7 @@ computeRasterParm(struct pam * const pamP, Compute the parameters of the raster portion of the TIFF image. 'minisblack' and 'miniswhite' mean the user requests the corresponding - photometric. Both FALSE means user has no explicit requirement. + photometric. Both false means user has no explicit requirement. -----------------------------------------------------------------------------*/ unsigned short defaultPhotometric; /* The photometric we use if the user specified no preference */ @@ -709,14 +754,14 @@ computeRasterParm(struct pam * const pamP, if (chv) { *samplesperpixelP = 1; /* Pixel is just the one index value */ *bitspersampleP = - colors <= 2 && indexsizeAllowed.b1 ? 1 : - colors <= 4 && indexsizeAllowed.b2 ? 2 : - colors <= 16 && indexsizeAllowed.b4 ? 4 : - colors <= 256 && indexsizeAllowed.b8 ? 8 : + colorCt <= 2 && indexsizeAllowed.b1 ? 1 : + colorCt <= 4 && indexsizeAllowed.b2 ? 2 : + colorCt <= 16 && indexsizeAllowed.b4 ? 4 : + colorCt <= 256 && indexsizeAllowed.b8 ? 8 : 0; if (*bitspersampleP == 0) pm_error("Your -indexbits option is insufficient for the " - "%d colors in this image.", colors); + "%d colors in this image.", colorCt); defaultPhotometric = PHOTOMETRIC_PALETTE; } else { @@ -736,11 +781,15 @@ computeRasterParm(struct pam * const pamP, } } - if (miniswhite) + if (miniswhite) { + if (!grayscale) + pm_error("Image is color, so -miniswhite is invalid"); *photometricP = PHOTOMETRIC_MINISWHITE; - else if (minisblack) + } else if (minisblack) { + if (!grayscale) + pm_error("Image is color, so -minisblack is invalid"); *photometricP = PHOTOMETRIC_MINISBLACK; - else + } else *photometricP = defaultPhotometric; { @@ -764,9 +813,9 @@ computeRasterParm(struct pam * const pamP, /*---------------------------------------------------------------------------- WRITE MODES ----------- - + The Tiff library does all output. There are several issues: - + 1) The manner of output is opaque to the library client. I.e. we cannot see or control it. @@ -777,22 +826,22 @@ computeRasterParm(struct pam * const pamP, 4) The Tiff library produces unhelpful error messages when the above conditions are not met. - + We provide two modes for output: - + 1. Tmpfile mode (default) - + We have the Tiff library direct output to an unnamed temporary file we create which is seekable and readable. When output is complete, we copy the file's contents to Standard Output. - + 2. Direct mode (specified with -output) - + We have the Tiff library write output to the specified file. As the Tiff library requires taht it be be seekable and readable, we fail the program rather than ask the Tiff library to use the file if it does not meet these requirements. - + Direct mode is further divided into append and create. They are the same except that in append mode, we insist that the file already exist, whereas with create mode, we create it if necessary. In either case, if @@ -972,9 +1021,9 @@ copyBufferToStdout(int const tmpfileFd) { static void -destroyTiffGenerator(WriteMethod const writeMethod, - TIFF * const tifP, - int const ofd) { +closeTiffGenerator(WriteMethod const writeMethod, + TIFF * const tifP, + int const ofd) { TIFFFlushData(tifP); @@ -994,7 +1043,7 @@ static void createTiffColorMap(struct pam * const pamP, unsigned int const bitspersample, tupletable const chv, - unsigned int const colors, + unsigned int const colorCt, unsigned short *** const tiffColorMapP) { unsigned int const colorMapSize = 1 << bitspersample; @@ -1009,7 +1058,7 @@ createTiffColorMap(struct pam * const pamP, for (i = 0; i < colorMapSize; ++i) { unsigned int plane; for (plane = 0; plane < pamP->depth; ++plane) { - if (i < colors) + if (i < colorCt) tiffColorMap[plane][i] = chv[i]->tuple[plane] * 65535L / pamP->maxval; else @@ -1136,7 +1185,7 @@ convertImage(FILE * const ifP, tuplehash cht; unsigned short ** tiffColorMap; /* malloc'ed */ struct pam pam; - unsigned int colors; + unsigned int colorCt; bool grayscale; unsigned short photometric; unsigned short samplesperpixel; @@ -1152,14 +1201,16 @@ convertImage(FILE * const ifP, pm_tell2(ifP, &rasterPos, sizeof(rasterPos)); - analyzeColors(&pam, cmdline, MAXCOLORS, &chv, &colors, &grayscale); + analyzeColors(&pam, cmdline, MAXCOLORS, &chv, &colorCt, &grayscale); + + reportTiffType(grayscale, chv != NULL, colorCt, cmdline.verbose); /* Go back to beginning of raster */ pm_seek2(ifP, &rasterPos, sizeof(rasterPos)); /* Figure out TIFF parameters. */ - computeRasterParm(&pam, chv, colors, grayscale, + computeRasterParm(&pam, chv, colorCt, grayscale, cmdline.compression, cmdline.minisblack, cmdline.miniswhite, cmdline.indexsizeAllowed, @@ -1172,10 +1223,10 @@ convertImage(FILE * const ifP, cht = NULL; tiffColorMap = NULL; } else { - createTiffColorMap(&pam, bitspersample, chv, colors, &tiffColorMap); + createTiffColorMap(&pam, bitspersample, chv, colorCt, &tiffColorMap); /* Convert color vector to color hash table, for fast lookup. */ - cht = pnm_computetupletablehash(&pam, chv, colors); + cht = pnm_computetupletablehash(&pam, chv, colorCt); pnm_freetupletable(&pam, chv); } @@ -1193,9 +1244,6 @@ convertImage(FILE * const ifP, - - - int main(int argc, const char *argv[]) { CmdlineInfo cmdline; @@ -1205,7 +1253,7 @@ main(int argc, const char *argv[]) { int ofd; int eof; unsigned int imageSeq; - + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -1229,7 +1277,7 @@ main(int argc, const char *argv[]) { break; } - eof = FALSE; /* initial assumption */ + eof = false; /* initial assumption */ imageSeq = 0; while (!eof) { @@ -1254,9 +1302,11 @@ main(int argc, const char *argv[]) { } } - destroyTiffGenerator(cmdline.writeMethod, tifP, ofd); + closeTiffGenerator(cmdline.writeMethod, tifP, ofd); pm_close(ifP); + freeCmdline(cmdline); + return 0; } diff --git a/converter/other/pamtouil.c b/converter/other/pamtouil.c index ee7f5ae6..01858cbc 100644 --- a/converter/other/pamtouil.c +++ b/converter/other/pamtouil.c @@ -13,6 +13,7 @@ ** implied warranty. */ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _BSD_SOURCE /* Make sure string.h contains strdup() */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #include <ctype.h> diff --git a/converter/other/pamtowinicon.c b/converter/other/pamtowinicon.c index 7e2c9e86..3d77d731 100644 --- a/converter/other/pamtowinicon.c +++ b/converter/other/pamtowinicon.c @@ -643,7 +643,7 @@ writePng(const struct pam * const pamP, if (haveAlpha || haveAnd) { const char * alphaFileName; - const char * command; + const char * alphaOpt; if (haveAlpha) makeAlphaFile(pamP, tuples, alphaPlane, &alphaFileName); @@ -653,19 +653,19 @@ writePng(const struct pam * const pamP, strcpy (pam.tuple_type, pam.depth == 3 ? PAM_PPM_TUPLETYPE: PAM_PGM_TUPLETYPE); - pm_asprintf(&command, "pnmtopng -alpha=\"%s\"", alphaFileName); + pm_asprintf(&alphaOpt, "-alpha=%s", alphaFileName); - pm_system(pm_feed_from_pamtuples, &pamTuples, - acceptToFile, &acceptParm, - command); + pm_system_lp("pnmtopng", pm_feed_from_pamtuples, &pamTuples, + acceptToFile, &acceptParm, + "pnmtopng", alphaOpt, NULL); - pm_strfree(command); + pm_strfree(alphaOpt); unlink(alphaFileName); } else { - pm_system(pm_feed_from_pamtuples, &pamTuples, - acceptToFile, &acceptParm, - "pnmtopng"); + pm_system_lp("pnmtopng", pm_feed_from_pamtuples, &pamTuples, + acceptToFile, &acceptParm, + "pnmtopng", NULL); } *sizeP = pngSize; diff --git a/converter/other/pclxl.h b/converter/other/pclxl.h index b1d1c043..5b3eae4b 100644 --- a/converter/other/pclxl.h +++ b/converter/other/pclxl.h @@ -48,7 +48,7 @@ enum DataOrg { }; enum DataSource { - eDefault = 0 + eDefaultDataSource = 0 }; enum DataType { @@ -58,9 +58,9 @@ enum DataType { eSint16 = 3 }; -enum DitherMatrix { +enum DitherMatrix { eDeviceBest = 0 -}; +}; enum DuplexPageMode { @@ -109,7 +109,7 @@ enum Measure { }; enum MediaSource { - eDefaultSource = 0, + eDefaultMediaSource = 0, eAutoSelect = 1, eManualFeed = 2, eMultiPurposeTray = 3, @@ -246,7 +246,7 @@ enum Attribute { aYSpacingData = 176, aCharBoldValue = 177 }; - + enum Operator { oBeginSession = 0x41, oEndSession = 0x42, @@ -317,7 +317,7 @@ enum Operator { oPiePath = 0x9f, oRectangle = 0xa0, oRectanglePath = 0xa1, - oRoundRectangle = 0xa2, + oRoundRectangle = 0xa2, oRoundRectanglePath = 0xa3, oText = 0xa8, oTextPath = 0xa9, @@ -384,7 +384,7 @@ struct sPaperFormat { enum { eSTART, eRLE, - eLIT + eLIT } RLEstates; #endif diff --git a/converter/other/pdbimgtopam.c b/converter/other/pdbimgtopam.c index 3cb4129a..67044109 100644 --- a/converter/other/pdbimgtopam.c +++ b/converter/other/pdbimgtopam.c @@ -97,6 +97,8 @@ parseCommandLine(int argc, const char ** argv, cmdlineP->inputFileName = argv[1]; else pm_error("Program takes at most one argument: input file name"); + + free(option_def); } @@ -211,7 +213,8 @@ readCompressed(IMAGE * const imgP, if (end_offset == UNKNOWN_OFFSET) { /* - * Read until EOF. Some of them have an extra zero byte + * Read sufficient amount for worst-case compressed image, + * or until EOF. Some of them have an extra zero byte * dangling off the end. I originally thought this was * an empty note record (even though there was no record * header for it); however, the release notes for Image @@ -221,12 +224,20 @@ readCompressed(IMAGE * const imgP, * this extra byte and ignore it by paying attention to * the image dimensions. */ - MALLOCARRAY(buffer, ipdb_img_size(imgP)); + size_t const maxCompressedSizeWithBloat = ipdb_img_size(imgP) * 2; + /* + * Provide a buffer large enough for the worst case. + * See note in lib/util/runlength.c . + * We do not use pm_rlenc_allocoutbuf() because there is no + * guarantee that the encoder that produced the image was + * efficient. + */ + MALLOCARRAY(buffer, maxCompressedSizeWithBloat); if (buffer == NULL) retval = ENOMEM; else { - dataSize = fread(buffer, 1, ipdb_img_size(imgP), fP); + dataSize = fread(buffer, 1, maxCompressedSizeWithBloat, fP); if (dataSize <= 0) retval = EIO; else @@ -307,6 +318,8 @@ imageReadData(FILE * const fileP, IMAGE * const imgP, uint32_t const end_offset) { + size_t const imageSize = ipdb_img_size(imgP); + int retval; size_t dataSize; uint8_t * buffer; @@ -318,14 +331,24 @@ imageReadData(FILE * const fileP, * Compressed data can cross row boundaries so we decompress * the data here to avoid messiness in the row access functions. */ - if (dataSize != ipdb_img_size(imgP)) { - decompress(buffer, dataSize, ipdb_img_size(imgP), &imgP->data); + if (dataSize < imageSize || imgP->version == 1) { + if (imgP->version == 0) + pm_message("Image header says raster data is uncompressed. " + "Encountered only %u instead of the " + "required %u bytes. Assuming compressed mode.", + (unsigned)dataSize, (unsigned)imageSize); + decompress(buffer, dataSize, imageSize, &imgP->data); if (imgP->data == NULL) retval = ENOMEM; else imgP->compressed = true; free(buffer); } else { + if (dataSize > imageSize) + pm_message("Image header says raster data is uncompressed. " + "Encountered %u instead of the required %u bytes. " + "Assuming uncompressed mode.", + (unsigned)dataSize, (unsigned)imageSize); imgP->compressed = false; imgP->data = buffer; /* Storage at 'buffer' now belongs to *imgP */ diff --git a/converter/other/pgmtoppm.c b/converter/other/pgmtoppm.c index f8a69424..c3a26594 100644 --- a/converter/other/pgmtoppm.c +++ b/converter/other/pgmtoppm.c @@ -10,6 +10,7 @@ ** implied warranty. */ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _BSD_SOURCE /* Make sure strdup() is in <string.h> */ #include <string.h> diff --git a/converter/other/pngtopam.c b/converter/other/pngtopam.c index 8743174e..1023c6c6 100644 --- a/converter/other/pngtopam.c +++ b/converter/other/pngtopam.c @@ -64,12 +64,12 @@ static bool verbose; static void -parseCommandLine(int argc, +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. + 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. @@ -90,13 +90,13 @@ parseCommandLine(int argc, MALLOCARRAY(option_def, 100); option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "verbose", OPT_FLAG, NULL, + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); - OPTENT3(0, "alpha", OPT_FLAG, NULL, + OPTENT3(0, "alpha", OPT_FLAG, NULL, &alphaSpec, 0); - OPTENT3(0, "alphapam", OPT_FLAG, NULL, + OPTENT3(0, "alphapam", OPT_FLAG, NULL, &alphapamSpec, 0); - OPTENT3(0, "mix", OPT_FLAG, NULL, + OPTENT3(0, "mix", OPT_FLAG, NULL, &mixSpec, 0); OPTENT3(0, "background", OPT_STRING, &cmdlineP->background, &backgroundSpec, 0); @@ -104,9 +104,9 @@ parseCommandLine(int argc, &cmdlineP->gammaSpec, 0); OPTENT3(0, "text", OPT_STRING, &cmdlineP->text, &textSpec, 0); - OPTENT3(0, "time", OPT_FLAG, NULL, + OPTENT3(0, "time", OPT_FLAG, NULL, &cmdlineP->time, 0); - OPTENT3(0, "byrow", OPT_FLAG, NULL, + OPTENT3(0, "byrow", OPT_FLAG, NULL, &cmdlineP->byrow, 0); opt.opt_table = option_def; @@ -248,7 +248,7 @@ computePngLineSize(struct pngx * const pngxP) { if (UINT_MAX / bytesPerSample / samplesPerPixel < pngx_imageWidth(pngxP)) pm_error("Width %u of PNG is uncomputably large", pngx_imageWidth(pngxP)); - + return pngx_imageWidth(pngxP) * bytesPerSample * samplesPerPixel; } @@ -370,7 +370,7 @@ reader_createRowByRow(struct pngx * const pngxP, readerP->pngRaster = NULL; - MALLOCARRAY(readerP->rowBuf, computePngLineSize(pngxP)); + MALLOCARRAY(readerP->rowBuf, computePngLineSize(pngxP)); if (!readerP->rowBuf) pm_error("Could not allocate %u bytes for a PNG row buffer", @@ -393,7 +393,7 @@ reader_destroy(Reader * const readerP) { if (readerP->pngRaster) freePngRaster(readerP->pngRaster, readerP->pngxP); - + if (readerP->rowBuf) free(readerP->rowBuf); @@ -434,14 +434,14 @@ getPngVal(const png_byte ** const pp, int const bitDepth) { png_uint_16 c; - + if (bitDepth == 16) c = *(*pp)++ << 8; else c = 0; c |= *(*pp)++; - + return c; } @@ -498,7 +498,7 @@ setTuple(const struct pam * const pamP, tuple[PAM_GRN_PLANE] = foreground.g; tuple[PAM_BLU_PLANE] = foreground.b; tuple[PAM_TRN_PLANE] = alpha; - } + } } else { assert(alphaHandling == ALPHA_MIX); @@ -540,7 +540,7 @@ saveText(struct pngx * const pngxP, while (text.line[i].key[j] != '\0' && text.line[i].key[j] != ' ') - ++j; + ++j; if (text.line[i].key[j] != ' ') { fprintf(tfP, "%s", text.line[i].key); @@ -552,7 +552,7 @@ saveText(struct pngx * const pngxP, putc(' ', tfP); } putc(' ', tfP); /* at least one space between key and text */ - + for (j = 0; j < text.line[i].text_length; ++j) { putc(text.line[i].text[j], tfP); if (text.line[i].text[j] == '\n') { @@ -607,11 +607,11 @@ dumpTypeAndFilter(struct pngx * const pngxP) { case PNG_COLOR_TYPE_GRAY: typeString = "gray"; break; - + case PNG_COLOR_TYPE_GRAY_ALPHA: typeString = "gray+alpha"; break; - + case PNG_COLOR_TYPE_PALETTE: typeString = "palette"; break; @@ -630,13 +630,13 @@ dumpTypeAndFilter(struct pngx * const pngxP) { pm_asprintf(&filterString, "base filter"); break; default: - pm_asprintf(&filterString, "unknown filter type %d", + pm_asprintf(&filterString, "unknown filter type %d", pngx_filterType(pngxP)); } pm_message("%s, %s, %s", typeString, - pngx_interlaceType(pngxP) ? + pngx_interlaceType(pngxP) ? "Adam7 interlaced" : "not interlaced", filterString); @@ -679,7 +679,7 @@ dumpPngInfo(struct pngx * const pngxP) { pngx_gama(pngxP)); else pm_message("gAMA chunk (image gamma): not present"); - + if (pngx_chunkIsPresent(pngxP, PNG_INFO_sBIT)) pm_message("sBIT chunk: present"); else @@ -739,7 +739,7 @@ transColor(struct pngx * const pngxP) { struct pngx_trns const trans = pngx_trns(pngxP); assert(pngx_chunkIsPresent(pngxP, PNG_INFO_tRNS)); - + return trans.transColor; } @@ -775,7 +775,7 @@ isTransparentColor(pngcolor const color, We could fix this by not letting libpng gamma-correct the pixels, and just do it ourselves. */ - + switch (pngx_colorType(pngxP)) { case PNG_COLOR_TYPE_GRAY: retval = color.r == gammaCorrect(transColor16.gray, gamma, @@ -788,7 +788,7 @@ isTransparentColor(pngcolor const color, pngxP->maxval)); } } - } else + } else retval = FALSE; return retval; @@ -810,7 +810,7 @@ setupGammaCorrection(struct pngx * const pngxP, use *gammaCorrectionP to do it). 'screenGammaIsKnown' means we know what the screen gamma is, and it is - 'screenGamma'. If we don't know what the screen gamma is, gamma + 'screenGamma'. If we don't know what the screen gamma is, gamma correction is not possible, so we set up for no gamma correction. The gamma correction we ordain is a combination of the image gamma, @@ -845,7 +845,7 @@ setupGammaCorrection(struct pngx * const pngxP, gammaCorrectionP->needCorrection = true; gammaCorrectionP->gamma = imageGamma * screenGamma; /* In case of gamma-corrections, sBIT's as in the - PNG-file are not valid anymore + PNG-file are not valid anymore */ pngx_removeChunk(pngxP, PNG_INFO_sBIT); if (verbose) @@ -870,7 +870,7 @@ paletteHasPartialTransparency(struct pngx * const pngxP) { bool foundGray; unsigned int i; - + for (i = 0, foundGray = FALSE; i < trans.numTrans && !foundGray; ++i) { @@ -945,7 +945,7 @@ getComponentSbit(struct pngx * const pngxP, /* We care about both the foreground and the alpha */ bool fgNotUniform; png_byte fgSbit; - + getComponentSbitFg(pngxP, &fgSbit, &fgNotUniform); if (fgNotUniform) @@ -961,7 +961,7 @@ getComponentSbit(struct pngx * const pngxP, } } - + static void shiftPalette(struct pngx * const pngxP, @@ -977,9 +977,9 @@ shiftPalette(struct pngx * const pngxP, shift); else { struct pngx_plte const palette = pngx_plte(pngxP); - + unsigned int i; - + for (i = 0; i < palette.size; ++i) { palette.palette[i].red >>= (8 - shift); palette.palette[i].green >>= (8 - shift); @@ -1004,7 +1004,7 @@ computeMaxvalFromSbit(struct pngx * const pngxP, 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 + is used */ bool notUniform; @@ -1043,7 +1043,7 @@ computeMaxvalFromSbit(struct pngx * const pngxP, "writing file with %u bits", componentSigBit); *maxvalP = (1l << componentSigBit) - 1; *succeededP = true; - + if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_PALETTE) shiftPalette(pngxP, componentSigBit); else @@ -1070,7 +1070,7 @@ setupSignificantBits(struct pngx * const pngxP, Also set up *pngxP for the corresponding significant bits. -----------------------------------------------------------------------------*/ bool gotItFromSbit; - + if (pngx_chunkIsPresent(pngxP, PNG_INFO_sBIT)) computeMaxvalFromSbit(pngxP, alphaHandling, &pngxP->maxval, &gotItFromSbit, errorLevelP); @@ -1119,7 +1119,7 @@ imageHasColor(struct pngx * const pngxP) { bool foundColor; unsigned int i; - + for (i = 0, foundColor = FALSE; i < palette.size && !foundColor; ++i) { @@ -1148,7 +1148,7 @@ determineOutputType(struct pngx * const pngxP, /* The output is a old style pseudo-PNM transparency image */ *depthP = 1; *formatP = maxval > 1 ? PGM_FORMAT : PBM_FORMAT; - } else { + } else { /* The output is a normal Netpbm image */ bool const outputIsColor = imageHasColor(pngxP) || !isGrayscale(bgColor); @@ -1191,7 +1191,7 @@ getBackgroundColor(struct pngx * const pngxP, 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. + which is a bit arbitrary. */ pixel const backcolor = ppm_parsecolor(requestedColor, maxval); @@ -1207,12 +1207,12 @@ getBackgroundColor(struct pngx * const pngxP, switch (pngx_colorType(pngxP)) { case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: - bgColorP->r = bgColorP->g = bgColorP->b = + bgColorP->r = bgColorP->g = bgColorP->b = gammaCorrect(background.gray, gamma, pngxP->maxval); break; case PNG_COLOR_TYPE_PALETTE: { struct pngx_plte const palette = pngx_plte(pngxP); - png_color const rawBgcolor = + png_color const rawBgcolor = palette.palette[background.index]; *bgColorP = gammaCorrectColor(pngcolorFromByte(rawBgcolor), gamma, pngxP->maxval); @@ -1221,13 +1221,13 @@ getBackgroundColor(struct pngx * const pngxP, case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: { png_color_16 const rawBgcolor = background; - + *bgColorP = gammaCorrectColor(pngcolorFrom16(rawBgcolor), gamma, pngxP->maxval); } break; } - } else + } else /* when no background given, we use white [from version 2.37] */ bgColorP->r = bgColorP->g = bgColorP->b = maxval; } @@ -1345,7 +1345,7 @@ makeTupleRow(const struct pam * const pamP, pngxP, paletteAlpha(pngxP, index, pngxP->maxval)); } break; - + case PNG_COLOR_TYPE_RGB: { pngcolor fgColor; @@ -1403,7 +1403,7 @@ reportOutputFormat(const struct pam * const pamP) { assert(false); /* Every possible value handled above */ } } - + static void @@ -1449,9 +1449,9 @@ writeNetpbm(struct pam * const pamP, -static void -convertpng(FILE * const ifP, - FILE * const tfP, +static void +convertpng(FILE * const ifP, + FILE * const tfP, struct CmdlineInfo const cmdline, int * const errorLevelP) { @@ -1487,7 +1487,7 @@ convertpng(FILE * const ifP, getBackgroundColor(pngxP, cmdline.background, gamma, pngxP->maxval, &bgColor); - + pam.size = sizeof(pam); pam.len = PAM_STRUCT_SIZE(tuple_type); pam.file = stdout; @@ -1499,7 +1499,7 @@ convertpng(FILE * const ifP, determineOutputType(pngxP, cmdline.alpha, bgColor, pngxP->maxval, &pam.format, &pam.depth, pam.tuple_type); - rasterReaderP = cmdline.byrow ? + rasterReaderP = cmdline.byrow ? reader_createRowByRow(pngxP, ifP) : reader_createAllAtOnce(pngxP, ifP); writeNetpbm(&pam, pngxP, rasterReaderP, bgColor, @@ -1516,7 +1516,7 @@ convertpng(FILE * const ifP, -int +int main(int argc, const char *argv[]) { struct CmdlineInfo cmdline; diff --git a/converter/other/pngx.c b/converter/other/pngx.c index 185b4a27..4bb09421 100644 --- a/converter/other/pngx.c +++ b/converter/other/pngx.c @@ -1,3 +1,4 @@ +#include <stdbool.h> #include <assert.h> #include <png.h> #include "pm_c_util.h" @@ -59,6 +60,7 @@ pngx_create(struct pngx ** const pngxPP, if (!pngxP) pm_error("Failed to allocate memory for PNG object"); else { + pngxP->infoPrepared = false; pngxP->numPassesRequired = 1; switch(rw) { @@ -347,7 +349,7 @@ void pngx_setChrm(struct pngx * const pngxP, struct pngx_chroma const chroma) { - png_set_cHRM(pngxP->png_ptr, pngxP->info_ptr, + png_set_cHRM(pngxP->png_ptr, pngxP->info_ptr, chroma.wx, chroma.wy, chroma.rx, chroma.ry, chroma.gx, chroma.gy, @@ -466,6 +468,37 @@ pngx_setIhdr(struct pngx * const pngxP, void pngx_setInterlaceHandling(struct pngx * const pngxP) { + /* The documentation is vague and contradictory on what this does, but + what it appears from reasoning and experimentation to do is the + following. + + It applies to reading and writing by rows (png_write_row, png_read_row) + as opposed to whole image (png_write_image, png_read_image). It has + no effect on whole image read and write. + + This is not what makes an image interlaced or tells the decompressor + that it is interlaced. All it does is control how you you read and + write the raster when the image is interlaced. It has no effect if the + image is not interlaced. (You make an image interlaced by setting the + IHDR; the decompressor finds out from the IHDR that it is interlaced). + + In the write case, it controls whether you construct the subimages + yourself and feed them to libpng in sequence or you feed libpng the + entire image multiple times and libpng picks out the pixels appropriate + for each subimage in each pass. + + In the read case, it controls whether you get the raw subimages and you + assemble them into the full image or you read the whole image multiple + times into the same buffer, with the pixels that belong to each + subimage being filled in on each pass. + + Note that the only kind of interlacing that exists today is ADAM7 and + consequently, the number of passes is always 1 (for no interlacing) or + 7 (for interlacing). + */ + if (!pngxP->infoPrepared) + pm_error("pngx_setInterlaceHandling must not be called before " + "pngx_writeInfo or pngx_readInfo"); pngxP->numPassesRequired = png_set_interlace_handling(pngxP->png_ptr); } @@ -475,6 +508,10 @@ pngx_setInterlaceHandling(struct pngx * const pngxP) { void pngx_setPacking(struct pngx * const pngxP) { + if (!pngxP->infoPrepared) + pm_error("pngx_setPacking must not be called before " + "pngx_writeInfo or pngx_readInfo"); + png_set_packing(pngxP->png_ptr); } @@ -484,7 +521,7 @@ void pngx_setPhys(struct pngx * const pngxP, struct pngx_phys const phys) { - png_set_pHYs(pngxP->png_ptr, pngxP->info_ptr, + png_set_pHYs(pngxP->png_ptr, pngxP->info_ptr, phys.x, phys.y, phys.unit); } @@ -516,7 +553,19 @@ pngx_setSbit(struct pngx * const pngxP, void pngx_setShift(struct pngx * const pngxP, png_color_8 const sigBitArg) { - +/*---------------------------------------------------------------------------- + Tell the number of significant bits in the row buffers that will be given + to the compressor. Those bits are the least significant of the 8 bits of + space in the row buffer for each sample. For example, if red sample values + are in the range 0-7, only the lower 3 bits of the 8-bit byte for each + red sample will be used, so one would call this with sigBitArg.red == 3. + + The name alludes to the fact that to normalize the sample to 8 bits, one + shifts it left, and this function tells how much shift has to happen. In + the example above, each red sample has to be shifted left 5 bits (so that + the upper 3 bits are significant and the lower 5 bits are always zero) to + create an 8 bit sample out of the 3 bit samples. +-----------------------------------------------------------------------------*/ png_color_8 sigBit; sigBit = sigBitArg; @@ -651,6 +700,8 @@ void pngx_readInfo(struct pngx * const pngxP) { png_read_info(pngxP->png_ptr, pngxP->info_ptr); + + pngxP->infoPrepared = true; } @@ -659,6 +710,8 @@ void pngx_writeInfo(struct pngx * const pngxP) { png_write_info(pngxP->png_ptr, pngxP->info_ptr); + + pngxP->infoPrepared = true; } @@ -688,7 +741,7 @@ pngx_readStart(struct pngx * const pngxP, FILE * const ifP) { size_t sigByteCt; - + verifyFileIsPng(ifP, &sigByteCt); /* Declare that we already read the signature bytes */ @@ -733,9 +786,18 @@ pngx_writeRow(struct pngx * const pngxP, void +pngx_writeImage(struct pngx * const pngxP, + png_byte ** const raster) { + + png_write_image(pngxP->png_ptr, (png_byte **)raster); +} + + + +void pngx_readEnd(struct pngx * const pngxP) { - /* Note that some of info_ptr is not defined until png_read_end() + /* Note that some of info_ptr is not defined until png_read_end() completes. That's because it comes from chunks that are at the end of the stream. In particular, text and time chunks may be at the end. Furthermore, they may be in both places, in diff --git a/converter/other/pngx.h b/converter/other/pngx.h index 81e0dc55..f4701bb2 100644 --- a/converter/other/pngx.h +++ b/converter/other/pngx.h @@ -1,7 +1,12 @@ #ifndef PNGX_H_INCLUDED #define PNGX_H_INCLUDED +#include <stdbool.h> #include <png.h> + /* This includes the Zlib interface header file zlib.h because libpng uses + libz and some of the Zlib interface, e.g. the Z_DEFLATED constant, + is part of the libpng interface. + */ #include "pm_c_util.h" /* pngx is designed to be an extension of the PNG library to make using @@ -49,10 +54,16 @@ struct pngx { pngx_rw rw; png_uint_16 maxval; unsigned int numPassesRequired; - /* The number of times we have write the complete image to the + /* The number of times we have to write the complete image to the compressor. This is more than one when the compressor is set up to do an interlaced format. */ + bool infoPrepared; + /* png_write_info or png_read_info has been called, so libpng is in a + state in which things such as png_set_interlace_handling will work. + These functions use information in *png_ptr that is set by + png_XXX_info. + */ }; void @@ -266,6 +277,10 @@ pngx_writeRow(struct pngx * const pngxP, const png_byte * const line); void +pngx_writeImage(struct pngx * const pngxP, + png_byte ** const raster); + +void pngx_readEnd(struct pngx * const pngxP); void diff --git a/converter/other/pnmtoddif.c b/converter/other/pnmtoddif.c index ae8c8524..ac02e425 100644 --- a/converter/other/pnmtoddif.c +++ b/converter/other/pnmtoddif.c @@ -538,15 +538,12 @@ convertRaster(FILE * const ifP, unsigned int const bytesPerLine) { unsigned char * data; - unsigned char * p; MALLOCARRAY(data, bytesPerLine); if (data == NULL) pm_error("Couldn't allocate %u-byte line buffer", bytesPerLine); - p = data; /* initial value */ - switch (PNM_FORMAT_TYPE(format)) { case PBM_TYPE: convertPbmRaster(ifP, format, cols, rows, ofP, bytesPerLine, data); diff --git a/converter/other/pnmtojpeg.c b/converter/other/pnmtojpeg.c index 7e7272a0..44826245 100644 --- a/converter/other/pnmtojpeg.c +++ b/converter/other/pnmtojpeg.c @@ -16,6 +16,7 @@ *****************************************************************************/ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ diff --git a/converter/other/pnmtopalm/palm.h b/converter/other/pnmtopalm/palm.h index 718a66cf..0edf9a28 100644 --- a/converter/other/pnmtopalm/palm.h +++ b/converter/other/pnmtopalm/palm.h @@ -28,9 +28,18 @@ #define PALM_FORMAT_565LE 0x02 /* Palm says internal use only */ #define PALM_FORMAT_INDEXEDLE 0x03 /* Palm says internal use only */ -typedef unsigned long Color_s; +typedef unsigned long ColormapEntry; + /* A entry in a Colormap. It is an encoding of 4 bytes as the integer + that those 4 bytes would represent in pure binary: -typedef Color_s * Color; + MSB 0: the color index + 1: red intensity + 2: green intensity + LSB 3: blue intensity + + The intensities are on a scale with a certain maxval (that must be + specified to interpret a ColormapEntry). + */ typedef struct { unsigned int nentries; @@ -39,24 +48,11 @@ typedef struct { /* number of colors actually in 'color_entries' -- entries are filled from 0 consecutively, one color per entry. */ - Color_s * color_entries; /* Array of colors */ -} Colormap_s; - -typedef Colormap_s * Colormap; + ColormapEntry * color_entries; /* Array of colors */ +} Colormap; qsort_comparison_fn palmcolor_compare_indices; qsort_comparison_fn palmcolor_compare_colors; -Colormap -palmcolor_build_custom_8bit_colormap(unsigned int const rows, - unsigned int const cols, - pixel ** const pixels); - -Colormap -palmcolor_build_default_8bit_colormap(void); - -Colormap -palmcolor_read_colormap (FILE * const ifP); - #endif diff --git a/converter/other/pnmtopalm/palmcolormap.c b/converter/other/pnmtopalm/palmcolormap.c index 0f47558c..1341ca2b 100644 --- a/converter/other/pnmtopalm/palmcolormap.c +++ b/converter/other/pnmtopalm/palmcolormap.c @@ -4,18 +4,46 @@ #include "pm_c_util.h" #include "mallocvar.h" #include "pnm.h" - #include "palm.h" +#include "palmcolormap.h" + + + +static pixval +scaleSample(pixval const arg, + pixval const oldMaxval, + pixval const newMaxval) { + + return (arg * newMaxval + oldMaxval/2) / oldMaxval; +} + + + +ColormapEntry +palmcolor_mapEntryColorFmPixel(pixel const color, + pixval const maxval, + pixval const newMaxval) { + + + return + 0 + | (scaleSample(PPM_GETR(color), maxval, newMaxval) << 16) + | (scaleSample(PPM_GETG(color), maxval, newMaxval) << 8) + | (scaleSample(PPM_GETB(color), maxval, newMaxval) << 0); +} + + + int palmcolor_compare_indices(const void * const p1, const void * const p2) { /*---------------------------------------------------------------------------- This is a 'qsort' collation function. -----------------------------------------------------------------------------*/ - if ((*((Color) p1) & 0xFF000000) < (*((Color) p2) & 0xFF000000)) + if ((*((ColormapEntry *) p1) & 0xFF000000) < (*((ColormapEntry *) p2) & 0xFF000000)) return -1; - else if ((*((Color) p1) & 0xFF000000) > (*((Color) p2) & 0xFF000000)) + else if ((*((ColormapEntry *) p1) & 0xFF000000) > (*((ColormapEntry *) p2) & 0xFF000000)) return 1; else return 0; @@ -165,86 +193,88 @@ static int PalmPalette8bpp[256][3] = -Colormap +Colormap * palmcolor_build_default_8bit_colormap(void) { unsigned int i; - Colormap cm; + Colormap * cmP; - MALLOCVAR_NOFAIL(cm); - cm->nentries = 232; - MALLOCARRAY_NOFAIL(cm->color_entries, cm->nentries); + MALLOCVAR_NOFAIL(cmP); + cmP->nentries = 232; + MALLOCARRAY_NOFAIL(cmP->color_entries, cmP->nentries); /* Fill in the colors */ for (i = 0; i < 231; ++i) { - cm->color_entries[i] = ((i << 24) | + cmP->color_entries[i] = ((i << 24) | (PalmPalette8bpp[i][0] << 16) | (PalmPalette8bpp[i][1] << 8) | (PalmPalette8bpp[i][2])); } - cm->color_entries[231] = 0xFF000000; - cm->ncolors = 232; + cmP->color_entries[231] = 0xFF000000; + cmP->ncolors = 232; /* now sort the table */ - qsort (cm->color_entries, cm->ncolors, sizeof(Color_s), - palmcolor_compare_colors); - return cm; + qsort(cmP->color_entries, cmP->ncolors, sizeof(ColormapEntry), + palmcolor_compare_colors); + return cmP; } -Colormap -palmcolor_build_custom_8bit_colormap(unsigned int const rows, +Colormap * +palmcolor_build_custom_8bit_colormap(pixel ** const pixels, + unsigned int const rows, unsigned int const cols, - pixel ** const pixels) { + pixval const maxval) { + unsigned int row; - Colormap colormap; + Colormap * colormapP; - MALLOCVAR_NOFAIL(colormap); - colormap->nentries = 256; - MALLOCARRAY_NOFAIL(colormap->color_entries, colormap->nentries); - colormap->ncolors = 0; /* initial value */ + MALLOCVAR_NOFAIL(colormapP); + colormapP->nentries = 256; + MALLOCARRAY_NOFAIL(colormapP->color_entries, colormapP->nentries); + colormapP->ncolors = 0; /* initial value */ for (row = 0; row < rows; ++row) { unsigned int col; for (col = 0; col < cols; ++col) { - Color found; - Color_s temp; - - temp = ((PPM_GETR(pixels[row][col]) << 16) | - (PPM_GETG(pixels[row][col]) << 8) | - PPM_GETB(pixels[row][col])); - found = (bsearch (&temp, - colormap->color_entries, colormap->ncolors, - sizeof(Color_s), palmcolor_compare_colors)); - if (!found) { - if (colormap->ncolors >= colormap->nentries) + ColormapEntry * foundEntryP; + ColormapEntry const searchTarget = + palmcolor_mapEntryColorFmPixel(pixels[row][col], maxval, 255); + + foundEntryP = + bsearch(&searchTarget, + colormapP->color_entries, colormapP->ncolors, + sizeof(ColormapEntry), palmcolor_compare_colors); + if (!foundEntryP) { + if (colormapP->ncolors >= colormapP->nentries) pm_error("Too many colors for custom colormap " - "(max 256). " + "(max %u). " "Try using pnmquant to reduce the number " - "of colors."); + "of colors.", colormapP->nentries); else { /* add the new color, and re-sort */ - temp |= ((colormap->ncolors) << 24); - colormap->color_entries[colormap->ncolors] = temp; - colormap->ncolors += 1; - qsort(colormap->color_entries, colormap->ncolors, - sizeof(Color_s), palmcolor_compare_colors); + unsigned int const colorIndex = colormapP->ncolors++; + ColormapEntry const newEntry = + searchTarget | (colorIndex << 24); + colormapP->color_entries[colorIndex] = newEntry; + qsort(colormapP->color_entries, colormapP->ncolors, + sizeof(ColormapEntry), palmcolor_compare_colors); } } } } - return colormap; + return colormapP; } -Colormap +Colormap * palmcolor_read_colormap (FILE * const ifP) { unsigned short ncolors; - Colormap retval; + Colormap * retval; int rc; rc = pm_readbigshort(ifP, (short *) &ncolors); @@ -252,13 +282,13 @@ palmcolor_read_colormap (FILE * const ifP) { retval = NULL; else { long colorentry; - Colormap colormap; + Colormap * colormapP; unsigned int i; bool error; - MALLOCVAR_NOFAIL(colormap); - colormap->nentries = ncolors; - MALLOCARRAY_NOFAIL(colormap->color_entries, colormap->nentries); + MALLOCVAR_NOFAIL(colormapP); + colormapP->nentries = ncolors; + MALLOCARRAY_NOFAIL(colormapP->color_entries, colormapP->nentries); for (i = 0, error = FALSE; i < ncolors && !error; ++i) { int rc; @@ -266,15 +296,15 @@ palmcolor_read_colormap (FILE * const ifP) { if (rc != 0) error = TRUE; else - colormap->color_entries[i] = (colorentry & 0xFFFFFFFF); + colormapP->color_entries[i] = (colorentry & 0xFFFFFFFF); } if (error) { - free (colormap->color_entries); - free (colormap); + free (colormapP->color_entries); + free (colormapP); retval = NULL; } else { - colormap->ncolors = ncolors; - retval = colormap; + colormapP->ncolors = ncolors; + retval = colormapP; } } return retval; diff --git a/converter/other/pnmtopalm/palmcolormap.h b/converter/other/pnmtopalm/palmcolormap.h new file mode 100644 index 00000000..cbdb2031 --- /dev/null +++ b/converter/other/pnmtopalm/palmcolormap.h @@ -0,0 +1,25 @@ +#ifndef PALMCOLORMAP_H_INCLUDED +#define PALMCOLORMAP_H_INCLUDED + +#include <stdio.h> +#include "ppm.h" +#include "palm.h" + +ColormapEntry +palmcolor_mapEntryColorFmPixel(pixel const color, + pixval const maxval, + pixval const newMaxval); + +Colormap * +palmcolor_build_custom_8bit_colormap(pixel ** const pixels, + unsigned int const rows, + unsigned int const cols, + pixval const maxval); + +Colormap * +palmcolor_build_default_8bit_colormap(void); + +Colormap * +palmcolor_read_colormap (FILE * const ifP); + +#endif diff --git a/converter/other/pnmtopalm/palmtopnm.c b/converter/other/pnmtopalm/palmtopnm.c index 0f76207d..b3c0321a 100644 --- a/converter/other/pnmtopalm/palmtopnm.c +++ b/converter/other/pnmtopalm/palmtopnm.c @@ -21,17 +21,18 @@ #include "mallocvar.h" #include "palm.h" +#include "palmcolormap.h" -enum palmCompressionType { - COMPRESSION_NONE, - COMPRESSION_RLE, +enum PalmCompressionType { + COMPRESSION_NONE, + COMPRESSION_RLE, COMPRESSION_SCANLINE, COMPRESSION_PACKBITS }; -struct palmHeader { +struct PalmHeader { unsigned short cols; unsigned short rows; unsigned short bytesPerRow; @@ -46,7 +47,7 @@ struct palmHeader { unsigned int pixelSize; unsigned char version; unsigned int transparentIndex; - enum palmCompressionType compressionType; + enum PalmCompressionType compressionType; /* version 3 encoding specific */ unsigned char size; unsigned char pixelFormat; @@ -56,7 +57,7 @@ struct palmHeader { -struct directPixelFormat { +struct DirectPixelFormat { unsigned int redbits; unsigned int greenbits; unsigned int bluebits; @@ -64,15 +65,15 @@ struct directPixelFormat { -struct directColorInfo { - struct directPixelFormat pixelFormat; - Color_s transparentColor; +struct DirectColorInfo { + struct DirectPixelFormat pixelFormat; + ColormapEntry transparentColor; }; -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -85,13 +86,13 @@ struct cmdlineInfo { static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo *cmdlineP) { +parseCommandLine(int argc, const char ** argv, + struct CmdlineInfo *cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. -----------------------------------------------------------------------------*/ - optEntry *option_def = malloc( 100*sizeof( optEntry ) ); + optEntry * option_def; /* Instructions to pm_optParseOptions3 on how to parse our options. */ optStruct3 opt; @@ -100,6 +101,8 @@ parseCommandLine(int argc, char ** argv, unsigned int option_def_index; + MALLOCARRAY_NOFAIL(option_def, 100); + option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); @@ -107,23 +110,23 @@ parseCommandLine(int argc, char ** argv, &cmdlineP->showhist, 0); OPTENT3(0, "transparent", OPT_FLAG, NULL, &cmdlineP->transparent, 0); - OPTENT3(0, "rendition", OPT_UINT, &cmdlineP->rendition, + OPTENT3(0, "rendition", OPT_UINT, &cmdlineP->rendition, &renditionSpec, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We may have parms that are negative numbers */ - pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (renditionSpec) { if (cmdlineP->rendition < 1) pm_error("The -rendition value must be at least 1"); - } else + } else cmdlineP->rendition = 1; - + if (cmdlineP->transparent && cmdlineP->showhist) pm_error("You can't specify -showhist with -transparent"); @@ -135,12 +138,13 @@ parseCommandLine(int argc, char ** argv, pm_error("Too many arguments (%d). The only non-option " "argument is the file name", argc-1); } + free(option_def); } static xelval * -createGraymap(unsigned int const ncolors, +createGraymap(unsigned int const ncolors, xelval const maxval) { int i; xelval *map; @@ -154,8 +158,8 @@ createGraymap(unsigned int const ncolors, -static void -skipbytes(FILE * const ifP, +static void +skipbytes(FILE * const ifP, unsigned int const nbytes) { unsigned char buf[256]; @@ -176,15 +180,15 @@ skipbytes(FILE * const ifP, pm_error("Error reading Palm file. Short read."); n = 0; } - } + } } static void interpretCompression(unsigned char const compressionValue, - enum palmCompressionType * const compressionTypeP) { - + enum PalmCompressionType * const compressionTypeP) { + switch (compressionValue) { case PALM_COMPRESSION_RLE: *compressionTypeP = COMPRESSION_RLE; @@ -220,17 +224,18 @@ readRestOfHeaderVersion3(FILE * const ifP, short * const nextDepthOffsetP) { unsigned char unused; - + pm_readcharu(ifP, sizeP); /* should be 0x18, but I can't see why we should really care */ if (*sizeP != 0x18) - pm_message("Strange value for Palm bitmap header size: %hu", *sizeP); + pm_message("Strange value for Palm bitmap header size: %u", + (unsigned)*sizeP); pm_readcharu(ifP, pixelFormatP); if (*pixelFormatP != PALM_FORMAT_INDEXED && *pixelFormatP != PALM_FORMAT_565) pm_error("Unrecognized pixelformat type: %u", *pixelFormatP); - + pm_readcharu(ifP, &unused); @@ -244,15 +249,15 @@ readRestOfHeaderVersion3(FILE * const ifP, *densityP != PALM_DENSITY_TRIPLE && *densityP != PALM_DENSITY_QUADRUPLE) pm_error("Invalid value for -density: %d.", *densityP); - + pm_readbiglong(ifP, transparentValueP); if (pixelSize < 16) *transparentIndexP = *transparentValueP; else *transparentIndexP = 0; - + pm_readbiglong(ifP, nextBitmapOffsetP); - + /* version < 3 specific */ *nextDepthOffsetP = 0; } @@ -269,18 +274,18 @@ readRestOfHeaderOld(FILE * const ifP, long * const transparentValueP, long * const nextBitmapOffsetP, short * const nextDepthOffsetP) { - + short pad; unsigned char transparentIndex; - + pm_readbigshort(ifP, nextDepthOffsetP); pm_readcharu(ifP, &transparentIndex); *transparentIndexP = transparentIndex; - + pm_readcharu(ifP,compressionTypeP); - + pm_readbigshort(ifP, &pad); /* reserved by Palm as of 8/9/00 */ - + /* version 3 specific */ *sizeP = 0; *pixelFormatP = 0; @@ -292,7 +297,7 @@ readRestOfHeaderOld(FILE * const ifP, static void -interpretHeader(struct palmHeader * const palmHeaderP, +interpretHeader(struct PalmHeader * const palmHeaderP, short const cols, short const rows, short const bytesPerRow, @@ -306,7 +311,7 @@ interpretHeader(struct palmHeader * const palmHeaderP, long const transparentValue, unsigned int const transparentIndex, unsigned char const compressionType) { - + palmHeaderP->cols = cols; palmHeaderP->rows = rows; palmHeaderP->bytesPerRow = bytesPerRow; @@ -329,11 +334,11 @@ interpretHeader(struct palmHeader * const palmHeaderP, */ pm_error("PALM_DIRECT_COLOR_FLAG is set but pixelFormat is not" "PALM_FORMAT_565."); - - palmHeaderP->directColor = ((flags & PALM_DIRECT_COLOR_FLAG) || + + palmHeaderP->directColor = ((flags & PALM_DIRECT_COLOR_FLAG) || palmHeaderP->pixelFormat == PALM_FORMAT_565); - - if (flags & PALM_IS_COMPRESSED_FLAG) + + if (flags & PALM_IS_COMPRESSED_FLAG) interpretCompression(compressionType, &palmHeaderP->compressionType); else @@ -345,7 +350,7 @@ interpretHeader(struct palmHeader * const palmHeaderP, static void readHeader(FILE * const ifP, unsigned int const requestedRendition, - struct palmHeader * const palmHeaderP) { + struct PalmHeader * const palmHeaderP) { /*---------------------------------------------------------------------------- Read the Palm Bitmap header from the file 'ifP'. Read past all renditions up to 'requestedRendition' and read the header of that @@ -358,7 +363,7 @@ readHeader(FILE * const ifP, currentRendition = 1; while (!gotHeader) { short cols, rows, bytesPerRow, flags, nextDepthOffset, density; - unsigned char pixelSizeCode, version, compressionType, + unsigned char pixelSizeCode, version, compressionType, size, pixelFormat; long transparentValue, nextBitmapOffset; unsigned int pixelSize, transparentIndex; @@ -367,7 +372,7 @@ readHeader(FILE * const ifP, pm_readbigshort(ifP, &rows); pm_readbigshort(ifP, &bytesPerRow); pm_readbigshort(ifP, &flags); - + pm_readcharu(ifP, &pixelSizeCode); pixelSize = pixelSizeCode == 0 ? 1 : pixelSizeCode; if (pixelSizeCode != 0x00 && @@ -384,12 +389,12 @@ readHeader(FILE * const ifP, "bits per pixel.", bytesPerRow, cols, pixelSize); pm_readcharu(ifP, &version); - if (version > 3) + if (version > 3) pm_error("Unknown encoding version type: %d", version); else if (version == 3) readRestOfHeaderVersion3(ifP, pixelSize, &size, &pixelFormat, &compressionType, - &density, &transparentIndex, + &density, &transparentIndex, &transparentValue, &nextBitmapOffset, &nextDepthOffset); else @@ -400,29 +405,29 @@ readHeader(FILE * const ifP, &nextDepthOffset); if (currentRendition < requestedRendition) { - if (version < 3 && nextDepthOffset == 0 && pixelSizeCode != 0xFF) + if (version < 3 && nextDepthOffset == 0 && pixelSizeCode != 0xFF) pm_error("Not enough renditions in the input Palm Bitmap " "to extract the %dth", requestedRendition); - if (version == 3 && nextBitmapOffset == 0) + if (version == 3 && nextBitmapOffset == 0) pm_error("Not enough renditions in the input Palm Bitmap " "to extract the %dth", requestedRendition); /* nextDepthOffset is calculated in 4 byte words - from the beginning of this bitmap (so it equals its size) + from the beginning of this bitmap (so it equals its size) */ if (version < 3 && pixelSizeCode != 0xFF ) skipbytes(ifP, (nextDepthOffset*4)-16); else if (version == 3) /* FIXME rewrite skipbytes to accept longs? */ - skipbytes(ifP, (short) nextBitmapOffset-24); + skipbytes(ifP, (short) nextBitmapOffset-24); if (pixelSizeCode != 0xFF) ++currentRendition; } else if (pixelSizeCode != 0xFF) { gotHeader = TRUE; - + interpretHeader(palmHeaderP, cols, rows, bytesPerRow, flags, pixelSizeCode, pixelSize, version, size, pixelFormat, density, - transparentValue, transparentIndex, + transparentValue, transparentIndex, compressionType); } } @@ -441,8 +446,8 @@ yesno(bool const arg) { static void -reportPalmHeader(struct palmHeader const palmHeader, - struct directColorInfo const directColorInfo) { +reportPalmHeader(struct PalmHeader const palmHeader, + struct DirectColorInfo const directColorInfo) { const char *ctype; @@ -462,9 +467,9 @@ reportPalmHeader(struct palmHeader const palmHeader, } pm_message("Dimensions: %hu columns x %hu rows", palmHeader.cols, palmHeader.rows); - pm_message("Row layout: %hu bytes per row, %hu bits per pixel", + pm_message("Row layout: %hu bytes per row, %u bits per pixel", palmHeader.bytesPerRow, palmHeader.pixelSize); - pm_message("Pixel Size code: %hu", palmHeader.pixelSizeCode); + pm_message("Pixel Size code: %u", (unsigned)palmHeader.pixelSizeCode); pm_message("Flags: 0x%04hx", palmHeader.flags); pm_message(" Direct Color: %s", yesno(palmHeader.directColor)); pm_message(" Colormap: %s", yesno(palmHeader.hasColormap)); @@ -473,10 +478,10 @@ reportPalmHeader(struct palmHeader const palmHeader, if (palmHeader.hasTransparency) { if (palmHeader.directColor) { /* Copied from doTransparent(...) */ - Color_s const color = directColorInfo.transparentColor; - pm_message("Transparent value: #%02x%02x%02x", - (unsigned int)((color >> 16) & 0xFF), - (unsigned int)((color >> 8) & 0xFF), + ColormapEntry const color = directColorInfo.transparentColor; + pm_message("Transparent value: #%02x%02x%02x", + (unsigned int)((color >> 16) & 0xFF), + (unsigned int)((color >> 8) & 0xFF), (unsigned int)((color >> 0) & 0xFF)); } else pm_message("Transparent index: %u", palmHeader.transparentIndex); @@ -489,7 +494,7 @@ reportPalmHeader(struct palmHeader const palmHeader, static void -determineOutputFormat(struct palmHeader const palmHeader, +determineOutputFormat(struct PalmHeader const palmHeader, int * const formatP, xelval * const maxvalP) { @@ -515,14 +520,14 @@ determineOutputFormat(struct palmHeader const palmHeader, static void readRgbFormat(FILE * const ifP, - struct directPixelFormat * const pixelFormatP) { + struct DirectPixelFormat * const pixelFormatP) { unsigned char r, g, b; pm_readcharu(ifP, &r); pm_readcharu(ifP, &g); pm_readcharu(ifP, &b); - + if (r != 5 || g != 6 || b != 5) pm_error("This image has a direct color pixel format of " "%u red, %u green, %u blue bits. This program " @@ -537,8 +542,8 @@ readRgbFormat(FILE * const ifP, static void -readDirectTransparentColor(FILE * const ifP, - Color_s * const colorP) { +readDirectTransparentColor(FILE * const ifP, + ColormapEntry * const colorP) { unsigned char r, g, b; @@ -553,8 +558,8 @@ readDirectTransparentColor(FILE * const ifP, static void readDirectInfoType(FILE * const ifP, - struct palmHeader const palmHeader, - struct directColorInfo * const directInfoTypeP) { + struct PalmHeader const palmHeader, + struct DirectColorInfo * const directInfoTypeP) { /*---------------------------------------------------------------------------- Read the Palm Bitmap Direct Info Type section, if any. @@ -568,12 +573,12 @@ readDirectInfoType(FILE * const ifP, if ((palmHeader.directColor) && palmHeader.pixelSize != 16) pm_error("The image is of the direct color type, but has %u " "bits per pixel. The only kind of direct color images " - "this program understands are 16 bit ones.", + "this program understands are 16 bit ones.", palmHeader.pixelSize); if (palmHeader.version == 3) { /* All direct color info is in the header, because it'sversion - 3 encoding. No Direct Info Type section. + 3 encoding. No Direct Info Type section. */ } else { if (palmHeader.directColor) { @@ -584,7 +589,7 @@ readDirectInfoType(FILE * const ifP, pm_readcharu(ifP, &padding); pm_readcharu(ifP, &padding); - readDirectTransparentColor(ifP, + readDirectTransparentColor(ifP, &directInfoTypeP->transparentColor); } else { /* Not a direct color image; no Direct Info Type section. */ @@ -596,8 +601,8 @@ readDirectInfoType(FILE * const ifP, static void readColormap(FILE * const ifP, - struct palmHeader const palmHeader, - Colormap * const colormapP) { + struct PalmHeader const palmHeader, + Colormap ** const colormapPP) { /*---------------------------------------------------------------------------- Read the colormap, if any from the Palm Bitmap. @@ -605,18 +610,18 @@ readColormap(FILE * const ifP, return an undefined value as *colormapP. -----------------------------------------------------------------------------*/ if (palmHeader.hasColormap) - *colormapP = palmcolor_read_colormap(ifP); + *colormapPP = palmcolor_read_colormap(ifP); } static void -getColorInfo(struct palmHeader const palmHeader, - struct directColorInfo const directInfoType, - Colormap const colormapFromImage, - Colormap * const colormapP, +getColorInfo(struct PalmHeader const palmHeader, + struct DirectColorInfo const directInfoType, + Colormap * const colormapFromImageP, + Colormap ** const colormapPP, unsigned int * const ncolorsP, - struct directColorInfo * const directColorInfoP) { + struct DirectColorInfo * const directColorInfoP) { /*---------------------------------------------------------------------------- Gather color encoding information from the various sources. @@ -626,14 +631,14 @@ getColorInfo(struct palmHeader const palmHeader, If it's a version 3 direct color, the pixel format must be "565". -----------------------------------------------------------------------------*/ if (palmHeader.version == 3 && palmHeader.directColor) { - *colormapP = NULL; + *colormapPP = NULL; assert(palmHeader.pixelFormat == PALM_FORMAT_565); directColorInfoP->pixelFormat.redbits = 5; directColorInfoP->pixelFormat.greenbits = 6; directColorInfoP->pixelFormat.bluebits = 5; - directColorInfoP->transparentColor = + directColorInfoP->transparentColor = /* See convertRowToPnmDirect for this trick This will break once maxval isn't always set 255 for @@ -646,18 +651,18 @@ getColorInfo(struct palmHeader const palmHeader, ((((palmHeader.transparentValue >> 0) & 0x1F) * 255 / 0x1F) << 0); } else if (palmHeader.directColor) { - *colormapP = NULL; + *colormapPP = NULL; *directColorInfoP = directInfoType; } else if (palmHeader.hasColormap) - *colormapP = colormapFromImage; + *colormapPP = colormapFromImageP; else if (palmHeader.pixelSize >= 8) { - Colormap colormap; - colormap = palmcolor_build_default_8bit_colormap(); - qsort(colormap->color_entries, colormap->ncolors, - sizeof(Color_s), palmcolor_compare_indices); - *colormapP = colormap; + Colormap * const colormapP = + palmcolor_build_default_8bit_colormap(); + qsort(colormapP->color_entries, colormapP->ncolors, + sizeof(ColormapEntry), palmcolor_compare_indices); + *colormapPP = colormapP; } else - *colormapP = NULL; + *colormapPP = NULL; *ncolorsP = 1 << palmHeader.pixelSize; } @@ -670,8 +675,8 @@ doTransparent(FILE * const ofP, bool const directColor, unsigned char const transparentIndex, unsigned char const pixelSize, - Colormap const colormap, - struct directColorInfo const directColorInfo) { + Colormap * const colormapP, + struct DirectColorInfo const directColorInfo) { /*---------------------------------------------------------------------------- Generate a PNM comment on *ofP telling what color in the raster is supposed to be transparent. @@ -681,31 +686,32 @@ doTransparent(FILE * const ofP, RGB_ALPHA and GRAYSCALE_ALPHA tuple types). -----------------------------------------------------------------------------*/ if (hasTransparency) { - if (colormap) { - Color_s const color = transparentIndex << 24; - Color const actualColor = (bsearch(&color, - colormap->color_entries, - colormap->ncolors, - sizeof(color), - palmcolor_compare_indices)); - if (!actualColor) + if (colormapP) { + ColormapEntry const searchTarget = transparentIndex << 24; + ColormapEntry * const foundEntryP = + bsearch(&searchTarget, + colormapP->color_entries, + colormapP->ncolors, + sizeof(searchTarget), + palmcolor_compare_indices); + if (!foundEntryP) pm_error("Invalid input; transparent index %u " "is not among the %u colors in the image's colormap", - transparentIndex, colormap->ncolors); + transparentIndex, colormapP->ncolors); - fprintf(ofP, "#%02x%02x%02x\n", - (unsigned int) ((*actualColor >> 16) & 0xFF), - (unsigned int) ((*actualColor >> 8) & 0xFF), - (unsigned int) ((*actualColor >> 0) & 0xFF)); + fprintf(ofP, "#%02x%02x%02x\n", + (unsigned int) ((*foundEntryP >> 16) & 0xFF), + (unsigned int) ((*foundEntryP >> 8) & 0xFF), + (unsigned int) ((*foundEntryP >> 0) & 0xFF)); } else if (directColor) { - Color_s const color = directColorInfo.transparentColor; - fprintf(ofP, "#%02x%02x%02x\n", - (unsigned int)((color >> 16) & 0xFF), - (unsigned int)((color >> 8) & 0xFF), + ColormapEntry const color = directColorInfo.transparentColor; + fprintf(ofP, "#%02x%02x%02x\n", + (unsigned int)((color >> 16) & 0xFF), + (unsigned int)((color >> 8) & 0xFF), (unsigned int)((color >> 0) & 0xFF)); } else { unsigned int const maxval = pm_bitstomaxval(pixelSize); - unsigned int const grayval = + unsigned int const grayval = ((maxval - transparentIndex) * 256) / maxval; fprintf(ofP, "#%02x%02x%02x\n", grayval, grayval, grayval); } @@ -723,10 +729,10 @@ createHistogram(unsigned int const ncolors, MALLOCARRAY(seen, ncolors); if (!seen) pm_error("Can't allocate array for keeping track of " - "how many pixels of each of %u colors are in the image.", + "how many pixels of each of %u colors are in the image.", ncolors); - { + { /* Initialize the counter for each color to zero */ unsigned int i; for (i = 0; i < ncolors; ++i) @@ -761,7 +767,7 @@ readScanlineRow(FILE * const ifP, pm_readcharu(ifP, &diffmask); byteCount = MIN(bytesPerRow - j, 8); - + for (k = 0; k < byteCount; ++k) { /* the first row cannot be compressed */ if (firstRow || ((diffmask & (1 << (7 - k))) != 0)) { @@ -800,7 +806,7 @@ readRleRow(FILE * const ifP, memset(palmrow + j, inval, incount); j += incount; } -} +} @@ -810,7 +816,7 @@ readPackBitsRow16(FILE * const ifP, unsigned int const bytesPerRow) { /* From the Palm OS Programmer's API Reference: - + Although the [...] spec is byte-oriented, the 16-bit algorithm is identical [to the 8-bit algorithm]: just substitute "word" for "byte". */ @@ -819,7 +825,7 @@ readPackBitsRow16(FILE * const ifP, for (j = 0; j < bytesPerRow; ) { char incount; pm_readchar(ifP, &incount); - if (incount < 0) { + if (incount < 0) { /* How do we handle incount == -128 ? */ unsigned int const runlength = (-incount + 1) * 2; unsigned int k; @@ -841,13 +847,13 @@ readPackBitsRow16(FILE * const ifP, } j += nonrunlength; } - if (j > bytesPerRow) + if (j > bytesPerRow) pm_error("Bytes in PackBits compressed row exceed bytes per row. " "Bytes per row is %u. " "The bytes in this row were pushed up to %u bytes " "(and then we gave up).", bytesPerRow, j); } -} +} @@ -861,7 +867,7 @@ readPackBitsRow(FILE * const ifP, for (j = 0; j < bytesPerRow; ) { char incount; pm_readchar(ifP, &incount); - if (incount < 0) { + if (incount < 0) { /* How do we handle incount == -128 ? */ unsigned int const runlength = -incount + 1; unsigned char inval; @@ -879,13 +885,13 @@ readPackBitsRow(FILE * const ifP, } j += nonrunlength; } - if (j > bytesPerRow) + if (j > bytesPerRow) pm_error("Bytes in PackBits compressed row exceed bytes per row. " "Bytes per row is %u. " "The bytes in this row were pushed up to %u bytes " "(and then we gave up).", bytesPerRow, j); } -} +} @@ -895,7 +901,7 @@ readUncompressedRow(FILE * const ifP, unsigned int const bytesPerRow) { int bytesRead; - + bytesRead = fread(palmrow, 1, bytesPerRow, ifP); if (bytesRead != bytesPerRow) pm_error("Error reading Palm file. Short read."); @@ -907,7 +913,7 @@ static void readDecompressedRow(FILE * const ifP, unsigned char * const palmrow, unsigned char * const lastrow, - enum palmCompressionType const compressionType, + enum PalmCompressionType const compressionType, unsigned int const bytesPerRow, unsigned int const pixelSize, bool const firstRow) { @@ -968,27 +974,27 @@ convertRowToPnmDirect(const unsigned char * const palmrow, blue=0x1F. How do we promote those colors? Simple shift would give us R=248,G=252,B=248; which is slightly green. Hardly seems right. - + So I've perverted the math a bit. Each color value is multiplied by 255, then divided by either 31 (red or blue) or 63 (green). That's the right way to do it - anyway. + anyway. */ const unsigned char *inbyte; unsigned int j; - + for (inbyte = palmrow, j = 0; j < cols; ++j) { unsigned int inval; inval = *inbyte++ << 8; inval |= *inbyte++; - + if (seen) ++seen[inval]; - - PPM_ASSIGN(xelrow[j], - (((inval >> 11) & 0x1F) * maxval) / 0x1F, - (((inval >> 5) & 0x3F) * maxval) / 0x3F, + + PPM_ASSIGN(xelrow[j], + (((inval >> 11) & 0x1F) * maxval) / 0x1F, + (((inval >> 5) & 0x3F) * maxval) / 0x3F, (((inval >> 0) & 0x1F) * maxval) / 0x1F ); } @@ -1000,46 +1006,50 @@ static void convertRowToPnmNotDirect(const unsigned char * const palmrow, xel * const xelrow, unsigned int const cols, - Colormap const colormap, + Colormap * const colormapP, xelval * const graymap, unsigned int * const seen, unsigned int const pixelSize) { unsigned int const mask = (1 << pixelSize) - 1; - const unsigned char *inbyte; + const unsigned char * inbyteP; unsigned int inbit; unsigned int j; - + + assert(pixelSize <= 8); + inbit = 8 - pixelSize; - inbyte = palmrow; + inbyteP = &palmrow[0]; for (j = 0; j < cols; ++j) { - short const color = ((*inbyte) & (mask << inbit)) >> inbit; + short const color = (*inbyteP & (mask << inbit)) >> inbit; if (seen) ++seen[color]; - - if (colormap) { - Color_s const color2 = color << 24; - Color const actualColor = (bsearch (&color2, - colormap->color_entries, - colormap->ncolors, - sizeof(color2), - palmcolor_compare_indices)); - if (!actualColor) + + if (colormapP) { + ColormapEntry const searchTarget = color << 24; + ColormapEntry * const foundEntryP = + bsearch(&searchTarget, + colormapP->color_entries, + colormapP->ncolors, + sizeof(searchTarget), + palmcolor_compare_indices); + + if (!foundEntryP) pm_error("Invalid input. A color index in column %u " "is %u, which is not among the %u colors " "in the colormap", - j, color, colormap->ncolors); + j, color, colormapP->ncolors); - PPM_ASSIGN(xelrow[j], - (*actualColor >> 16) & 0xFF, - (*actualColor >> 8) & 0xFF, - (*actualColor >> 0) & 0xFF); + PPM_ASSIGN(xelrow[j], + (*foundEntryP >> 16) & 0xFF, + (*foundEntryP >> 8) & 0xFF, + (*foundEntryP >> 0) & 0xFF); } else PNM_ASSIGN1(xelrow[j], graymap[color]); - + if (!inbit) { - ++inbyte; + ++inbyteP; inbit = 8 - pixelSize; } else inbit -= pixelSize; @@ -1050,9 +1060,9 @@ convertRowToPnmNotDirect(const unsigned char * const palmrow, static void writePnm(FILE * const ofP, - struct palmHeader const palmHeader, + struct PalmHeader const palmHeader, FILE * const ifP, - Colormap const colormap, + Colormap * const colormapP, xelval * const graymap, unsigned int const nColors, int const format, @@ -1067,22 +1077,22 @@ writePnm(FILE * const ofP, xel * xelrow; unsigned int * seen; unsigned int row; - + pnm_writepnminit(ofP, cols, rows, maxval, format, 0); xelrow = pnm_allocrow(cols); /* Read the picture data, one row at a time */ MALLOCARRAY_NOFAIL(palmrow, palmHeader.bytesPerRow); - MALLOCARRAY_NOFAIL(lastrow, palmHeader.bytesPerRow); - + MALLOCARRAY_NOFAIL(lastrow, palmHeader.bytesPerRow); + if (seenP) { createHistogram(nColors, &seen); *seenP = seen; } else seen = NULL; - /* We should actually use compressedDataSizeNN for checking the sanity - of the data we're reading ... + /* We should actually use compressedDataSizeNN for checking the sanity + of the data we're reading ... */ if (palmHeader.compressionType != COMPRESSION_NONE) { if (palmHeader.version < 3) { @@ -1095,8 +1105,8 @@ writePnm(FILE * const ofP, } for (row = 0; row < rows; ++row) { - readDecompressedRow(ifP, palmrow, lastrow, - palmHeader.compressionType, + readDecompressedRow(ifP, palmrow, lastrow, + palmHeader.compressionType, palmHeader.bytesPerRow, palmHeader.pixelSize, row == 0); @@ -1105,7 +1115,7 @@ writePnm(FILE * const ofP, assert(palmHeader.pixelSize == 16); convertRowToPnmDirect(palmrow, xelrow, cols, maxval, seen); } else - convertRowToPnmNotDirect(palmrow, xelrow, cols, colormap, graymap, + convertRowToPnmNotDirect(palmrow, xelrow, cols, colormapP, graymap, seen, palmHeader.pixelSize); pnm_writepnmrow(ofP, xelrow, cols, maxval, format, 0); @@ -1119,28 +1129,29 @@ writePnm(FILE * const ofP, static void showHistogram(unsigned int * const seen, - Colormap const colormap, + Colormap * const colormapP, const xelval * const graymap, unsigned int const ncolors) { unsigned int colorIndex; - + for (colorIndex = 0; colorIndex < ncolors; ++colorIndex) { - if (!colormap) - pm_message("%.3d -> %.3d: %d", + if (!colormapP) + pm_message("%.3d -> %.3d: %d", colorIndex, graymap[colorIndex], seen[colorIndex]); else { - Color_s const color = colorIndex << 24; - Color const actualColor = (bsearch(&color, - colormap->color_entries, - colormap->ncolors, - sizeof(color), - palmcolor_compare_indices)); - if (actualColor) + ColormapEntry const searchTarget = colorIndex << 24; + ColormapEntry * const foundEntryP = + bsearch(&searchTarget, + colormapP->color_entries, + colormapP->ncolors, + sizeof(searchTarget), + palmcolor_compare_indices); + if (foundEntryP) pm_message("%.3d -> %ld,%ld,%ld: %d", colorIndex, - (*actualColor >> 16) & 0xFF, - (*actualColor >> 8) & 0xFF, - (*actualColor & 0xFF), seen[colorIndex]); + (*foundEntryP >> 16) & 0xFF, + (*foundEntryP >> 8) & 0xFF, + (*foundEntryP & 0xFF), seen[colorIndex]); } } } @@ -1148,22 +1159,21 @@ showHistogram(unsigned int * const seen, int -main(int argc, char **argv) { +main(int argc, const char **argv) { - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; - FILE* ifP; - struct palmHeader palmHeader; - struct directColorInfo directInfoType; - Colormap colormapFromImage; - Colormap colormap; - struct directColorInfo directColorInfo; + FILE * ifP; + struct PalmHeader palmHeader; + struct DirectColorInfo directInfoType; + Colormap * colormapFromImageP; + Colormap * colormapP; + struct DirectColorInfo directColorInfo; int format; xelval maxval; unsigned int nColors; - /* Parse default params */ - pnm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -1172,22 +1182,22 @@ main(int argc, char **argv) { readHeader(ifP, cmdline.rendition, &palmHeader); readDirectInfoType(ifP, palmHeader, &directInfoType); - - readColormap(ifP, palmHeader, &colormapFromImage); - + + readColormap(ifP, palmHeader, &colormapFromImageP); + determineOutputFormat(palmHeader, &format, &maxval); - - getColorInfo(palmHeader, directInfoType, colormapFromImage, - &colormap, &nColors, &directColorInfo); + + getColorInfo(palmHeader, directInfoType, colormapFromImageP, + &colormapP, &nColors, &directColorInfo); if (cmdline.verbose) reportPalmHeader(palmHeader, directColorInfo); if (cmdline.transparent) - doTransparent(stdout, + doTransparent(stdout, palmHeader.hasTransparency, palmHeader.directColor, - palmHeader.transparentIndex, - palmHeader.pixelSize, colormap, directColorInfo); + palmHeader.transparentIndex, + palmHeader.pixelSize, colormapP, directColorInfo); else { unsigned int * seen; xelval * graymap; @@ -1195,12 +1205,12 @@ main(int argc, char **argv) { graymap = createGraymap(nColors, maxval); writePnm(stdout, - palmHeader, ifP, colormap, graymap, nColors, format, maxval, + palmHeader, ifP, colormapP, graymap, nColors, format, maxval, cmdline.showhist ? &seen : NULL); - + if (cmdline.showhist) - showHistogram(seen, colormap, graymap, nColors); - + showHistogram(seen, colormapP, graymap, nColors); + free(graymap); } pm_close(ifP); diff --git a/converter/other/pnmtopalm/pnmtopalm.c b/converter/other/pnmtopalm/pnmtopalm.c index a7d1fd46..25c8af2e 100644 --- a/converter/other/pnmtopalm/pnmtopalm.c +++ b/converter/other/pnmtopalm/pnmtopalm.c @@ -29,33 +29,37 @@ #include "pm_c_util.h" #include "pnm.h" -#include "palm.h" #include "shhopt.h" #include "mallocvar.h" #include "runlength.h" -enum compressionType {COMP_NONE, COMP_SCANLINE, COMP_RLE, COMP_PACKBITS}; +#include "palm.h" +#include "palmcolormap.h" + +enum CompressionType {COMP_NONE, COMP_SCANLINE, COMP_RLE, COMP_PACKBITS}; -struct cmdline_info { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ const char * inputFilespec; /* Filespecs of input files */ - const char * transparent; /* -transparent value. Null if unspec */ - unsigned int depth; /* -depth value. 0 if unspec */ - unsigned int maxdepth; /* -maxdepth value. 0 if unspec */ - enum compressionType compression; + const char * transparent; + unsigned int depthSpec; + unsigned int depth; + unsigned int maxdepthSpec; + unsigned int maxdepth; + enum CompressionType compression; unsigned int verbose; unsigned int colormap; - unsigned int offset; /* -offset specified */ - unsigned int density; /* screen density */ + unsigned int offset; + unsigned int density; unsigned int withdummy; }; static void -parseCommandLine(int argc, char ** argv, struct cmdline_info *cmdlineP) { +parseCommandLine(int argc, const char ** argv, struct CmdlineInfo *cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. @@ -64,7 +68,7 @@ parseCommandLine(int argc, char ** argv, struct cmdline_info *cmdlineP) { optEntry *option_def; unsigned int option_def_index; - unsigned int transSpec, depthSpec, maxdepthSpec, densitySpec; + unsigned int transSpec, densitySpec; unsigned int scanline_compression, rle_compression, packbits_compression; MALLOCARRAY_NOFAIL(option_def, 100); @@ -73,9 +77,9 @@ parseCommandLine(int argc, char ** argv, struct cmdline_info *cmdlineP) { OPTENT3(0, "transparent", OPT_STRING, &cmdlineP->transparent, &transSpec, 0); OPTENT3(0, "depth", OPT_UINT, - &cmdlineP->depth, &depthSpec, 0); + &cmdlineP->depth, &cmdlineP->depthSpec, 0); OPTENT3(0, "maxdepth", OPT_UINT, - &cmdlineP->maxdepth, &maxdepthSpec, 0); + &cmdlineP->maxdepth, &cmdlineP->maxdepthSpec, 0); OPTENT3(0, "scanline_compression", OPT_FLAG, NULL, &scanline_compression, 0); OPTENT3(0, "rle_compression", OPT_FLAG, @@ -97,28 +101,26 @@ parseCommandLine(int argc, char ** argv, struct cmdline_info *cmdlineP) { opt.short_allowed = FALSE; /* We have some short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdline_p and others. */ - if (depthSpec) { + if (cmdlineP->depthSpec) { if (cmdlineP->depth != 1 && cmdlineP->depth != 2 && cmdlineP->depth != 4 && cmdlineP->depth != 8 && cmdlineP->depth != 16) pm_error("invalid value for -depth: %u. Valid values are " "1, 2, 4, 8, and 16", cmdlineP->depth); - } else - cmdlineP->depth = 0; + } - if (maxdepthSpec) { + if (cmdlineP->maxdepthSpec) { if (cmdlineP->maxdepth != 1 && cmdlineP->maxdepth != 2 && cmdlineP->maxdepth != 4 && cmdlineP->maxdepth != 8 && cmdlineP->maxdepth != 16) pm_error("invalid value for -maxdepth: %u. Valid values are " "1, 2, 4, 8, and 16", cmdlineP->maxdepth); - } else - cmdlineP->maxdepth = 0; + } - if (depthSpec && maxdepthSpec && + if (cmdlineP->depthSpec && cmdlineP->maxdepthSpec && cmdlineP->depth > cmdlineP->maxdepth) pm_error("-depth value (%u) is greater than -maxdepth (%u) value.", cmdlineP->depth, cmdlineP->maxdepth); @@ -132,8 +134,8 @@ parseCommandLine(int argc, char ** argv, struct cmdline_info *cmdlineP) { cmdlineP->density != PALM_DENSITY_DOUBLE && cmdlineP->density != PALM_DENSITY_TRIPLE && cmdlineP->density != PALM_DENSITY_QUADRUPLE) - pm_error("Invalid value for -density: %d. Valid values are " - "%d, %d, %d, %d and %d.", cmdlineP->density, + pm_error("Invalid value for -density: %u. Valid values are " + "%u, %u, %u, %u and %u.", cmdlineP->density, PALM_DENSITY_LOW, PALM_DENSITY_ONEANDAHALF, PALM_DENSITY_DOUBLE, PALM_DENSITY_TRIPLE, PALM_DENSITY_QUADRUPLE); @@ -164,7 +166,7 @@ parseCommandLine(int argc, char ** argv, struct cmdline_info *cmdlineP) { if (argc-1 > 1) pm_error("This program takes at most 1 argument: the file name. " - "You specified %d", argc-1); + "You specified %u", argc-1); else if (argc-1 > 0) cmdlineP->inputFilespec = argv[1]; else @@ -173,108 +175,241 @@ parseCommandLine(int argc, char ** argv, struct cmdline_info *cmdlineP) { +static xelval +scaleSample(pixval const arg, + pixval const oldMaxval, + pixval const newMaxval) { + + return (arg * newMaxval + oldMaxval/2) / oldMaxval; +} + + + +static void +determinePalmFormatPgm(xelval const maxval, + bool const bppSpecified, + unsigned int const bpp, + bool const maxBppSpecified, + unsigned int const maxBpp, + bool const wantCustomColormap, + enum CompressionType const compression, + bool const verbose, + unsigned int * const bppP) { + + /* We can usually handle this one, but may not have enough pixels. So + check. + */ + + if (wantCustomColormap) + pm_error("You specified -colormap with a black and white input" + "image. -colormap is valid only with color."); + if (bppSpecified) + *bppP = bpp; + else if (maxBppSpecified && (maxval >= (1 << maxBpp))) + *bppP = maxBpp; + else if (compression != COMP_NONE && maxval > 255) + *bppP = 8; + else if (maxval > 16) + *bppP = 4; + else { + /* scale to minimum number of bpp needed */ + unsigned int bpp; + for (bpp = 1; (1 << bpp) < maxval; bpp *= 2) + ; + *bppP = bpp; + } + if (verbose) + pm_message("output is grayscale %u bits-per-pixel", *bppP); +} + + + +static void +validateImageAgainstStandardColormap(const Colormap * const colormapP, + xel ** const xels, + unsigned int const cols, + unsigned int const rows, + xelval const maxval) { +/*---------------------------------------------------------------------------- + Abort program if the image xels[][] (which is 'cols' x 'rows') contains a + color not in the colormap *colormapP, giving an error message assuming the + user chose the standard Palm colormap. +-----------------------------------------------------------------------------*/ + unsigned int row; + + for (row = 0; row < rows; ++row) { + unsigned int col; + + for (col = 0; col < cols; ++col) { + ColormapEntry const searchTarget = + palmcolor_mapEntryColorFmPixel(xels[row][col], maxval, 255); + + ColormapEntry * const foundEntryP = + (bsearch(&searchTarget, + colormapP->color_entries, colormapP->ncolors, + sizeof(ColormapEntry), palmcolor_compare_colors)); + if (!foundEntryP) + pm_error( + "A color in the input image is not in the standard Palm " + "8-bit color palette. Either adjust the colors in the " + "input with 'pnmremap' and the 'palmcolor8.map' file " + "(see manual) or specify -colormap or -depth=16"); + } + } +} + + + +static void +determinePalmFormatPpm(unsigned int const cols, + unsigned int const rows, + xelval const maxval, + xel ** const xels, + bool const bppSpecified, + unsigned int const bpp, + bool const maxBppSpecified, + unsigned int const maxBpp, + bool const wantCustomColormap, + enum CompressionType const compression, + bool const verbose, + unsigned int * const bppP, + bool * const directColorP, + Colormap ** const colormapPP) { + + /* We don't attempt to identify PPM files that are actually + monochrome. So there are two options here: either 8-bit with a + colormap, either the standard one or a custom one, or 16-bit direct + color. In the colormap case, if 'wantCustomColormap' is true (not + recommended by Palm) we will put in our own colormap that has the + colors of the input image; otherwise we will select the default + Palm colormap and will fail if the input image has any colors that + are not in that map (user should use Pnmremap and the + palmcolor8.map file that comes with Netpbm to avoid this). We try + for colormapped first, since it works on more PalmOS devices. + */ + if ((bppSpecified && bpp == 16) || + (!bppSpecified && maxBppSpecified && maxBpp == 16)) { + /* we do the 16-bit direct color */ + *directColorP = TRUE; + *colormapPP = NULL; + *bppP = 16; + } else if (!wantCustomColormap) { + /* colormapped with the standard colormap */ + Colormap * colormapP; + + if ((bppSpecified && bpp != 8) || (maxBppSpecified && maxBpp < 8)) + pm_error("Must use depth of 8 for color Palm Bitmap without " + "custom color table."); + colormapP = palmcolor_build_default_8bit_colormap(); + validateImageAgainstStandardColormap(colormapP, + xels, cols, rows, maxval); + + *colormapPP = colormapP; + *bppP = 8; + *directColorP = FALSE; + if (verbose) + pm_message("Output is color with default colormap at 8 bpp"); + } else { + /* colormapped with a custom colormap */ + *colormapPP = + palmcolor_build_custom_8bit_colormap(xels, rows, cols, maxval); + for (*bppP = 1; (1 << *bppP) < (*colormapPP)->ncolors; *bppP *= 2); + if (bppSpecified) { + if (bpp >= *bppP) + *bppP = bpp; + else + pm_error("Too many colors for specified depth. " + "Specified depth is %u bits; would need %u to " + "represent the %u colors in the image. " + "Use pnmquant to reduce.", + maxBpp, *bppP, (*colormapPP)->ncolors); + } else if (maxBppSpecified && maxBpp < *bppP) { + pm_error("Too many colors for specified max depth. " + "Specified maximum is %u bits; would need %u to " + "represent the %u colors in the image. " + "Use pnmquant to reduce.", + maxBpp, *bppP, (*colormapPP)->ncolors); + } else if (compression != COMP_NONE && *bppP > 8) { + pm_error("Too many colors for a compressed image. " + "Maximum is 256; the image has %u", + (*colormapPP)->ncolors); + } + *directColorP = FALSE; + if (verbose) + pm_message("Output is color with custom colormap " + "with %u colors at %u bpp", + (*colormapPP)->ncolors, *bppP); + } +} + + + static void -determinePalmFormat(unsigned int const cols, - unsigned int const rows, - xelval const maxval, - int const format, - xel ** const xels, - unsigned int const specified_bpp, - unsigned int const max_bpp, - bool const custom_colormap, - bool const verbose, - unsigned int * const bppP, - bool * const directColorP, - Colormap * const colormapP) { +determinePalmFormat(unsigned int const cols, + unsigned int const rows, + xelval const maxval, + int const format, + xel ** const xels, + bool const bppSpecified, + unsigned int const bpp, + bool const maxBppSpecified, + unsigned int const maxBpp, + bool const wantCustomColormap, + enum CompressionType const compression, + bool const verbose, + unsigned int * const bppP, + bool * const directColorP, + Colormap ** const colormapPP) { +/*---------------------------------------------------------------------------- + Determine what kind of Palm output file to make. + Also compute the colormap, if there is to be one. This could be either one + we make up, that needs to go into the image, or a standard one. +-----------------------------------------------------------------------------*/ + if (compression != COMP_NONE) { + if (bppSpecified && bpp > 8) + pm_error("You requested %u bits per pixel and compression. " + "This program does not know how to generate a " + "compressed image with more than 8 bits per pixel", + bpp); + if (maxBppSpecified && maxBpp > 8) + pm_error("You requested %u max bits per pixel and compression. " + "This program does not know how to generate a " + "compressed image with more than 8 bits per pixel", + maxBpp); + } if (PNM_FORMAT_TYPE(format) == PBM_TYPE) { - if (custom_colormap) + if (wantCustomColormap) pm_error("You specified -colormap with a black and white input " "image. -colormap is valid only with color."); - if (specified_bpp) - *bppP = specified_bpp; + if (bppSpecified) + *bppP = bpp; else *bppP = 1; /* no point in wasting bits */ *directColorP = FALSE; - *colormapP = NULL; + *colormapPP = NULL; if (verbose) pm_message("output is black and white"); } else if (PNM_FORMAT_TYPE(format) == PGM_TYPE) { - /* we can usually handle this one, but may not have enough - pixels. So check... */ - if (custom_colormap) - pm_error("You specified -colormap with a black and white input" - "image. -colormap is valid only with color."); - if (specified_bpp) - *bppP = specified_bpp; - else if (max_bpp && (maxval >= (1 << max_bpp))) - *bppP = max_bpp; - else if (maxval > 16) - *bppP = 4; - else { - /* scale to minimum number of bpp needed */ - for (*bppP = 1; (1 << *bppP) < maxval; *bppP *= 2) - ; - } - if (*bppP > 4) - *bppP = 4; - if (verbose) - pm_message("output is grayscale %d bits-per-pixel", *bppP); + determinePalmFormatPgm(maxval, + bppSpecified, bpp, maxBppSpecified, maxBpp, + wantCustomColormap, compression, + verbose, + bppP); + *directColorP = FALSE; - *colormapP = NULL; + *colormapPP = NULL; } else if (PNM_FORMAT_TYPE(format) == PPM_TYPE) { - - /* We assume that we only get a PPM if the image cannot be - represented as PBM or PGM. There are two options here: either - 8-bit with a colormap, either the standard one or a custom one, - or 16-bit direct color. In the 8-bit case, if "custom_colormap" - is specified (not recommended by Palm) we will put in our own - colormap; otherwise we will assume that the colors have been - mapped to the default Palm colormap by appropriate use of - pnmquant. We try for 8-bit color first, since it works on - more PalmOS devices. - */ - if ((specified_bpp == 16) || - (specified_bpp == 0 && max_bpp == 16)) { - /* we do the 16-bit direct color */ - *directColorP = TRUE; - *colormapP = NULL; - *bppP = 16; - } else if (!custom_colormap) { - /* standard indexed 8-bit color */ - *colormapP = palmcolor_build_default_8bit_colormap(); - *bppP = 8; - if (((specified_bpp != 0) && (specified_bpp != 8)) || - ((max_bpp != 0) && (max_bpp < 8))) - pm_error("Must use depth of 8 for color Palm Bitmap without " - "custom color table."); - *directColorP = FALSE; - if (verbose) - pm_message("Output is color with default colormap at 8 bpp"); - } else { - /* indexed 8-bit color with a custom colormap */ - *colormapP = - palmcolor_build_custom_8bit_colormap(rows, cols, xels); - for (*bppP = 1; (1 << *bppP) < (*colormapP)->ncolors; *bppP *= 2); - if (specified_bpp != 0) { - if (specified_bpp >= *bppP) - *bppP = specified_bpp; - else - pm_error("Too many colors for specified depth. " - "Use pnmquant to reduce."); - } else if ((max_bpp != 0) && (max_bpp < *bppP)) { - pm_error("Too many colors for specified max depth. " - "Use pnmquant to reduce."); - } - *directColorP = FALSE; - if (verbose) - pm_message("Output is color with custom colormap " - "with %d colors at %d bpp", - (*colormapP)->ncolors, *bppP); - } + determinePalmFormatPpm(cols, rows, maxval, xels, bppSpecified, bpp, + maxBppSpecified, maxBpp, + wantCustomColormap, compression, verbose, + bppP, directColorP, colormapPP); } else { pm_error("unknown format 0x%x on input file", (unsigned) format); } + + if (compression != COMP_NONE) + assert(*bppP <= 8); } @@ -300,25 +435,23 @@ findTransparentColor(const char * const colorSpec, pixval const newMaxval, bool const directColor, pixval const maxval, - Colormap const colormap, + Colormap * const colormapP, xel * const transcolorP, unsigned int * const transindexP) { *transcolorP = ppm_parsecolor(colorSpec, maxval); if (!directColor) { - Color_s const temp_color = - ((((PPM_GETR(*transcolorP)*newMaxval) / maxval) << 16) - | (((PPM_GETG(*transcolorP)*newMaxval) / maxval) << 8) - | ((PPM_GETB(*transcolorP)*newMaxval) / maxval)); - Color const found = - (bsearch(&temp_color, - colormap->color_entries, colormap->ncolors, - sizeof(Color_s), palmcolor_compare_colors)); - if (!found) { + ColormapEntry const searchTarget = + palmcolor_mapEntryColorFmPixel(*transcolorP, maxval, newMaxval); + ColormapEntry * const foundEntryP = + (bsearch(&searchTarget, + colormapP->color_entries, colormapP->ncolors, + sizeof(ColormapEntry), palmcolor_compare_colors)); + if (!foundEntryP) { pm_error("Specified transparent color %s not found " "in colormap.", colorSpec); } else - *transindexP = (*found >> 24) & 0xFF; + *transindexP = (*foundEntryP >> 24) & 0xFF; } } @@ -326,9 +459,9 @@ findTransparentColor(const char * const colorSpec, static unsigned int bitmapVersion(unsigned int const bpp, - bool const colormap, + bool const colormapped, bool const transparent, - enum compressionType const compression, + enum CompressionType const compression, unsigned int const density) { /*---------------------------------------------------------------------------- Return the version number of the oldest version that can represent @@ -343,7 +476,7 @@ bitmapVersion(unsigned int const bpp, version = 3; else if (transparent || compression != COMP_NONE) version = 2; - else if (bpp > 1 || colormap) + else if (bpp > 1 || colormapped) version = 1; else version = 0; @@ -357,8 +490,8 @@ static void writeCommonHeader(unsigned int const cols, unsigned int const rows, unsigned int const rowbytes, - enum compressionType const compression, - bool const colormap, + enum CompressionType const compression, + bool const colormapped, bool const transparent, bool const directColor, unsigned int const bpp, @@ -382,7 +515,7 @@ writeCommonHeader(unsigned int const cols, flags = 0; /* initial value */ if (compression != COMP_NONE) flags |= PALM_IS_COMPRESSED_FLAG; - if (colormap) + if (colormapped) flags |= PALM_HAS_COLORMAP_FLAG; if (transparent) flags |= PALM_HAS_TRANSPARENCY_FLAG; @@ -398,7 +531,7 @@ writeCommonHeader(unsigned int const cols, static unsigned char -compressionFieldValue(enum compressionType const compression) { +compressionFieldValue(enum CompressionType const compression) { unsigned char retval; @@ -424,7 +557,7 @@ compressionFieldValue(enum compressionType const compression) { static void writeRemainingHeaderLow(unsigned int const nextDepthOffset, unsigned int const transindex, - enum compressionType const compression, + enum CompressionType const compression, unsigned int const bpp) { /*---------------------------------------------------------------------------- Write last 6 bytes of a low density Palm Bitmap header. @@ -449,7 +582,7 @@ writeRemainingHeaderLow(unsigned int const nextDepthOffset, static void writeRemainingHeaderHigh(unsigned int const bpp, - enum compressionType const compression, + enum CompressionType const compression, unsigned int const density, xelval const maxval, bool const transparent, @@ -480,9 +613,9 @@ writeRemainingHeaderHigh(unsigned int const bpp, if (bpp == 16) { /* Blind guess here */ fputc(0, stdout); - fputc((PPM_GETR(transcolor) * 255) / maxval, stdout); - fputc((PPM_GETG(transcolor) * 255) / maxval, stdout); - fputc((PPM_GETB(transcolor) * 255) / maxval, stdout); + fputc(scaleSample(PPM_GETR(transcolor), maxval, 255), stdout); + fputc(scaleSample(PPM_GETG(transcolor), maxval, 255), stdout); + fputc(scaleSample(PPM_GETB(transcolor), maxval, 255), stdout); } else { assert(transindex <= UCHAR_MAX); fputc(0, stdout); @@ -523,7 +656,7 @@ writeDummy() { static void writeColormap(bool const explicitColormap, - Colormap const colormap, + Colormap * const colormapP, bool const directColor, unsigned int const bpp, bool const transparent, @@ -534,14 +667,14 @@ writeColormap(bool const explicitColormap, /* if there's a colormap, write it out */ if (explicitColormap) { unsigned int row; - if (!colormap) + if (!colormapP) pm_error("Internal error: user specified -colormap, but we did " "not generate a colormap."); - qsort (colormap->color_entries, colormap->ncolors, - sizeof(Color_s), palmcolor_compare_indices); - pm_writebigshort( stdout, colormap->ncolors ); - for (row = 0; row < colormap->ncolors; ++row) - pm_writebiglong (stdout, colormap->color_entries[row]); + qsort(colormapP->color_entries, colormapP->ncolors, + sizeof(ColormapEntry), palmcolor_compare_indices); + pm_writebigshort( stdout, colormapP->ncolors ); + for (row = 0; row < colormapP->ncolors; ++row) + pm_writebiglong (stdout, colormapP->color_entries[row]); } if (directColor && (version < 3)) { @@ -552,13 +685,13 @@ writeColormap(bool const explicitColormap, fputc(5, stdout); /* # of bits of blue */ fputc(0, stdout); /* reserved by Palm */ } else - pm_error("Don't know how to create %d bit DirectColor bitmaps.", + pm_error("Don't know how to create %u bit DirectColor bitmaps.", bpp); if (transparent) { fputc(0, stdout); - fputc((PPM_GETR(transcolor) * 255) / maxval, stdout); - fputc((PPM_GETG(transcolor) * 255) / maxval, stdout); - fputc((PPM_GETB(transcolor) * 255) / maxval, stdout); + fputc(scaleSample(PPM_GETR(transcolor) , maxval, 255), stdout); + fputc(scaleSample(PPM_GETG(transcolor) , maxval, 255), stdout); + fputc(scaleSample(PPM_GETB(transcolor) , maxval, 255), stdout); } else pm_writebiglong(stdout, 0); /* no transparent color */ } @@ -571,17 +704,29 @@ computeRawRowDirectColor(const xel * const xelrow, unsigned int const cols, xelval const maxval, unsigned char * const rowdata) { +/*---------------------------------------------------------------------------- + Compute a row of Palm data in raw (uncompressed) form for an image that + uses direct color (really, true color: each pixel contains RGB intensities + as distinct R, G, and B numbers). + In this format, each pixel is 16 bits: 5 red, 6 green, 5 blue. + + 'xelrow' is the image contents of row. It is 'cols' columns wide and + samples are based on maxval 'maxval'. + + Put the output data at 'rowdata'. +-----------------------------------------------------------------------------*/ unsigned int col; - unsigned char *outptr; + unsigned char * outCursor; - for (col = 0, outptr = rowdata; col < cols; ++col) { + for (col = 0, outCursor = &rowdata[0]; col < cols; ++col) { unsigned int const color = - ((((PPM_GETR(xelrow[col])*31)/maxval) << 11) | - (((PPM_GETG(xelrow[col])*63)/maxval) << 5) | - ((PPM_GETB(xelrow[col])*31)/maxval)); - *outptr++ = (color >> 8) & 0xFF; - *outptr++ = color & 0xFF; + (scaleSample(PPM_GETR(xelrow[col]), maxval, 31) << 11) | + (scaleSample(PPM_GETG(xelrow[col]), maxval, 63) << 5) | + (scaleSample(PPM_GETB(xelrow[col]), maxval, 31) << 0); + + *outCursor++ = (color >> 8) & 0xFF; + *outCursor++ = color & 0xFF; } } @@ -592,23 +737,40 @@ computeRawRowNonDirect(const xel * const xelrow, unsigned int const cols, xelval const maxval, unsigned int const bpp, - Colormap const colormap, + Colormap * const colormapP, unsigned int const newMaxval, unsigned char * const rowdata) { +/*---------------------------------------------------------------------------- + Compute a row of Palm data in raw (uncompressed) form for an image that + does not have a raster whose elements are explicit R, G, and B + intensities. + If 'colormapP' is non-null, the pixel is an index into that colormap. + 'newMaxval' is meaningless. + + If 'colormapP' is null, the pixel is a grayscale intensity, on a scale with + maximum value 'newMaxval'. (N.B. this is really direct color, but for some + reason it's historically lumped in with the paletted formats). + + 'xelrow' is the image contents of row. It is 'cols' columns wide and + samples are based on maxval 'maxval'. + + Put the output data at 'rowdata', using 'bpp' bits per pixel. +-----------------------------------------------------------------------------*/ unsigned int col; - unsigned char *outptr; + unsigned char * outCursor; + /* Points to next slot in 'rowdata' we will fill */ unsigned char outbyte; /* Accumulated bits to be output */ unsigned char outbit; /* The lowest bit number we want to access for this pixel */ - outbyte = 0x00; - outptr = rowdata; + outbyte = 0x00; /* initial value */ + outCursor = &rowdata[0]; /* Start at the beginning of the row */ for (outbit = 8 - bpp, col = 0; col < cols; ++col) { unsigned int color; - if (!colormap) { + if (!colormapP) { /* we assume grayscale, and use simple scaling */ color = (PNM_GET1(xelrow[col]) * newMaxval)/maxval; if (color > newMaxval) @@ -616,24 +778,23 @@ computeRawRowNonDirect(const xel * const xelrow, "color of %u.", color); color = newMaxval - color; /* note grayscale maps are inverted */ } else { - Color_s const temp_color = - ((((PPM_GETR(xelrow[col])*newMaxval)/maxval)<<16) - | (((PPM_GETG(xelrow[col])*newMaxval)/maxval)<<8) - | (((PPM_GETB(xelrow[col])*newMaxval)/maxval))); - Color const found = (bsearch (&temp_color, - colormap->color_entries, - colormap->ncolors, - sizeof(Color_s), - palmcolor_compare_colors)); - if (!found) { - pm_error("Color %d:%d:%d not found in colormap. " - "Try using pnmquant to reduce the " - "number of colors.", + ColormapEntry const searchTarget = + palmcolor_mapEntryColorFmPixel(xelrow[col], maxval, 255); + ColormapEntry * const foundEntryP = + bsearch(&searchTarget, + colormapP->color_entries, + colormapP->ncolors, + sizeof(ColormapEntry), + palmcolor_compare_colors); + if (!foundEntryP) { + pm_error("INERNAL ERROR: " + "Color (%u,%u,%u) not found in colormap, " + "though it was supposedly there before", PPM_GETR(xelrow[col]), PPM_GETG(xelrow[col]), PPM_GETB(xelrow[col])); } - color = (*found >> 24) & 0xFF; + color = (*foundEntryP >> 24) & 0xFF; } if (color > newMaxval) @@ -642,7 +803,7 @@ computeRawRowNonDirect(const xel * const xelrow, outbyte |= (color << outbit); if (outbit == 0) { /* Bit buffer is full. Flush to to rowdata. */ - *outptr++ = outbyte; + *outCursor++ = outbyte; outbyte = 0x00; outbit = 8 - bpp; } else @@ -650,7 +811,7 @@ computeRawRowNonDirect(const xel * const xelrow, } if ((cols % (8 / bpp)) != 0) { /* Flush bits remaining in the bit buffer to rowdata */ - *outptr++ = outbyte; + *outCursor++ = outbyte; } } @@ -830,7 +991,7 @@ rleCompressAndBufferRow(const unsigned char * const rowdata, unsigned int repeatcount; for (repeatcount = 1; repeatcount < (rowbytes - pos) && repeatcount < 255; - ++repeatcount) + ++repeatcount) if (rowdata[pos + repeatcount] != rowdata[pos]) break; @@ -870,7 +1031,7 @@ packbitsCompressAndBufferRow(const unsigned char * const rowdata, static void bufferRowFromRawRowdata(const unsigned char * const rowdata, unsigned int const rowbytes, - enum compressionType const compression, + enum CompressionType const compression, const unsigned char * const lastrow, struct seqBuffer * const rasterBufferP) { /*---------------------------------------------------------------------------- @@ -909,16 +1070,17 @@ bufferRow(const xel * const xelrow, unsigned int const rowbytes, unsigned int const bpp, unsigned int const newMaxval, - enum compressionType const compression, + enum CompressionType const compression, bool const directColor, - Colormap const colormap, + Colormap * const colormapP, unsigned char * const rowdata, unsigned char * const lastrow, struct seqBuffer * const rasterBufferP) { /*---------------------------------------------------------------------------- Add a row of the Palm Bitmap raster to buffer 'rasterBufferP'. - 'xelrow' is the image contents of row. It is 'cols' columns wide. + 'xelrow' is the image contents of row. It is 'cols' columns wide and + samples are based on maxval 'maxval'. If 'compression' indicates scanline compression, 'lastrow' is the row immediately preceding this one in the image (and this function @@ -930,7 +1092,7 @@ bufferRow(const xel * const xelrow, if (directColor) computeRawRowDirectColor(xelrow, cols, maxval, rowdata); else - computeRawRowNonDirect(xelrow, cols, maxval, bpp, colormap, newMaxval, + computeRawRowNonDirect(xelrow, cols, maxval, bpp, colormapP, newMaxval, rowdata); bufferRowFromRawRowdata(rowdata, rowbytes, compression, @@ -947,9 +1109,9 @@ bufferRaster(xel ** const xels, unsigned int const rowbytes, unsigned int const bpp, unsigned int const newMaxval, - enum compressionType const compression, + enum CompressionType const compression, bool const directColor, - Colormap const colormap, + Colormap * const colormapP, struct seqBuffer ** const rasterBufferPP) { unsigned char * rowdata; @@ -971,7 +1133,7 @@ bufferRaster(xel ** const xels, for (row = 0; row < rows; ++row) { bufferRow(xels[row], cols, maxval, rowbytes, bpp, newMaxval, compression, - directColor, colormap, rowdata, row > 0 ? lastrow : NULL, + directColor, colormapP, rowdata, row > 0 ? lastrow : NULL, *rasterBufferPP); if (compression == COMP_SCANLINE) @@ -988,8 +1150,8 @@ static void computeOffsetStuff(bool const offsetWanted, unsigned int const version, bool const directColor, - enum compressionType const compression, - bool const colormap, + enum CompressionType const compression, + bool const colormapped, unsigned int const colormapColorCount, unsigned int const sizePlusRasterSize, unsigned int * const nextDepthOffsetP, @@ -1003,7 +1165,7 @@ computeOffsetStuff(bool const offsetWanted, */ unsigned int const headerSize = ((version < 3) ? 16 : 24); unsigned int const colormapSize = - (colormap ? (2 + colormapColorCount * 4) : 0); + (colormapped ? (2 + colormapColorCount * 4) : 0); if (version < 3) { unsigned int const directSize = (directColor && version < 3) ? 8 : 0; @@ -1058,12 +1220,12 @@ writeBitmap(xel ** const xels, unsigned int const rowbytes, unsigned int const bpp, unsigned int const newMaxval, - enum compressionType const compression, + enum CompressionType const compression, bool const transparent, bool const directColor, bool const offsetWanted, - bool const hasColormap, - Colormap const colormap, + bool const colormapped, + Colormap * const colormapP, unsigned int const transindex, xel const transcolor, unsigned int const version, @@ -1086,11 +1248,11 @@ writeBitmap(xel ** const xels, */ struct seqBuffer * rasterBufferP; - writeCommonHeader(cols, rows, rowbytes, compression, hasColormap, + writeCommonHeader(cols, rows, rowbytes, compression, colormapped, transparent, directColor, bpp, version); bufferRaster(xels, cols, rows, maxval, rowbytes, bpp, newMaxval, - compression, directColor, colormap, &rasterBufferP); + compression, directColor, colormapP, &rasterBufferP); /* rasterSize itself takes 2 or 4 bytes */ if (version < 3) @@ -1099,7 +1261,7 @@ writeBitmap(xel ** const xels, sizePlusRasterSize = 4 + bufferLength(rasterBufferP); computeOffsetStuff(offsetWanted, version, directColor, compression, - hasColormap, hasColormap ? colormap->ncolors : 0, + colormapped, colormapped ? colormapP->ncolors : 0, sizePlusRasterSize, &nextDepthOffset, &nextBitmapOffset, &padBytesRequired); @@ -1111,7 +1273,7 @@ writeBitmap(xel ** const xels, maxval, transparent, transcolor, transindex, nextBitmapOffset); - writeColormap(hasColormap, colormap, directColor, bpp, + writeColormap(colormapped, colormapP, directColor, bpp, transparent, transcolor, maxval, version); if (compression != COMP_NONE) @@ -1134,8 +1296,8 @@ writeBitmap(xel ** const xels, int -main( int argc, char **argv ) { - struct cmdline_info cmdline; +main( int argc, const char **argv ) { + struct CmdlineInfo cmdline; unsigned int version; FILE* ifP; xel** xels; @@ -1148,10 +1310,9 @@ main( int argc, char **argv ) { unsigned int bpp; bool directColor; unsigned int newMaxval; - Colormap colormap; + Colormap * colormapP; - /* Parse default params */ - pnm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -1161,18 +1322,20 @@ main( int argc, char **argv ) { pm_close(ifP); if (cmdline.verbose) - pm_message("Input is %dx%d %s, maxval %d", + pm_message("Input is %ux%u %s, maxval %u", cols, rows, formatName(format), maxval); - determinePalmFormat(cols, rows, maxval, format, xels, cmdline.depth, - cmdline.maxdepth, cmdline.colormap, cmdline.verbose, - &bpp, &directColor, &colormap); + determinePalmFormat(cols, rows, maxval, format, xels, + cmdline.depthSpec, cmdline.depth, + cmdline.maxdepthSpec, cmdline.maxdepth, + cmdline.colormap, cmdline.compression, cmdline.verbose, + &bpp, &directColor, &colormapP); newMaxval = (1 << bpp) - 1; if (cmdline.transparent) findTransparentColor(cmdline.transparent, newMaxval, directColor, - maxval, colormap, &transcolor, &transindex); + maxval, colormapP, &transcolor, &transindex); else transindex = 0; @@ -1185,7 +1348,7 @@ main( int argc, char **argv ) { writeBitmap(xels, cols, rows, maxval, rowbytes, bpp, newMaxval, cmdline.compression, !!cmdline.transparent, directColor, cmdline.offset, - cmdline.colormap, colormap, transindex, transcolor, + cmdline.colormap, colormapP, transindex, transcolor, version, cmdline.density, cmdline.withdummy); return 0; diff --git a/converter/other/pnmtopclxl.c b/converter/other/pnmtopclxl.c index 8cabb614..f7db62ee 100644 --- a/converter/other/pnmtopclxl.c +++ b/converter/other/pnmtopclxl.c @@ -3,7 +3,7 @@ * * (C) 2002 Jochen Karrer, Linuxdata GbR * - * convert a pnm to PCL-XL image + * convert a pnm to PCL-XL image * * ------------------------------------------------------------- */ @@ -44,7 +44,7 @@ typedef struct InputSource { - const char * name; + const char * name; struct InputSource * next; } InputSource; @@ -82,7 +82,7 @@ parseCommandLine(int argc, char ** argv, struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- parse program command line described in Unix standard form by argc - and argv. Return the information in the options as *cmdlineP. + 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. @@ -104,25 +104,25 @@ parseCommandLine(int argc, char ** argv, option_def_index = 0; /* incremented by OPTENT3 */ OPTENT3(0, "dpi", OPT_UINT, &cmdlineP->dpi, &dpiSpec, 0); - OPTENT3(0, "xoffs", OPT_FLOAT, &cmdlineP->xoffs, + OPTENT3(0, "xoffs", OPT_FLOAT, &cmdlineP->xoffs, &xoffsSpec, 0); - OPTENT3(0, "yoffs", OPT_FLOAT, &cmdlineP->yoffs, + OPTENT3(0, "yoffs", OPT_FLOAT, &cmdlineP->yoffs, &yoffsSpec, 0); - OPTENT3(0, "format", OPT_STRING, &formatOpt, + OPTENT3(0, "format", OPT_STRING, &formatOpt, &formatSpec, 0); - OPTENT3(0, "duplex", OPT_STRING, &duplexOpt, + OPTENT3(0, "duplex", OPT_STRING, &duplexOpt, &cmdlineP->duplexSpec, 0); OPTENT3(0, "copies", OPT_UINT, &cmdlineP->copies, &cmdlineP->copiesSpec, 0); - OPTENT3(0, "colorok", OPT_FLAG, NULL, + OPTENT3(0, "colorok", OPT_FLAG, NULL, &cmdlineP->colorok, 0); - OPTENT3(0, "center", OPT_FLAG, NULL, + OPTENT3(0, "center", OPT_FLAG, NULL, &cmdlineP->center, 0 ); OPTENT3(0, "feeder", OPT_UINT, &cmdlineP->feeder, &cmdlineP->feederSpec, 0); OPTENT3(0, "outtray", OPT_UINT, &cmdlineP->outtray, &cmdlineP->outtraySpec, 0); - OPTENT3(0, "verbose", OPT_FLAG, NULL, + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); OPTENT3(0, "jobsetup", OPT_STRING, &cmdlineP->jobsetup, &jobsetupSpec, 0); @@ -216,7 +216,7 @@ parseCommandLine(int argc, char ** argv, static void freeSource(InputSource * const firstSourceP) { - + InputSource * sourceP; sourceP = firstSourceP; @@ -284,7 +284,7 @@ pnmToPcllinePackbits(pclGenerator * const pclGeneratorP, unsigned int col, padCt; unsigned int const padsize = pclGeneratorP->paddedLinelen - pclGeneratorP->linelen; - + tuplerow = pnm_allocpamrow(pamP); pnm_readpamrow(pamP, tuplerow); @@ -297,7 +297,7 @@ pnmToPcllinePackbits(pclGenerator * const pclGeneratorP, if (bitmask == 0) { pclGeneratorP->data[pclGeneratorP->cursor++] = accum; bitmask = 0x80; accum = 0x0; - } + } } if (bitmask != 0x80) pclGeneratorP->data[pclGeneratorP->cursor++] = accum; @@ -351,7 +351,7 @@ createPclGeneratorPackbits(struct pam * const pamP, pclGeneratorP->data = malloc(pclDatabuffSize(pclGeneratorP->paddedLinelen)); - + if (pclGeneratorP->data == NULL) pm_error("Unable to allocate row buffer."); @@ -378,7 +378,7 @@ pnmToPcllineWholebytes(pclGenerator * const pclGeneratorP, for (col = 0; col < pamP->width; ++col) { unsigned int plane; for (plane = 0; plane < pamP->depth; ++plane) { - pclGeneratorP->data[pclGeneratorP->cursor++] = + pclGeneratorP->data[pclGeneratorP->cursor++] = pnm_scalesample(tuplerow[col][plane], pamP->maxval, 255); } } @@ -399,7 +399,7 @@ createPclGeneratorWholebytes(struct pam * const pamP, pclGenerator * pclGenP; MALLOCVAR_NOFAIL(pclGenP); - + if (pamP->depth < 3) pclGenP->colorSpace = eGray; else @@ -418,7 +418,7 @@ createPclGeneratorWholebytes(struct pam * const pamP, if (pclGenP->data == NULL) pm_error("Unable to allocate row buffer."); } - + pclGenP->getnextrow = pnmToPcllineWholebytes; *pclGenPP = pclGenP; @@ -436,7 +436,7 @@ destroyPclGenerator(pclGenerator * const pclGenP) { -static void +static void createPclGenerator(struct pam * const pamP, pclGenerator ** const pclGeneratorPP, bool const colorok) { @@ -448,16 +448,16 @@ createPclGenerator(struct pam * const pamP, "through Ppmtopgm. To suppress this warning, use the " "-colorok option."); - if (pamP->depth == 1 && pamP->maxval == 1) + if (pamP->depth == 1 && pamP->maxval == 1) createPclGeneratorPackbits(pamP, pclGeneratorPP); - else + else createPclGeneratorWholebytes(pamP, pclGeneratorPP); } -struct tPrinter { +struct tPrinter { const char *name; float topmargin; float bottommargin; @@ -478,7 +478,7 @@ out_ubyte(int const fd, -static int +static int XL_Operator(int const fd, enum Operator const data) { @@ -514,7 +514,7 @@ static int out_sint16(int const fd, signed short const sdata ) { - unsigned short const data= (unsigned short)sdata; + unsigned short const data= (unsigned short)sdata; unsigned char c[2]; @@ -559,7 +559,7 @@ xl_ubyte_array(int const fd, unsigned int i; unsigned char head[4]; - + head[0] = 0xc8; head[1] = 0xc1; head[2] = len & 0xff; @@ -671,7 +671,7 @@ convertAndWriteRleBlock(int const outFd, pm_rlenc_compressbyte(pclGeneratorP->data, outbuf, PM_RLE_PACKBITS, pclGeneratorP->paddedLinelen * lineCt, &rlelen); - xl_dataLength(outFd, rlelen); + xl_dataLength(outFd, rlelen); XY_Write(outFd, outbuf, rlelen); } @@ -680,10 +680,10 @@ convertAndWriteRleBlock(int const outFd, /* * ------------------------------------------------------------ * XL_WriteImage - * Write a PCL-XL image to the datastream + * Write a PCL-XL image to the datastream * ------------------------------------------------------------ */ -static void +static void convertAndWriteImage(int const outFd, pclGenerator * const pclGenP, struct pam * const pamP) { @@ -695,10 +695,10 @@ convertAndWriteImage(int const outFd, xl_ubyte(outFd, eDirectPixel); xl_attr_ubyte(outFd, aColorMapping); xl_ubyte(outFd, pclGenP->colorDepth); xl_attr_ubyte(outFd, aColorDepth); - xl_uint16(outFd, pclGenP->width); xl_attr_ubyte(outFd, aSourceWidth); - xl_uint16(outFd, pclGenP->height); xl_attr_ubyte(outFd, aSourceHeight); - xl_uint16_xy(outFd, pclGenP->width*1, pclGenP->height*1); - xl_attr_ubyte(outFd, aDestinationSize); + xl_uint16(outFd, pclGenP->width); xl_attr_ubyte(outFd, aSourceWidth); + xl_uint16(outFd, pclGenP->height); xl_attr_ubyte(outFd, aSourceHeight); + xl_uint16_xy(outFd, pclGenP->width*1, pclGenP->height*1); + xl_attr_ubyte(outFd, aDestinationSize); XL_Operator(outFd, oBeginImage); pm_rlenc_allocoutbuf(&outbuf, inSize, PM_RLE_PACKBITS); @@ -707,13 +707,13 @@ convertAndWriteImage(int const outFd, unsigned int const blockHeight = MIN(20, pclGenP->height-blockStartLine); - xl_uint16(outFd, blockStartLine); xl_attr_ubyte(outFd, aStartLine); + xl_uint16(outFd, blockStartLine); xl_attr_ubyte(outFd, aStartLine); xl_uint16(outFd, blockHeight); xl_attr_ubyte(outFd, aBlockHeight); xl_ubyte(outFd, eRLECompression); xl_attr_ubyte(outFd, aCompressMode); /* In modern PCL-XL, we could use a PadBytesMultiple attribute here to avoid having to pad the data to a multiple of 4 bytes. But PCL-XL 1.1 didn't have PadBytesMultiple. - xl_ubyte(outFd, 1); xl_attr_ubyte(outFd, aPadBytesMultiple); + xl_ubyte(outFd, 1); xl_attr_ubyte(outFd, aPadBytesMultiple); */ XL_Operator(outFd, oReadImage); convertAndWriteRleBlock(outFd, pclGenP, pamP, @@ -735,16 +735,16 @@ printEmbeddedImage(int const outFd, struct pam pam; pclGenerator * pclGeneratorP; - openDataSource(outFd, eBinaryLowByteFirst, eDefaultSource); + openDataSource(outFd, eBinaryLowByteFirst, eDefaultDataSource); ifP = pm_openr(sourceP->name); pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type)); - + createPclGenerator(&pam, &pclGeneratorP, colorok); convertAndWriteImage(outFd, pclGeneratorP, &pam); - + destroyPclGenerator(pclGeneratorP); pm_close(ifP); @@ -772,9 +772,9 @@ copyFile(const char * const sourceFileName, if (ferror(sourceFileP)) pm_error("Read from file failed. errno=%d (%s)", errno, strerror(errno)); - + totalBytesWritten = 0; - + while (totalBytesWritten < bytesRead) { ssize_t rc; @@ -804,16 +804,16 @@ jobHead(int const outFd, as opposed to e.g. Postscript. -----------------------------------------------------------------------------*/ /* Reset */ - XY_Puts(outFd,"\033%-12345X"); + XY_Puts(outFd,"\033%-12345X"); if (userJobSetupFileName) copyFile(userJobSetupFileName, outFd); if (renderGray) - XY_Puts(outFd, "@PJL SET RENDERMODE=GRAYSCALE\n"); + XY_Puts(outFd, "@PJL SET RENDERMODE=GRAYSCALE\n"); - XY_Puts(outFd, "@PJL ENTER LANGUAGE=PCLXL\n"); - XY_Puts(outFd, ") HP-PCL XL;1;1;Generated by Netpbm Pnmtopclxl\n"); + XY_Puts(outFd, "@PJL ENTER LANGUAGE=PCLXL\n"); + XY_Puts(outFd, ") HP-PCL XL;1;1;Generated by Netpbm Pnmtopclxl\n"); } @@ -825,7 +825,7 @@ jobEnd(int const outFd) { Reset printer to quiescent mode. Exit the printer language. -----------------------------------------------------------------------------*/ - XY_Puts(outFd,"\033%-12345X"); + XY_Puts(outFd,"\033%-12345X"); } @@ -852,7 +852,7 @@ beginPage(int const outFd, } if (doMediaDestination) { - xl_ubyte(outFd, mediaDestination); + xl_ubyte(outFd, mediaDestination); xl_attr_ubyte(outFd, aMediaDestination); } @@ -898,11 +898,11 @@ setColorSpace(int const outFd, paletteDepth is not e8Bit. Is each palette entry still a byte and only some of the byte gets used? Or are there multiple entries per byte? -----------------------------------------------------------------------------*/ - xl_ubyte(outFd, colorSpace); xl_attr_ubyte(outFd, aColorSpace); + xl_ubyte(outFd, colorSpace); xl_attr_ubyte(outFd, aColorSpace); if (palette) { - xl_ubyte(outFd, paletteDepth); - xl_attr_ubyte(outFd, aPaletteDepth); - xl_ubyte_array(outFd, palette, paletteSize); + xl_ubyte(outFd, paletteDepth); + xl_attr_ubyte(outFd, aPaletteDepth); + xl_ubyte_array(outFd, palette, paletteSize); xl_attr_ubyte(outFd, aPaletteData); } XL_Operator(outFd, oSetColorSpace); @@ -925,8 +925,8 @@ positionCursor(int const outFd, float xpos, ypos; if (center) { - float const width = 1.0 * imageWidth/dpi; - float const height = 1.0 * imageHeight/dpi; + float const width = 1.0 * imageWidth/dpi; + float const height = 1.0 * imageHeight/dpi; xpos = (PAPERWIDTH(format) - width)/2; ypos = (PAPERHEIGHT(format) - height)/2; } else { @@ -985,11 +985,11 @@ convertAndPrintPage(int const outFd, an IllegalArraySize error from the printer on the SetColorSpace command. - So we don't use a palette at all now. + So we don't use a palette at all now. */ setColorSpace(outFd, pclGeneratorP->colorSpace, NULL, 0, 0); - positionCursor(outFd, center, xoffs, yoffs, + positionCursor(outFd, center, xoffs, yoffs, pclGeneratorP->width, pclGeneratorP->height, dpi, format); convertAndWriteImage(outFd, pclGeneratorP, pamP); @@ -1007,7 +1007,7 @@ beginSession(int const outFd, bool const noReporting, enum ErrorReport const errorReport) { - xl_uint16_xy(outFd, xdpi, ydpi); xl_attr_ubyte(outFd, aUnitsPerMeasure); + xl_uint16_xy(outFd, xdpi, ydpi); xl_attr_ubyte(outFd, aUnitsPerMeasure); xl_ubyte(outFd, measure); xl_attr_ubyte(outFd, aMeasure); /* xl_ubyte(outFd,eNoReporting); xl_attr_ubyte(outFd,aErrorReport); */ xl_ubyte(outFd,errorReport); xl_attr_ubyte(outFd,aErrorReport); @@ -1015,8 +1015,8 @@ beginSession(int const outFd, } - -static void + +static void endSession(int outFd) { XL_Operator(outFd,oEndSession); } @@ -1046,9 +1046,9 @@ printPages(int const outFd, InputSource * sourceP; unsigned int sourceNum; - sourceP = firstSourceP; + sourceP = firstSourceP; - openDataSource(outFd, eBinaryLowByteFirst, eDefaultSource); + openDataSource(outFd, eBinaryLowByteFirst, eDefaultDataSource); sourceNum = 0; /* initial value */ @@ -1074,9 +1074,9 @@ printPages(int const outFd, pm_message("Processing File %u, Page %u", sourceNum, pageNum); pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type)); - + createPclGenerator(&pam, &pclGeneratorP, colorok); - + convertAndPrintPage( outFd, pclGeneratorP, &pam, format, dpi, center, xoffs, yoffs, doDuplex, duplex, @@ -1087,7 +1087,7 @@ printPages(int const outFd, } } pm_close(ifP); - sourceP = sourceP->next; + sourceP = sourceP->next; } closeDataSource(outFd); } @@ -1100,9 +1100,9 @@ main(int argc, char *argv[]) { int const outFd = STDOUT_FILENO; struct cmdlineInfo cmdline; - + /* In case you're wondering why we do direct file descriptor I/O - instead of stream (FILE *), it's because Jochen originally + instead of stream (FILE *), it's because Jochen originally wrote this code for an embedded system with diet-libc. Without the stream library, the statically linked binary was only about 5K big. @@ -1116,7 +1116,7 @@ main(int argc, char *argv[]) { else { jobHead(outFd, cmdline.rendergray, cmdline.jobsetup); - beginSession(outFd, cmdline.dpi, cmdline.dpi, eInch, + beginSession(outFd, cmdline.dpi, cmdline.dpi, eInch, FALSE, eBackChAndErrPage); printPages(outFd, cmdline.sourceP, diff --git a/converter/other/pnmtoplainpnm b/converter/other/pnmtoplainpnm index 87c58597..4f5378b2 100755 --- a/converter/other/pnmtoplainpnm +++ b/converter/other/pnmtoplainpnm @@ -1,3 +1,3 @@ #! /bin/sh -pnmtopnm -plain $@ +pamtopnm -plain $@ diff --git a/converter/other/pnmtopng.c b/converter/other/pnmtopng.c index 3899a9d2..60b8276b 100644 --- a/converter/other/pnmtopng.c +++ b/converter/other/pnmtopng.c @@ -26,7 +26,7 @@ it's easy to see that an ordinary fax could deplete your virtual memory and even if it didn't, it might deplete your real memory and iterating through the array would cause thrashing. This program - iterates through the image multiple times. + iterates through the image multiple times. So instead, we read the image into memory one row at a time, into a single row buffer. We use Netpbm's pm_openr_seekable() facility to @@ -38,19 +38,19 @@ in the system's I/O cache (remember that the file is a lot smaller than the xel array you'd get by doing a pnm_readpnm() of it). - However, it does introduce some delay because of all the system calls + However, it does introduce some delay because of all the system calls required to read the file. A future enhancement might read the entire - file into an xel array in some cases, and read one row at a time in + file into an xel array in some cases, and read one row at a time in others, depending on the needs of the particular use. We do still read the entire alpha mask (if there is one) into a - 'gray' array, rather than access it one row at a time. + 'gray' array, rather than access it one row at a time. Before May 2001, we did in fact read the whole image into an xel array, and we got complaints. Before April 2000, it wasn't as big a problem because xels were only 24 bits. Now they're 96. */ - + #ifndef PNMTOPNG_WARNING_LEVEL # define PNMTOPNG_WARNING_LEVEL 0 /* use 0 for backward compatibility, */ #endif /* 2 for warnings (1 == error) */ @@ -62,7 +62,7 @@ /* Because of a design error in png.h, you must not #include <setjmp.h> before <png.h>. If you do, png.h won't compile. */ -#include <setjmp.h> +#include <setjmp.h> #include <zlib.h> #include "pm_c_util.h" @@ -170,7 +170,7 @@ parseSizeOpt(const char * const sizeOpt, struct pngx_phys * const sizeP) { int count; - + count = sscanf(sizeOpt, "%d %d %d", &sizeP->x, &sizeP->y, &sizeP->unit); if (count != 3) @@ -185,7 +185,7 @@ parseRgbOpt(const char * const rgbOpt, struct pngx_chroma * const rgbP) { int count; - + count = sscanf(rgbOpt, "%f %f %f %f %f %f %f %f", &rgbP->wx, &rgbP->wy, &rgbP->rx, &rgbP->ry, @@ -204,7 +204,7 @@ parseRgbOpt(const char * const rgbOpt, static void parseSrgbintentOpt(const char * const srgbintentOpt, pngx_srgbIntent * const srgbintentP) { - + if (streq(srgbintentOpt, "perceptual")) *srgbintentP = PNGX_PERCEPTUAL; else if (streq(srgbintentOpt, "relativecolorimetric")) @@ -242,7 +242,7 @@ parseModtimeOpt(const char * const modtimeOpt, if (count != 6) pm_error("Invalid value for -modtime '%s'. It should have " "the form [yy]yy-mm-dd hh:mm:ss.", modtimeOpt); - + if (year < 0) pm_error("Year is negative in -modtime value '%s'", modtimeOpt); if (year > 9999) @@ -290,7 +290,7 @@ parseCommandLine(int argc, const char ** argv, struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- parse program command line described in Unix standard form by argc - and argv. Return the information in the options as *cmdlineP. + 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. @@ -422,11 +422,11 @@ parseCommandLine(int argc, const char ** argv, cmdlineP->ztxt = NULL; if (!paletteSpec) cmdlineP->palette = NULL; - + if (filterSpec && (nofilter + sub + up + avg + paeth > 0)) pm_error("You may mot specify -filter with " "-nofilter, -sub, -up, -avg, or -paeth"); - + if (filterSpec) { if (filter < 0 || filter > 4) pm_error("-filter is obsolete. Use -nofilter, -sub, -up, -avg, " @@ -460,13 +460,12 @@ parseCommandLine(int argc, const char ** argv, cmdlineP->filterSet |= PNG_FILTER_PAETH; } } - if (cmdlineP->sizeSpec) parseSizeOpt(size, &cmdlineP->size); if (cmdlineP->rgbSpec) parseRgbOpt(rgb, &cmdlineP->rgb); - + if (cmdlineP->srgbintentSpec) parseSrgbintentOpt(srgbintent, &cmdlineP->srgbintent); @@ -538,14 +537,14 @@ reportInputType(int const format, static png_color_16 -xelToPngColor_16(xel const input, - xelval const maxval, +xelToPngColor_16(xel const input, + xelval const maxval, xelval const pngMaxval) { png_color_16 retval; xel scaled; - + PPM_DEPTH(scaled, input, maxval, pngMaxval); retval.red = PPM_GETR(scaled); @@ -559,12 +558,12 @@ xelToPngColor_16(xel const input, static void -closestColorInPalette(pixel const targetColor, +closestColorInPalette(pixel const targetColor, pixel palette_pnm[], unsigned int const paletteSize, unsigned int * const bestIndexP, unsigned int * const bestMatchP) { - + unsigned int paletteIndex; unsigned int bestIndex; unsigned int bestMatch; @@ -573,7 +572,7 @@ closestColorInPalette(pixel const targetColor, bestMatch = UINT_MAX; for (paletteIndex = 0; paletteIndex < paletteSize; ++paletteIndex) { - unsigned int const dist = + unsigned int const dist = PPM_DISTANCE(palette_pnm[paletteIndex], targetColor); if (dist < bestMatch) { @@ -678,13 +677,13 @@ static colorhist_vector getChv_chv; static void -getChv(FILE * const ifP, +getChv(FILE * const ifP, pm_filepos const rasterPos, - int const cols, - int const rows, + int const cols, + int const rows, xelval const maxval, - int const format, - int const maxColors, + int const format, + int const maxColors, colorhist_vector * const chvP, unsigned int * const colorsP) { /*---------------------------------------------------------------------------- @@ -693,7 +692,7 @@ getChv(FILE * const ifP, raster starts at position 'rasterPos' of the file. The image's properties are 'cols', 'rows', 'maxval', and 'format'. - Return the number of colors as *colorsP. Return the details of the + Return the number of colors as *colorsP. Return the details of the colors in newly malloc'ed storage, and its address as *chvP. If there are more than 'maxColors' colors, though, just return NULL as *chvP and leave *colorsP undefined. @@ -708,13 +707,13 @@ getChv(FILE * const ifP, if (!getChv_computed) { int colorCount; - if (verbose) + if (verbose) pm_message ("Finding colors in input image..."); pm_seek2(ifP, &rasterPos, sizeof(rasterPos)); - getChv_chv = ppm_computecolorhist2(ifP, cols, rows, maxval, format, + getChv_chv = ppm_computecolorhist2(ifP, cols, rows, maxval, format, maxColors, &colorCount); - + getChv_colors = colorCount; if (verbose) { @@ -745,7 +744,7 @@ static void freeChv(void) { static bool pgmBitsAreRepeated(unsigned int const repeatedSize, FILE * const ifP, - pm_filepos const rasterPos, + pm_filepos const rasterPos, int const cols, int const rows, xelval const maxval, @@ -772,7 +771,7 @@ pgmBitsAreRepeated(unsigned int const repeatedSize, xel * xelrow; xelrow = pnm_allocrow(cols); - + pm_seek2(ifP, &rasterPos, sizeof(rasterPos)); mayscale = TRUE; /* initial assumption */ @@ -797,8 +796,8 @@ pgmBitsAreRepeated(unsigned int const repeatedSize, static void -meaningful_bits_pgm(FILE * const ifP, - pm_filepos const rasterPos, +meaningful_bits_pgm(FILE * const ifP, + pm_filepos const rasterPos, int const cols, int const rows, xelval const maxval, @@ -849,8 +848,8 @@ meaningful_bits_pgm(FILE * const ifP, static void -meaningful_bits_ppm(FILE * const ifp, - pm_filepos const rasterPos, +meaningful_bits_ppm(FILE * const ifp, + pm_filepos const rasterPos, int const cols, int const rows, xelval const maxval, @@ -903,12 +902,12 @@ meaningful_bits_ppm(FILE * const ifp, static void -tryTransparentColor(FILE * const ifp, - pm_filepos const rasterPos, - int const cols, - int const rows, +tryTransparentColor(FILE * const ifp, + pm_filepos const rasterPos, + int const cols, + int const rows, xelval const maxval, - int const format, + int const format, gray ** const alphaMask, gray const alphaMaxval, pixel const transcolor, @@ -926,7 +925,7 @@ tryTransparentColor(FILE * const ifp, pm_seek2(ifp, &rasterPos, sizeof(rasterPos)); singleColorIsTrans = TRUE; /* initial assumption */ - + for (row = 0; row < rows && singleColorIsTrans; ++row) { int col; pnm_readpnmrow(ifp, xelrow, cols, maxval, format); @@ -961,7 +960,7 @@ tryTransparentColor(FILE * const ifp, } } } - } + } pnm_freerow(xelrow); } @@ -969,15 +968,15 @@ tryTransparentColor(FILE * const ifp, static void analyzeAlpha(FILE * const ifP, - pm_filepos const rasterPos, - unsigned int const cols, - unsigned int const rows, + pm_filepos const rasterPos, + unsigned int const cols, + unsigned int const rows, xelval const maxval, - int const format, + int const format, gray ** const alphaMask, gray const alphaMaxval, bool * const allOpaqueP, - bool * const singleColorIsTransP, + bool * const singleColorIsTransP, pixel * const alphaTranscolorP) { /*---------------------------------------------------------------------------- Get information about the alpha mask, in combination with the masked @@ -1003,7 +1002,7 @@ analyzeAlpha(FILE * const ifP, /* We found a pixel in the image where the alpha mask says it is not fully opaque. */ - + xelrow = pnm_allocrow(cols); { @@ -1083,7 +1082,7 @@ determineTransparency(struct cmdlineInfo const cmdline, or identify a transparent color. We return as *transparentP: - + -1 PNG is not to have single-color transparency 1 PNG is to have single-color transparency as directed by user 2 PNG is to have single-color transparency that effects an alpha @@ -1107,7 +1106,7 @@ determineTransparency(struct cmdlineInfo const cmdline, if (alphaCols != cols || alphaRows != rows) { pm_error("dimensions for image and alpha mask do not agree"); } - analyzeAlpha(ifP, rasterPos, cols, rows, maxval, format, + analyzeAlpha(ifP, rasterPos, cols, rows, maxval, format, alphaMask, alphaMaxval, &allOpaque, &alphaCanBeTransparencyIndex, &alphaTranscolor); @@ -1137,7 +1136,7 @@ determineTransparency(struct cmdlineInfo const cmdline, *alphaMaxvalP = 255; if (cmdline.transparent) { - const char * transstring2; + const char * transstring2; /* The -transparent value, but with possible leading '=' removed */ if (cmdline.transparent[0] == '=') { *transExactP = TRUE; @@ -1145,12 +1144,12 @@ determineTransparency(struct cmdlineInfo const cmdline, } else { *transExactP = FALSE; transstring2 = cmdline.transparent; - } + } /* We do this funny PPM_DEPTH thing instead of just passing 'maxval' to ppm_parsecolor() because ppm_parsecolor() does a cheap maxval scaling, and this is more precise. */ - PPM_DEPTH(*transColorP, + PPM_DEPTH(*transColorP, ppm_parsecolor(transstring2, PNM_OVERALLMAXVAL), PNM_OVERALLMAXVAL, maxval); @@ -1167,9 +1166,9 @@ determineBackground(struct cmdlineInfo const cmdline, xelval const maxval, xel * const backColorP) { - if (cmdline.background) + if (cmdline.background) PPM_DEPTH(*backColorP, - ppm_parsecolor(cmdline.background, PNM_OVERALLMAXVAL), + ppm_parsecolor(cmdline.background, PNM_OVERALLMAXVAL), PNM_OVERALLMAXVAL, maxval);; } @@ -1221,8 +1220,8 @@ hasColor(FILE * const ifP, static void -findRedundantBits(FILE * const ifp, - int const rasterPos, +findRedundantBits(FILE * const ifp, + int const rasterPos, int const cols, int const rows, xelval const maxval, @@ -1239,13 +1238,13 @@ findRedundantBits(FILE * const ifp, of bits, starting from the least significant end, that contain original information. -----------------------------------------------------------------------------*/ - if (!alpha && PNM_FORMAT_TYPE(format) == PGM_TYPE && !force) + if (!alpha && PNM_FORMAT_TYPE(format) == PGM_TYPE && !force) meaningful_bits_pgm(ifp, rasterPos, cols, rows, maxval, format, meaningfulBitsP); else if (PNM_FORMAT_TYPE(format) == PPM_TYPE && !force) meaningful_bits_ppm(ifp, rasterPos, cols, rows, maxval, format, meaningfulBitsP); - else + else *meaningfulBitsP = pm_maxvaltobits(maxval); if (verbose && *meaningfulBitsP != pm_maxvaltobits(maxval)) @@ -1257,24 +1256,24 @@ findRedundantBits(FILE * const ifp, static void readOrderedPalette(FILE * const pfp, - xel ordered_palette[], + xel ordered_palette[], unsigned int * const ordered_palette_size_p) { xel ** xels; int cols, rows; xelval maxval; int format; - + if (verbose) pm_message("reading ordered palette (colormap)..."); xels = pnm_readpnm(pfp, &cols, &rows, &maxval, &format); - - if (PNM_FORMAT_TYPE(format) != PPM_TYPE) + + if (PNM_FORMAT_TYPE(format) != PPM_TYPE) pm_error("ordered palette must be a PPM file, not type %d", format); *ordered_palette_size_p = rows * cols; - if (*ordered_palette_size_p > MAXCOLORS) + if (*ordered_palette_size_p > MAXCOLORS) pm_error("ordered-palette image contains %d pixels. Maximum is %d", *ordered_palette_size_p, MAXCOLORS); if (verbose) @@ -1286,12 +1285,12 @@ readOrderedPalette(FILE * const pfp, j = 0; /* initial value */ for (row = 0; row < rows; ++row) { int col; - for (col = 0; col < cols; ++col) + for (col = 0; col < cols; ++col) ordered_palette[j++] = xels[row][col]; } } pnm_freearray(xels, rows); -} +} @@ -1315,31 +1314,31 @@ compute_nonalpha_palette(colorhist_vector const chv, wants the colors in a particular order in the palette. -----------------------------------------------------------------------------*/ unsigned int colorIndex; - + xel ordered_palette[MAXCOLORS]; unsigned int ordered_palette_size; if (pfp) { readOrderedPalette(pfp, ordered_palette, &ordered_palette_size); - if (colors != ordered_palette_size) + if (colors != ordered_palette_size) pm_error("sizes of ordered palette (%d) " "and existing palette (%d) differ", ordered_palette_size, colors); - + /* Make sure the ordered palette contains all the colors in - the image + the image */ for (colorIndex = 0; colorIndex < colors; colorIndex++) { int j; bool found; - + found = FALSE; for (j = 0; j < ordered_palette_size && !found; ++j) { - if (PNM_EQUAL(ordered_palette[j], chv[colorIndex].color)) + if (PNM_EQUAL(ordered_palette[j], chv[colorIndex].color)) found = TRUE; } - if (!found) + if (!found) pm_error("failed to find color (%d, %d, %d), which is in the " "input image, in the ordered palette", PPM_GETR(chv[colorIndex].color), @@ -1352,7 +1351,7 @@ compute_nonalpha_palette(colorhist_vector const chv, for (colorIndex = 0; colorIndex < colors; ++colorIndex) palette_pnm[colorIndex] = ordered_palette[colorIndex]; } else { - for (colorIndex = 0; colorIndex < colors; ++colorIndex) + for (colorIndex = 0; colorIndex < colors; ++colorIndex) palette_pnm[colorIndex] = chv[colorIndex].color; } *paletteSizeP = colors; @@ -1442,7 +1441,7 @@ computeUnsortedAlphaPalette(FILE * const ifP, described by 'cols', 'rows', 'maxval', and 'format'. Using the alpha mask 'alpha_mask' and color map 'chv' (of size 'colors') - for the image, construct a palette of (color index, alpha) ordered pairs + for the image, construct a palette of (color index, alpha) ordered pairs for the image, as follows. The alpha/color palette is the set of all ordered pairs of @@ -1476,7 +1475,7 @@ computeUnsortedAlphaPalette(FILE * const ifP, alphasOfColor[colorIndex] = NULL; alphasOfColorCnt[colorIndex] = 0; } - + pm_seek2(ifP, &rasterPos, sizeof(rasterPos)); xelrow = pnm_allocrow(cols); @@ -1562,22 +1561,22 @@ sortAlphaPalette(gray * const alphasOfColor[], unsigned int bot_idx; unsigned int top_idx; unsigned int colorIndex; - + /* We start one index at the bottom of the palette index range and another at the top. We run through the unsorted palette, and when we see an opaque entry, we map it to the current top - cursor and bump it down. When we see a non-opaque entry, we map + cursor and bump it down. When we see a non-opaque entry, we map it to the current bottom cursor and bump it up. Because the input and output palettes are the same size, the two cursors should meet right when we process the last entry of the unsorted palette. - */ + */ bot_idx = 0; top_idx = alphasFirstIndex[colors-1] + alphasOfColorCnt[colors-1] - 1; - + for (colorIndex = 0; colorIndex < colors; ++colorIndex) { unsigned int j; for (j = 0; j < alphasOfColorCnt[colorIndex]; ++j) { - unsigned int const paletteIndex = + unsigned int const paletteIndex = alphasFirstIndex[colorIndex] + j; if (alphasOfColor[colorIndex][j] == alphaMaxval) mapping[paletteIndex] = top_idx--; @@ -1598,7 +1597,7 @@ sortAlphaPalette(gray * const alphasOfColor[], static void -compute_alpha_palette(FILE * const ifP, +compute_alpha_palette(FILE * const ifP, int const cols, int const rows, xelval const maxval, @@ -1626,10 +1625,10 @@ compute_alpha_palette(FILE * const ifP, The palette is sorted so that the opaque entries are last, and we return *transSizeP as the number of non-opaque entries. - palette[] and trans[] are allocated by the caller to at least + palette[] and trans[] are allocated by the caller to at least MAXPALETTEENTRIES elements. - If there are more than MAXPALETTEENTRIES color/alpha pairs in the image, + If there are more than MAXPALETTEENTRIES color/alpha pairs in the image, don't return any palette information -- just return *tooBigP == TRUE. -----------------------------------------------------------------------------*/ colorhist_vector chv; @@ -1638,8 +1637,8 @@ compute_alpha_palette(FILE * const ifP, gray * alphas_of_color[MAXPALETTEENTRIES]; unsigned int alphas_first_index[MAXPALETTEENTRIES]; unsigned int alphas_of_color_cnt[MAXPALETTEENTRIES]; - - getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, + + getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, &chv, &colors); assert(colors <= ARRAY_SIZE(alphas_of_color)); @@ -1658,7 +1657,7 @@ compute_alpha_palette(FILE * const ifP, index into the sorted PNG palette of the alpha/color pair whose index is x in the unsorted PNG palette. This mapping sorts the palette so that opaque entries - are last. + are last. */ *paletteSizeP = colors == 0 ? @@ -1677,22 +1676,22 @@ compute_alpha_palette(FILE * const ifP, for (colorIndex = 0; colorIndex < colors; ++colorIndex) { unsigned int j; for (j = 0; j < alphas_of_color_cnt[colorIndex]; ++j) { - unsigned int const paletteIndex = + unsigned int const paletteIndex = alphas_first_index[colorIndex] + j; palette_pnm[mapping[paletteIndex]] = chv[colorIndex].color; - trans_pnm[mapping[paletteIndex]] = + trans_pnm[mapping[paletteIndex]] = alphas_of_color[colorIndex][j]; } } } freeAlphasOfColor(alphas_of_color, colors); } -} +} static void -makeOneColorTransparentInPalette(xel const transColor, +makeOneColorTransparentInPalette(xel const transColor, bool const exact, pixel palette_pnm[], unsigned int const paletteSize, @@ -1700,12 +1699,12 @@ makeOneColorTransparentInPalette(xel const transColor, unsigned int * const transSizeP) { /*---------------------------------------------------------------------------- Find the color 'transColor' in the color/alpha palette defined by - palette_pnm[], paletteSize, trans_pnm[] and *transSizeP. + palette_pnm[], paletteSize, trans_pnm[] and *transSizeP. Make that entry fully transparent. Rearrange the palette so that that entry is first. (The PNG compressor - can do a better job when the opaque entries are all last in the + can do a better job when the opaque entries are all last in the color/alpha palette). If the specified color is not there and exact == TRUE, return @@ -1720,26 +1719,26 @@ makeOneColorTransparentInPalette(xel const transColor, unsigned int distance; assert(paletteSize > 0); - + if (*transSizeP != 0) pm_error("Internal error: trying to make a color in the palette " "transparent where there already is one."); - closestColorInPalette(transColor, palette_pnm, paletteSize, + closestColorInPalette(transColor, palette_pnm, paletteSize, &transparentIndex, &distance); if (distance != 0 && exact) { pm_message("specified transparent color not present in palette; " "ignoring -transparent"); errorlevel = PNMTOPNG_WARNING_LEVEL; - } else { + } else { /* Swap this with the first entry in the palette */ pixel tmp; - + tmp = palette_pnm[transparentIndex]; palette_pnm[transparentIndex] = palette_pnm[0]; palette_pnm[0] = tmp; - + /* Make it transparent */ trans_pnm[0] = PGM_TRANSPARENT; *transSizeP = 1; @@ -1755,8 +1754,8 @@ makeOneColorTransparentInPalette(xel const transColor, static void -findOrAddBackgroundInPalette(pixel const backColor, - pixel palette_pnm[], +findOrAddBackgroundInPalette(pixel const backColor, + pixel palette_pnm[], unsigned int * const paletteSizeP, unsigned int * const backgroundIndexP) { /*---------------------------------------------------------------------------- @@ -1765,11 +1764,11 @@ findOrAddBackgroundInPalette(pixel const backColor, add it, choose a background color that's already in the palette, as close to 'backColor' as possible. - If we add an entry to the palette, make it opaque. But in searching the + If we add an entry to the palette, make it opaque. But in searching the existing palette, ignore transparency. Note that PNG specs say that transparency of the background is meaningless; - i.e. a viewer must ignore the transparency of the palette entry when + i.e. a viewer must ignore the transparency of the palette entry when using the background color. Return the palette index of the background color as *backgroundIndexP. @@ -1778,9 +1777,9 @@ findOrAddBackgroundInPalette(pixel const backColor, unsigned int paletteIndex; backgroundIndex = -1; - for (paletteIndex = 0; - paletteIndex < *paletteSizeP; - ++paletteIndex) + for (paletteIndex = 0; + paletteIndex < *paletteSizeP; + ++paletteIndex) if (PPM_EQUAL(palette_pnm[paletteIndex], backColor)) backgroundIndex = paletteIndex; @@ -1823,8 +1822,8 @@ findOrAddBackgroundInPalette(pixel const backColor, -static void -buildColorLookup(pixel palette_pnm[], +static void +buildColorLookup(pixel palette_pnm[], unsigned int const paletteSize, colorhash_table * const chtP) { /*---------------------------------------------------------------------------- @@ -1849,14 +1848,14 @@ buildColorLookup(pixel palette_pnm[], -static void -buildColorAlphaLookup(pixel palette_pnm[], +static void +buildColorAlphaLookup(pixel palettePnm[], unsigned int const paletteSize, - gray trans_pnm[], + gray transPnm[], unsigned int const transSize, gray const alphaMaxval, coloralphahash_table * const cahtP) { - + coloralphahash_table const caht = alloccoloralphahash(); unsigned int paletteIndex; @@ -1865,12 +1864,12 @@ buildColorAlphaLookup(pixel palette_pnm[], gray paletteTrans; if (paletteIndex < transSize) - paletteTrans = alphaMaxval; + paletteTrans = transPnm[paletteIndex]; else - paletteTrans = trans_pnm[paletteIndex]; + paletteTrans = alphaMaxval; - addtocoloralphahash(caht, &palette_pnm[paletteIndex], - &trans_pnm[paletteIndex], paletteIndex); + addtocoloralphahash(caht, &palettePnm[paletteIndex], + &paletteTrans, paletteIndex); } *cahtP = caht; } @@ -1905,18 +1904,18 @@ tryAlphaPalette(FILE * const ifP, "a PNG with transparency when you specify " "the palette with -palette."); - compute_alpha_palette(ifP, cols, rows, maxval, format, + compute_alpha_palette(ifP, cols, rows, maxval, format, rasterPos, alpha_mask, alphaMaxval, - palette_pnm, trans_pnm, + palette_pnm, trans_pnm, paletteSizeP, transSizeP, &tooBig); if (tooBig) { pm_asprintf(impossibleReasonP, "too many color/transparency pairs " - "(more than the PNG maximum of %u", + "(more than the PNG maximum of %u", MAXPALETTEENTRIES); } else *impossibleReasonP = NULL; -} +} @@ -1930,15 +1929,15 @@ computePixelWidth(bool const colorPng, unsigned int bitsPerSample, bitsPerPixel; if (colorPng || alpha) { - /* PNG allows only depths of 8 and 16 for a truecolor image + /* PNG allows only depths of 8 and 16 for a truecolor image and for a grayscale image with an alpha channel. */ if (pnmMeaningfulBitCt > 8) bitsPerSample = 16; - else + else bitsPerSample = 8; } else { - /* A grayscale, non-colormapped, no-alpha PNG may have any + /* A grayscale, non-colormapped, no-alpha PNG may have any bit depth from 1 to 16 */ if (pnmMeaningfulBitCt > 8) @@ -1977,7 +1976,7 @@ paletteIndexBits(unsigned int const nColors) { Return the number of bits that a palette index in the PNG will occupy given that the palette has 'nColors' colors in it. It is 1, 2, 4, or 8 bits. - + If 'nColors' is not a valid PNG palette size, return 0. -----------------------------------------------------------------------------*/ unsigned int retval; @@ -2056,7 +2055,7 @@ computeColorMap(FILE * const ifP, pm_asprintf(noColormapReasonP, "You requested no color map"); else if (maxval > PALETTEMAXVAL) pm_asprintf(noColormapReasonP, "The maxval of the input image (%u) " - "exceeds the PNG palette maxval (%u)", + "exceeds the PNG palette maxval (%u)", maxval, PALETTEMAXVAL); else { unsigned int bitsPerPixel; @@ -2076,20 +2075,20 @@ computeColorMap(FILE * const ifP, */ colorhist_vector chv; unsigned int colors; - - getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, + + getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, &chv, &colors); if (chv == NULL) { - pm_asprintf(noColormapReasonP, + pm_asprintf(noColormapReasonP, "More than %u colors found -- too many for a " "colormapped PNG", MAXCOLORS); } else { /* There are few enough colors that a palette is possible */ if (bitsPerPixel <= paletteIndexBits(colors) && !pfP) - pm_asprintf(noColormapReasonP, + pm_asprintf(noColormapReasonP, "palette index for %u colors would be " - "no smaller than the indexed value (%u bits)", + "no smaller than the indexed value (%u bits)", colors, bitsPerPixel); else { unsigned int paletteSize; @@ -2098,7 +2097,7 @@ computeColorMap(FILE * const ifP, tryAlphaPalette(ifP, cols, rows, maxval, format, rasterPos, alpha_mask, alphaMaxval, pfP, - palette_pnm, &paletteSize, + palette_pnm, &paletteSize, trans_pnm, &transSize, noColormapReasonP); @@ -2106,13 +2105,13 @@ computeColorMap(FILE * const ifP, *noColormapReasonP = NULL; compute_nonalpha_palette(chv, colors, maxval, pfP, - palette_pnm, &paletteSize, + palette_pnm, &paletteSize, trans_pnm, &transSize); - + if (transparent) makeOneColorTransparentInPalette( - transcolor, transexact, - palette_pnm, paletteSize, trans_pnm, + transcolor, transexact, + palette_pnm, paletteSize, trans_pnm, &transSize); } if (!*noColormapReasonP) { @@ -2145,7 +2144,7 @@ static void computeColorMapLookupTable( /*---------------------------------------------------------------------------- Compute applicable lookup tables for the palette index. If there's no alpha mask, this is just a standard Netpbm colorhash_table. If there's - an alpha mask, it is the slower Pnmtopng-specific + an alpha mask, it is the slower Pnmtopng-specific coloralphahash_table. If a lookup table is not applicable to the image, return NULL as @@ -2153,10 +2152,10 @@ static void computeColorMapLookupTable( -----------------------------------------------------------------------------*/ if (colorMapped) { if (alpha) { - buildColorAlphaLookup(palette_pnm, palette_size, + buildColorAlphaLookup(palette_pnm, palette_size, trans_pnm, trans_size, alpha_maxval, cahtP); *chtP = NULL; - } else { + } else { buildColorLookup(palette_pnm, palette_size, chtP); *cahtP = NULL; } @@ -2203,15 +2202,15 @@ computeRasterWidth(bool const colorMapped, bitsPerSampleP, bitsPerPixelP); if (verbose) - pm_message("Writing %u bits per component per pixel", + pm_message("Writing %u bits per component per pixel", *bitsPerSampleP); } } static void -createPngPalette(pixel palette_pnm[], - unsigned int const paletteSize, +createPngPalette(pixel palette_pnm[], + unsigned int const paletteSize, pixval const maxval, gray trans_pnm[], unsigned int const transSize, @@ -2269,7 +2268,7 @@ setZlibCompression(struct pngx * const pngxP, pngx_setCompressionSize(pngxP, zlibCompression.buffer_size); } } - + static void @@ -2284,7 +2283,7 @@ makePngLine(png_byte * const line, struct pngx * const pngxP, xelval const png_maxval, unsigned int const depth) { - + unsigned int col; png_byte *pp; @@ -2318,7 +2317,7 @@ makePngLine(png_byte * const line, *pp++ = PPM_GETB(p_png) & 0xff; } else pm_error("INTERNAL ERROR: undefined color_type"); - + if (pngx_colorType(pngxP) & PNG_COLOR_MASK_ALPHA) { int const png_alphaval = (int) alpha_mask[col] * (float) png_maxval / maxval + 0.5; @@ -2372,7 +2371,7 @@ writeRaster(struct pngx * const pngxP, pnm_readpnmrow(ifP, xelrow, cols, maxval, format); pnm_promoteformatrow(xelrow, cols, maxval, format, maxval, PPM_TYPE); - + makePngLine(line, xelrow, cols, maxval, alpha, alpha ? alpha_mask[row] : NULL, cht, caht, pngxP, png_maxval, depth); @@ -2401,15 +2400,15 @@ doHistChunk(struct pngx * const pngxP, colorhist_vector chv; unsigned int colorCt; colorhash_table cht; - - getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, + + getChv(ifP, rasterPos, cols, rows, maxval, format, MAXCOLORS, &chv, &colorCt); cht = ppm_colorhisttocolorhash(chv, colorCt); - - { + + { png_uint_16 * histogram; /* malloc'ed */ - + MALLOCARRAY(histogram, MAXCOLORS); if (!histogram) @@ -2424,7 +2423,7 @@ doHistChunk(struct pngx * const pngxP, else histogram[i] = chv[chvIndex].value; } - + pngx_setHist(pngxP, histogram); if (verbose) @@ -2471,7 +2470,7 @@ doIhdrChunk(struct pngx * const pngxP, static void doGamaChunk(struct cmdlineInfo const cmdline, struct pngx * const pngxP) { - + if (cmdline.gammaSpec) pngx_setGama(pngxP, cmdline.gamma); } @@ -2541,7 +2540,7 @@ reportTrans(struct pngx * const pngxP) { struct pngx_trns const transInfo = pngx_trns(pngxP); pm_message("%u transparency values", transInfo.numTrans); - + pm_message("Transparent color {gray, red, green, blue} = " "{%d, %d, %d, %d}", transInfo.transColor.gray, @@ -2594,21 +2593,21 @@ doBkgdChunk(struct pngx * const pngxP, xelval const maxval, xelval const pngMaxval, bool const verbose) { - + if (bkgdRequested) { if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_PALETTE) pngx_setBkgdPalette(pngxP, backgroundIndex); else { - png_color_16 const pngBackground = + png_color_16 const pngBackground = xelToPngColor_16(backColor, maxval, pngMaxval); pngx_setBkgdRgb(pngxP, pngBackground); if (verbose) pm_message("Writing bKGD chunk with background color " " {gray, red, green, blue} = {%d, %d, %d, %d}", - pngBackground.gray, - pngBackground.red, - pngBackground.green, - pngBackground.blue ); + pngBackground.gray, + pngBackground.red, + pngBackground.green, + pngBackground.blue ); } } } @@ -2625,20 +2624,19 @@ doSbitChunk(struct pngx * const pngxP, if (pngx_colorType(pngxP) != PNG_COLOR_TYPE_PALETTE && (pngMaxval > maxval || (alpha && pngMaxval > alphaMaxval))) { - /* We're writing in a bit depth that doesn't match the maxval - of the input image and the alpha mask. So we write an sBIT - chunk to tell what the original image's maxval was. The - sBit chunk doesn't let us specify any maxval -- only powers - of two minus one. So we pick the power of two minus one - which is greater than or equal to the actual input maxval. - - PNG also doesn't let an sBIT chunk indicate a maxval - _greater_ than the the PNG maxval. The designers probably - did not conceive of the case where that would happen. The - case is this: We detected redundancy in the bits so were - able to store fewer bits than the user provided. But since - PNG doesn't allow it, we don't attempt to create such an - sBIT chunk. + /* We're writing in a bit depth that doesn't match the maxval of the + input image and the alpha mask. So we write an sBIT chunk to tell + what the original image's maxval was. The sBit chunk doesn't let + us specify any maxval -- only powers of two minus one. So we pick + the power of two minus one which is greater than or equal to the + actual input maxval. + + PNG also doesn't let an sBIT chunk indicate a maxval _greater_ than + the PNG maxval. The designers probably did not conceive of the + case where that would happen. The case is this: We detected + redundancy in the bits so were able to store fewer bits than the + user provided. But since PNG doesn't allow it, we don't attempt to + create such an sBIT chunk. */ { @@ -2652,7 +2650,7 @@ doSbitChunk(struct pngx * const pngxP, sbit.blue = sbitval; } else sbit.gray = sbitval; - + if (verbose) pm_message("Writing sBIT chunk with bits = %d", sbitval); @@ -2683,7 +2681,7 @@ addSrgbChunk(struct pngx * const pngxP, -static void +static void convertpnm(struct cmdlineInfo const cmdline, FILE * const ifP, FILE * const ofP, @@ -2702,14 +2700,14 @@ convertpnm(struct cmdlineInfo const cmdline, xelval maxval; /* The maxval of the input image */ xelval pngMaxval; - /* The maxval of the samples in the PNG output + /* The maxval of the samples in the PNG output (must be 1, 3, 7, 15, 255, or 65535) */ pixel transcolor; /* The color that is to be transparent, with maxval equal to that of the input image. */ - bool transExact; + bool transExact; /* boolean: the user wants only the exact color he specified to be transparent; not just something close to it. */ @@ -2728,14 +2726,14 @@ convertpnm(struct cmdlineInfo const cmdline, pixel palettePnm[MAXCOLORS]; png_color palette[MAXCOLORS]; /* The color part of the color/alpha palette passed to the PNG - compressor + compressor */ unsigned int paletteSize; gray transPnm[MAXCOLORS]; png_byte trans[MAXCOLORS]; /* The alpha part of the color/alpha palette passed to the PNG - compressor + compressor */ unsigned int transSize; @@ -2751,7 +2749,7 @@ convertpnm(struct cmdlineInfo const cmdline, we should. malloc'ed null-terminated string. */ unsigned int depth; - /* The number of bits per sample in the (uncompressed) png + /* The number of bits per sample in the (uncompressed) png raster -- if the raster contains palette indices, this is the number of bits in the index. */ @@ -2759,7 +2757,7 @@ convertpnm(struct cmdlineInfo const cmdline, /* The total number of bits per pixel in the (uncompressed) png raster, including all channels. */ - pm_filepos rasterPos; + pm_filepos rasterPos; /* file position in input image file of start of image (i.e. after the header) */ @@ -2800,7 +2798,7 @@ convertpnm(struct cmdlineInfo const cmdline, colorPng = (PNM_FORMAT_TYPE(format) == PPM_TYPE); else { if (PNM_FORMAT_TYPE(format) == PPM_TYPE) { - colorPng = hasColor(ifP, cols, rows, maxval, format, rasterPos); + colorPng = hasColor(ifP, cols, rows, maxval, format, rasterPos); } else colorPng = false; } @@ -2815,10 +2813,10 @@ convertpnm(struct cmdlineInfo const cmdline, findRedundantBits(ifP, rasterPos, cols, rows, maxval, format, alpha, cmdline.force, &pnmMeaningfulBitCt); - + computeColorMap(ifP, rasterPos, cols, rows, maxval, colorPng, format, cmdline.force, pfP, - alpha, transparent >= 0, transcolor, transExact, + alpha, transparent >= 0, transcolor, transExact, !!cmdline.background, backColor, alpha_mask, alphaMaxval, pnmMeaningfulBitCt, palettePnm, &paletteSize, transPnm, &transSize, @@ -2835,7 +2833,7 @@ convertpnm(struct cmdlineInfo const cmdline, colorMapped = FALSE; } else colorMapped = TRUE; - + computeColorMapLookupTable(colorMapped, palettePnm, paletteSize, transPnm, transSize, alpha, alphaMaxval, &cht, &caht); @@ -2846,7 +2844,7 @@ convertpnm(struct cmdlineInfo const cmdline, if (verbose) pm_message ("writing a%s %d-bit %s%s file%s", fulldepth == 8 ? "n" : "", fulldepth, - colorMapped ? "palette": + colorMapped ? "palette": colorPng ? "RGB" : "gray", alpha ? (colorMapped ? "+transparency" : "+alpha") : "", cmdline.interlace ? " (interlaced)" : ""); @@ -2873,7 +2871,7 @@ convertpnm(struct cmdlineInfo const cmdline, /* creating PNG palette (Not counting the transparency palette) */ createPngPalette(palettePnm, paletteSize, maxval, - transPnm, transSize, alphaMaxval, + transPnm, transSize, alphaMaxval, palette, trans); pngx_setPlte(pngxP, palette, paletteSize); @@ -2973,7 +2971,7 @@ displayVersion() { -int +int main(int argc, const char * argv[]) { struct cmdlineInfo cmdline; @@ -2983,29 +2981,29 @@ main(int argc, const char * argv[]) { FILE * tfP; int errorlevel; - + pm_proginit(&argc, argv); - + parseCommandLine(argc, argv, &cmdline); - + if (cmdline.libversion) { displayVersion(); return 0; } verbose = cmdline.verbose; - + ifP = pm_openr_seekable(cmdline.inputFileName); - + if (cmdline.alpha) afP = pm_openr(cmdline.alpha); else afP = NULL; - + if (cmdline.palette) pfP = pm_openr(cmdline.palette); else pfP = NULL; - + if (cmdline.text) tfP = pm_openr(cmdline.text); else if (cmdline.ztxt) @@ -3014,7 +3012,7 @@ main(int argc, const char * argv[]) { tfP = NULL; convertpnm(cmdline, ifP, stdout, afP, pfP, tfP, &errorlevel); - + if (afP) pm_close(afP); if (pfP) diff --git a/converter/other/pnmtops.c b/converter/other/pnmtops.c index c1dadc3e..de0dfd8d 100644 --- a/converter/other/pnmtops.c +++ b/converter/other/pnmtops.c @@ -33,6 +33,7 @@ goes in separate from the rest of the raster. */ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _BSD_SOURCE /* Make sure string.h contains strdup() */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #include <stdlib.h> @@ -86,7 +87,7 @@ setSignals() { -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -208,7 +209,7 @@ validateCompDimension(unsigned int const value, static void parseCommandLine(int argc, const char ** argv, - struct cmdlineInfo * const cmdlineP) { + struct CmdlineInfo * const cmdlineP) { unsigned int imagewidthSpec, imageheightSpec; float imagewidth, imageheight; @@ -2034,7 +2035,7 @@ main(int argc, const char * argv[]) { FILE * ifP; const char * name; /* malloc'ed */ - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; pm_proginit(&argc, argv); diff --git a/converter/other/pnmtosir.c b/converter/other/pnmtosir.c index c8dec5b6..20bb6178 100644 --- a/converter/other/pnmtosir.c +++ b/converter/other/pnmtosir.c @@ -1,5 +1,5 @@ /* pnmtosir.c - read a portable anymap and produce a Solitaire Image Recorder -** file (MGI TYPE 11 or MGI TYPE 17) +** file (MGI TYPE 11 or MGI TYPE 17) ** ** Copyright (C) 1991 by Marvin Landis ** @@ -11,67 +11,63 @@ ** implied warranty. */ +#include <stdbool.h> #include "pnm.h" #define MAXCOLORS 256 -int main(int argc, char * argv[]) { - FILE* ifp; - xel** xels; - register xel* xP; - const char* dumpname; - int rows, cols, format, row, col; - int m, n; - int grayscale; + + +int +main(int argc, const char * argv[]) { + + FILE * ifP; + xel ** xels; + int rows, cols, format; + unsigned int n; + bool isGrayscale; xelval maxval; - const char* const usage = "[pnmfile]"; - unsigned char ub; unsigned short Header[16]; unsigned short LutHeader[16]; unsigned short Lut[2048]; - pnm_init( &argc, argv ); + pm_proginit(&argc, argv); - if ( argc > 2 ) - pm_usage( usage ); + if (argc-1 > 1) + pm_error("There is only one possible argument: the input file. " + "You specified %d", argc-1); - if ( argc == 2 ) - { - dumpname = argv[1]; - ifp = pm_openr( argv[1] ); - } - else - { - dumpname = "Standard Input"; - ifp = stdin; - } + if (argc-1 > 0) { + const char * const inputFileName = argv[1]; + ifP = pm_openr(inputFileName); + } else { + ifP = stdin; + } - xels = pnm_readpnm( ifp, &cols, &rows, &maxval, &format ); - pm_close( ifp ); + xels = pnm_readpnm(ifP, &cols, &rows, &maxval, &format); /* Figure out the colormap. */ - switch ( PNM_FORMAT_TYPE(format) ) - { - case PPM_TYPE: - grayscale = 0; - pm_message( "Writing a 24-bit SIR format (MGI TYPE 11)" ); + switch (PNM_FORMAT_TYPE(format) ) { + case PPM_TYPE: + isGrayscale = false; + pm_message("Writing a 24-bit SIR format (MGI TYPE 11)"); break; case PGM_TYPE: - grayscale = 1; - pm_message( "Writing a grayscale SIR format (MGI TYPE 17)" ); + isGrayscale = true; + pm_message("Writing a grayscale SIR format (MGI TYPE 17)"); break; - default: - grayscale = 1; - pm_message( "Writing a monochrome SIR format (MGI TYPE 17)" ); + default: + isGrayscale = true; + pm_message("Writing a monochrome SIR format (MGI TYPE 17)"); break; - } + } /* Set up the header. */ Header[0] = 0x3a4f; Header[1] = 0; - if (grayscale) + if (isGrayscale) Header[2] = 17; else Header[2] = 11; @@ -93,54 +89,65 @@ int main(int argc, char * argv[]) { LutHeader[2] = 5; LutHeader[3] = 256; LutHeader[4] = 256; - for (n = 0; n < 5; n++) + for (n = 0; n < 5; ++n) pm_writelittleshort(stdout,LutHeader[n]); - for (n = 5; n < 256; n++) + for (n = 5; n < 256; ++n) pm_writelittleshort(stdout,0); - for(n = 0; n < 3; n ++) - for (m = 0; m < 256; m++) + for (n = 0; n < 3; ++n) { + unsigned int m; + for (m = 0; m < 256; ++m) Lut[m * 4 + n] = m << 8; - for (n = 0; n < 1024; n++) + } + for (n = 0; n < 1024; ++n) pm_writelittleshort(stdout,Lut[n]); /* Finally, write out the data. */ - switch ( PNM_FORMAT_TYPE(format) ) - { - case PPM_TYPE: - for ( row = 0; row < rows; ++row ) - for ( col = 0, xP = xels[row]; col < cols; ++col, ++xP ) - { - ub = (char) ( PPM_GETR( *xP ) * ( 255 / maxval ) ); - fputc( ub, stdout ); + switch (PNM_FORMAT_TYPE(format)) { + case PPM_TYPE: { + unsigned int row; + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + unsigned char const ub = + (char) (PPM_GETR(xels[row][col]) * (255 / maxval)); + fputc(ub, stdout); } - for ( row = 0; row < rows; ++row ) - for ( col = 0, xP = xels[row]; col < cols; ++col, ++xP ) - { - ub = (char) ( PPM_GETG( *xP ) * ( 255 / maxval ) ); - fputc( ub, stdout ); + } + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + unsigned const char ub = + (char) (PPM_GETG(xels[row][col]) * (255 / maxval)); + fputc(ub, stdout); } - for ( row = 0; row < rows; ++row ) - for ( col = 0, xP = xels[row]; col < cols; ++col, ++xP ) - { - ub = (char) ( PPM_GETB( *xP ) * ( 255 / maxval ) ); - fputc( ub, stdout ); + } + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + unsigned const char ub = + (char) (PPM_GETB(xels[row][col]) * (255 / maxval)); + fputc(ub, stdout); } - break; + } + } break; - default: - for ( row = 0; row < rows; ++row ) - for ( col = 0, xP = xels[row]; col < cols; ++col, ++xP ) - { - register unsigned long val; - - val = PNM_GET1( *xP ); - ub = (char) ( val * ( 255 / maxval ) ); - fputc( ub, stdout ); + default: { + unsigned int row; + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + unsigned long const val = PNM_GET1(xels[row][col]); + unsigned const char ub = (char) (val * (255 / maxval)); + fputc(ub, stdout); } - break; + } + } break; } + + pm_close(ifP); - exit( 0 ); + return 0; } + diff --git a/converter/other/pstopnm.c b/converter/other/pstopnm.c index 19b1630a..f5342655 100644 --- a/converter/other/pstopnm.c +++ b/converter/other/pstopnm.c @@ -14,8 +14,9 @@ -----------------------------------------------------------------------------*/ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 500 /* Make sure fdopen() is in stdio.h and strdup() is in string.h */ #include <assert.h> @@ -24,7 +25,7 @@ #include <stdlib.h> #include <stdio.h> #include <signal.h> -#include <sys/wait.h> +#include <sys/wait.h> #include <sys/stat.h> #include "pm_c_util.h" @@ -37,17 +38,32 @@ static bool verbose; enum Orientation {PORTRAIT, LANDSCAPE, UNSPECIFIED}; struct Box { - /* Description of a rectangle within an image; all coordinates - measured in points (1/72") with lower left corner of page being the - origin. + /* Description of a rectangle within an image; all coordinates + measured in points (1/72") with lower left corner of page being the + origin. Negative values are OK. */ + bool isDefined; + + /* Nothing below is meaningful unless 'isDefined' is true */ int llx; /* lower left X coord */ - /* -1 for llx means whole box is undefined. */ int lly; /* lower left Y coord */ int urx; /* upper right X coord */ int ury; /* upper right Y coord */ }; + + +static void +assertValidBox(struct Box const box) { + + if (box.isDefined) { + assert(box.urx >= box.llx); + assert(box.ury >= box.lly); + } +} + + + struct Dimensions { /*---------------------------------------------------------------------------- Horizontal and vertical dimensions of something, both in pixels and @@ -106,7 +122,7 @@ parseCommandLine(int argc, char ** argv, unsigned int textalphabitsSpec; MALLOCARRAY_NOFAIL(option_def, 100); - + option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "forceplain", OPT_FLAG, NULL, &cmdlineP->forceplain, 0); OPTENT3(0, "llx", OPT_FLOAT, &llx, &llxSpec, 0); @@ -150,7 +166,7 @@ parseCommandLine(int argc, char ** argv, if (ymaxSpec) { if (cmdlineP->ymax == 0) pm_error("zero is not a valid value for -ymax"); - } else + } else cmdlineP->ymax = 792; if (xsizeSpec) { @@ -162,7 +178,7 @@ parseCommandLine(int argc, char ** argv, if (ysizeSpec) { if (cmdlineP->ysize == 0) pm_error("zero is not a valid value for -ysize"); - } else + } else cmdlineP->ysize = 0; if (portraitOpt && !landscapeOpt) @@ -184,9 +200,11 @@ parseCommandLine(int argc, char ** argv, cmdlineP->formatType = PPM_TYPE; /* If any one of the 4 bounding box coordinates is given on the - command line, we default any of the 4 that aren't. + command line, we default any of the 4 that aren't. */ if (llxSpec || llySpec || urxSpec || urySpec) { + cmdlineP->extractBox.isDefined = true; + if (!llxSpec) cmdlineP->extractBox.llx = 72; else cmdlineP->extractBox.llx = llx * 72; if (!llySpec) cmdlineP->extractBox.lly = 72; @@ -196,7 +214,7 @@ parseCommandLine(int argc, char ** argv, if (!urySpec) cmdlineP->extractBox.ury = 720; else cmdlineP->extractBox.ury = ury * 72; } else { - cmdlineP->extractBox.llx = -1; + cmdlineP->extractBox.isDefined = false; } if (dpiSpec) { @@ -224,7 +242,7 @@ parseCommandLine(int argc, char ** argv, cmdlineP->inputFileName = "-"; /* stdin */ else if (argc-1 == 1) cmdlineP->inputFileName = argv[1]; - else + else pm_error("Too many arguments (%d). " "Only need one: the Postscript file name", argc-1); @@ -248,7 +266,7 @@ addPsToFileName(char const origFileName[], int statRc; statRc = lstat(origFileName, &statbuf); - + if (statRc == 0) *newFileNameP = strdup(origFileName); else { @@ -269,34 +287,62 @@ addPsToFileName(char const origFileName[], +static unsigned int +resolution(unsigned int const dotCt, + unsigned int const pointCt) { +/*---------------------------------------------------------------------------- + The resolution in dots per inch when 'dotCt' dots print 'pointCt' points + long. + + When this would round to zero, we return 1 dot per inch instead so it + doesn't play havoc with arithmetic - it's never going to happen unless + something is broken anyway. +-----------------------------------------------------------------------------*/ + return MAX(1, (unsigned int)((float)dotCt * 72 / pointCt + 0.5)); +} + + + static void computeSizeResFromSizeSpec(unsigned int const requestedXsize, unsigned int const requestedYsize, unsigned int const imageWidth, unsigned int const imageHeight, struct Dimensions * const imageDimP) { +/*---------------------------------------------------------------------------- + Compute output image size and assumed Postscript input resolution, assuming + user requested a specific size for at least one of the dimensions and the + input is 'imageWidth' x 'imageHeight' points. + + 'requestedXsize' is what the user requested for output image width in + pixels, or zero if he made no request. 'requestedYsize' is analogous + for the height. +-----------------------------------------------------------------------------*/ + assert(requestedXsize || requestedYsize); + + assert(imageWidth > 0); if (requestedXsize) { imageDimP->xsize = requestedXsize; - imageDimP->xres = (unsigned int) - (requestedXsize * 72 / imageWidth + 0.5); + imageDimP->xres = resolution(requestedXsize, imageWidth); if (!requestedYsize) { imageDimP->yres = imageDimP->xres; imageDimP->ysize = (unsigned int) (imageHeight * (float)imageDimP->yres/72 + 0.5); - } } + } + + assert(imageHeight > 0); if (requestedYsize) { imageDimP->ysize = requestedYsize; - imageDimP->yres = (unsigned int) - (requestedYsize * 72 / imageHeight + 0.5); + imageDimP->yres = resolution(requestedYsize, imageHeight); if (!requestedXsize) { imageDimP->xres = imageDimP->yres; imageDimP->xsize = (unsigned int) (imageWidth * (float)imageDimP->xres/72 + 0.5); } - } + } } @@ -312,8 +358,9 @@ computeSizeResBlind(unsigned int const xmax, if (imageWidth == 0 || imageHeight == 0) { imageDimP->xres = imageDimP->yres = 72; } else { - imageDimP->xres = imageDimP->yres = MIN(xmax * 72 / imageWidth, - ymax * 72 / imageHeight); + imageDimP->xres = imageDimP->yres = + MIN(resolution(xmax, imageWidth), + resolution(ymax, imageHeight)); } if (nocrop) { @@ -330,17 +377,17 @@ computeSizeResBlind(unsigned int const xmax, static void -computeSizeRes(struct CmdlineInfo const cmdline, +computeSizeRes(struct CmdlineInfo const cmdline, struct Box const borderedBox, struct Dimensions * const imageDimP) { /*---------------------------------------------------------------------------- Figure out how big the output image should be and what output device resolution Ghostscript should assume (return as *imageDimP). - A resolution number is the number of pixels per inch that the a + A resolution number is the number of pixels per inch that the printer prints. Since we're emulating a printed page with a PNM image, and a PNM image has no spatial dimension (you can't say how - many inches wide a PNM image is), it's kind of confusing. + many inches wide a PNM image is), it's kind of confusing. If the user doesn't select a resolution, we choose the resolution that causes the image to be a certain number of pixels, knowing how @@ -349,8 +396,8 @@ computeSizeRes(struct CmdlineInfo const cmdline, inches wide. We want the PNM image to be 1000 pixels wide. So we tell Ghostscript that our horizontal output device resolution is 500 pixels per inch. - - X and Y in all returned values is with respect to the image, not the + + X and Y in all returned values are with respect to the image, not the page. Note that the image might be placed sideways on the page, so that page X and Y would be reversed from image X and Y. -----------------------------------------------------------------------------*/ @@ -360,6 +407,8 @@ computeSizeRes(struct CmdlineInfo const cmdline, unsigned int const sx = borderedBox.urx - borderedBox.llx; unsigned int const sy = borderedBox.ury - borderedBox.lly; + assertValidBox(borderedBox); assert(borderedBox.isDefined); + if (cmdline.dpi) { /* User gave resolution; we figure out output image size */ imageDimP->xres = imageDimP->yres = cmdline.dpi; @@ -369,6 +418,7 @@ computeSizeRes(struct CmdlineInfo const cmdline, if (sx == 0 || sy == 0) pm_error("Input image is zero size; we cannot satisfy your " "produce your requested output dimensions"); + computeSizeResFromSizeSpec(cmdline.xsize, cmdline.ysize, sx, sy, imageDimP); } else @@ -397,7 +447,7 @@ languageDeclaration(char const inputFileName[]) { enum PostscriptLanguage language; if (streq(inputFileName, "-")) - /* Can't read stdin, because we need it to remain positioned for the + /* Can't read stdin, because we need it to remain positioned for the Ghostscript interpreter to read it. */ language = COMMON_POSTSCRIPT; @@ -430,12 +480,57 @@ languageDeclaration(char const inputFileName[]) { static struct Box +boundingBoxFmPostscriptFile(FILE * const ifP) { + + struct Box retval; + bool eof; + + for (retval.isDefined = false, eof = false; !retval.isDefined && !eof; ) { + char line[200]; + char * fgetsRc; + + fgetsRc = fgets(line, sizeof(line), ifP); + + if (fgetsRc == NULL) + eof = true; + else { + int rc; + int llx, lly, urx, ury; + + rc = sscanf(line, "%%%%BoundingBox: %d %d %d %d", + &llx, &lly, &urx, &ury); + if (rc == 4) { + /* We found a BoundingBox statement */ + + if (llx > urx) + pm_error("%%%%BoundingBox statement in input file has " + "lower left corner to the right of the " + "upper right corner"); + if (lly > ury) + pm_error("%%%%BoundingBox statement in input file has " + "lower left corner above the " + "upper right corner"); + + retval.llx = llx; retval.lly = lly; + retval.urx = urx; retval.ury = ury; + retval.isDefined = true; + } + } + } + fclose(ifP); + + return retval; +} + + + +static struct Box computeBoxToExtract(struct Box const cmdlineExtractBox, char const inputFileName[]) { struct Box retval; - if (cmdlineExtractBox.llx != -1) + if (cmdlineExtractBox.isDefined) /* User told us what box to extract, so that's what we'll do */ retval = cmdlineExtractBox; else { @@ -446,54 +541,37 @@ computeBoxToExtract(struct Box const cmdlineExtractBox, if (streq(inputFileName, "-")) /* Can't read stdin, because we need it to remain - positioned for the Ghostscript interpreter to read it. + positioned for the Ghostscript interpreter to read it. */ - psBb.llx = -1; + psBb.isDefined = false; else { FILE * ifP; - bool foundBb; - bool eof; ifP = pm_openr(inputFileName); - - for (foundBb = FALSE, eof = FALSE; !foundBb && !eof; ) { - char line[200]; - char * fgetsRc; - - fgetsRc = fgets(line, sizeof(line), ifP); - - if (fgetsRc == NULL) - eof = TRUE; - else { - int rc; - rc = sscanf(line, "%%%%BoundingBox: %d %d %d %d", - &psBb.llx, &psBb.lly, - &psBb.urx, &psBb.ury); - if (rc == 4) - foundBb = TRUE; - } - } - fclose(ifP); - if (!foundBb) { - psBb.llx = -1; + psBb = boundingBoxFmPostscriptFile(ifP); + + if (!psBb.isDefined) pm_message("Warning: no %%%%BoundingBox statement " "in the input or command line. " "Will use defaults"); - } } - if (psBb.llx != -1) { + if (psBb.isDefined) { if (verbose) pm_message("Using %%%%BoundingBox statement from input."); retval = psBb; - } else { + } else { /* Use the center of an 8.5" x 11" page with 1" border all around*/ + retval.isDefined = true; retval.llx = 72; retval.lly = 72; retval.urx = 540; retval.ury = 720; } } + + assert(retval.isDefined); + if (verbose) pm_message("Extracting the box ((%d,%d),(%d,%d))", retval.llx, retval.lly, retval.urx, retval.ury); @@ -503,7 +581,7 @@ computeBoxToExtract(struct Box const cmdlineExtractBox, static enum Orientation -computeOrientation(struct CmdlineInfo const cmdline, +computeOrientation(struct CmdlineInfo const cmdline, struct Box const extractBox) { /*---------------------------------------------------------------------------- The proper orientation of the image on the page, given the user's @@ -531,7 +609,7 @@ computeOrientation(struct CmdlineInfo const cmdline, /* Dimensions of image to print, in points */ unsigned int const imageWidPt = extractBox.urx - extractBox.llx; unsigned int const imageHgtPt = extractBox.ury - extractBox.lly; - + /* Dimensions of image to print, in pixels (possibly of assumed resolution) */ @@ -579,31 +657,30 @@ computeOrientation(struct CmdlineInfo const cmdline, static struct Box -addBorders(struct Box const inputBox, +addBorders(struct Box const inputBox, float const xborderScale, float const yborderScale) { /*---------------------------------------------------------------------------- Return a box which is 'inputBox' plus some borders. Add left and right borders that are the fraction 'xborderScale' of the - width of the input box; likewise for top and bottom borders with + width of the input box; likewise for top and bottom borders with 'yborderScale'. -----------------------------------------------------------------------------*/ - unsigned int const leftRightBorderSize = + unsigned int const leftRightBorderSize = ROUNDU((inputBox.urx - inputBox.llx) * xborderScale); - unsigned int const topBottomBorderSize = + unsigned int const topBottomBorderSize = ROUNDU((inputBox.ury - inputBox.lly) * yborderScale); struct Box retval; - - assert(inputBox.urx >= inputBox.llx); - assert(inputBox.ury >= inputBox.lly); + assertValidBox(inputBox); assert(inputBox.isDefined); retval.llx = inputBox.llx - (int)leftRightBorderSize; retval.lly = inputBox.lly - (int)topBottomBorderSize; retval.urx = inputBox.urx + (int)leftRightBorderSize; retval.ury = inputBox.ury + (int)topBottomBorderSize; + retval.isDefined = true; if (verbose) pm_message("With borders, extracted box is ((%d,%d),(%d,%d))", @@ -627,6 +704,8 @@ writePstrans(struct Box const box, const char * pstrans; + assert(xres > 0); assert(yres > 0); + switch (orientation) { case PORTRAIT: { int llx, lly; @@ -647,7 +726,7 @@ writePstrans(struct Box const box, if (pstrans == pm_strsol) pm_error("Unable to allocate memory for pstrans"); - if (verbose) + if (verbose) pm_message("Postscript prefix command: '%s'", pstrans); fprintf(pipeToGsP, "%s\n", pstrans); @@ -678,10 +757,10 @@ computeOutfileArg(struct CmdlineInfo const cmdline) { else { char * basename; const char * suffix; - + basename = strdup(cmdline.inputFileName); - if (strlen(basename) > 3 && - streq(basename+strlen(basename)-3, ".ps")) + if (strlen(basename) > 3 && + streq(basename+strlen(basename)-3, ".ps")) /* The input file name ends in ".ps". Chop it off. */ basename[strlen(basename)-3] = '\0'; @@ -729,7 +808,7 @@ computeGsDevice(int const formatType, static void findGhostscriptProg(const char ** const retvalP) { - + *retvalP = NULL; /* initial assumption */ if (getenv("GHOSTSCRIPT")) *retvalP = strdup(getenv("GHOSTSCRIPT")); @@ -739,7 +818,7 @@ findGhostscriptProg(const char ** const retvalP) { const char * candidate; pathwork = strdup(getenv("PATH")); - + candidate = strtok(pathwork, ":"); *retvalP = NULL; @@ -773,7 +852,7 @@ findGhostscriptProg(const char ** const retvalP) { static void execGhostscript(int const inputPipeFd, char const ghostscriptDevice[], - char const outfileArg[], + char const outfileArg[], struct Dimensions const pageDim, unsigned int const textalphabits) { /*---------------------------------------------------------------------------- @@ -791,12 +870,11 @@ execGhostscript(int const inputPipeFd, const char * gopt; const char * ropt; const char * textalphabitsopt; - int rc; findGhostscriptProg(&ghostscriptProg); /* Put the input pipe on Standard Input */ - rc = dup2(inputPipeFd, STDIN_FILENO); + dup2(inputPipeFd, STDIN_FILENO); close(inputPipeFd); pm_asprintf(&arg0, "gs"); @@ -817,13 +895,13 @@ execGhostscript(int const inputPipeFd, "'%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'", ghostscriptProg, arg0, deviceopt, outfileopt, gopt, ropt, textalphabitsopt, - "-q", "-dNOPAUSE", + "-q", "-dNOPAUSE", "-dSAFER", "-"); } execl(ghostscriptProg, arg0, deviceopt, outfileopt, gopt, ropt, textalphabitsopt, "-q", "-dNOPAUSE", "-dSAFER", "-", NULL); - + pm_error("execl() of Ghostscript ('%s') failed, errno=%d (%s)", ghostscriptProg, errno, strerror(errno)); } @@ -852,26 +930,26 @@ feedPsToGhostScript(const char * const inputFileName, bool eof; /* End of file on input */ pipeToGsP = fdopen(pipeToGhostscriptFd, "w"); - if (pipeToGsP == NULL) + if (pipeToGsP == NULL) pm_error("Unable to open stream on pipe to Ghostscript process."); - + ifP = pm_openr(inputFileName); /* In encapsulated Postscript, we the encapsulator are supposed to handle showing the page (which we do by passing a showpage - statement to Ghostscript). Any showpage statement in the + statement to Ghostscript). Any showpage statement in the input must be defined to have no effect. - + See "Enscapsulated PostScript Format File Specification", v. 3.0, 1 May 1992, in particular Example 2, p. 21. I found - it at + it at http://partners.adobe.com/asn/developer/pdfs/tn/5002.EPSF_Spec.pdf The example given is a much fancier solution than we need - here, I think, so I boiled it down a bit. JM + here, I think, so I boiled it down a bit. JM */ if (language == ENCAPSULATED_POSTSCRIPT) fprintf(pipeToGsP, "\n/b4_Inc_state save def /showpage { } def\n"); - + writePstrans(borderedBox, imageDim, orientation, pipeToGsP); /* If our child dies, it closes the pipe and when we next write to it, @@ -884,11 +962,11 @@ feedPsToGhostScript(const char * const inputFileName, while (!eof) { char buffer[4096]; size_t readCt; - + readCt = fread(buffer, 1, sizeof(buffer), ifP); - if (readCt == 0) + if (readCt == 0) eof = TRUE; - else + else fwrite(buffer, 1, readCt, pipeToGsP); } pm_close(ifP); @@ -897,7 +975,7 @@ feedPsToGhostScript(const char * const inputFileName, fprintf(pipeToGsP, "\nb4_Inc_state restore showpage\n"); fclose(pipeToGsP); -} +} @@ -940,7 +1018,7 @@ executeGhostscript(char const inputFileName[], struct Dimensions const imageDim, enum Orientation const orientation, char const ghostscriptDevice[], - char const outfileArg[], + char const outfileArg[], unsigned int const textalphabits, enum PostscriptLanguage const language) { @@ -949,12 +1027,12 @@ executeGhostscript(char const inputFileName[], if (strlen(outfileArg) > 80) pm_error("output file spec too long."); - + rc = pm_pipe(pipefd); if (rc < 0) pm_error("Unable to create pipe to talk to Ghostscript process. " "errno = %d (%s)", errno, strerror(errno)); - + rc = fork(); if (rc < 0) pm_error("Unable to fork a Ghostscript process. errno=%d (%s)", @@ -986,13 +1064,13 @@ executeGhostscript(char const inputFileName[], if (gsTermStatus != 0) { if (WIFEXITED(gsTermStatus)) - pm_error("Ghostscript failed. Exit code=%d\n", + pm_error("Ghostscript failed. Exit code=%d\n", WEXITSTATUS(gsTermStatus)); else if (WIFSIGNALED(gsTermStatus)) pm_error("Ghostscript process died because of a signal %d.", WTERMSIG(gsTermStatus)); - else - pm_error("Ghostscript process died with exit code %d", + else + pm_error("Ghostscript process died with exit code %d", gsTermStatus); } } @@ -1010,7 +1088,7 @@ main(int argc, char ** argv) { /* Size and resolution of the input image */ struct Box extractBox; /* coordinates of the box within the input we are to extract; i.e. - that will become the output. + that will become the output. */ struct Box borderedBox; /* Same as above, but expanded to include borders */ @@ -1031,32 +1109,31 @@ main(int argc, char ** argv) { extractBox = computeBoxToExtract(cmdline.extractBox, inputFileName); language = languageDeclaration(inputFileName); - + orientation = computeOrientation(cmdline, extractBox); borderedBox = addBorders(extractBox, cmdline.xborder, cmdline.yborder); + assertValidBox(borderedBox); assert(borderedBox.isDefined); + computeSizeRes(cmdline, borderedBox, &imageDim); - if (imageDim.xres == 0) - imageDim.xres = 1; - if (imageDim.yres == 0) - imageDim.yres = 1; - + assert(imageDim.xres > 0); assert(imageDim.yres > 0); + outfileArg = computeOutfileArg(cmdline); - ghostscriptDevice = + ghostscriptDevice = computeGsDevice(cmdline.formatType, cmdline.forceplain); - + pm_message("Writing %s format", ghostscriptDevice); - + executeGhostscript(inputFileName, borderedBox, imageDim, orientation, ghostscriptDevice, outfileArg, cmdline.textalphabits, language); pm_strfree(ghostscriptDevice); pm_strfree(outfileArg); - + return 0; } diff --git a/converter/other/rletopnm.c b/converter/other/rletopnm.c index 99959141..018456c8 100644 --- a/converter/other/rletopnm.c +++ b/converter/other/rletopnm.c @@ -35,6 +35,7 @@ * */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ @@ -264,7 +265,8 @@ writePpmRaster(FILE * const imageoutFileP, pixel *pixelrow; gray *alpharow; - int scan, x, y; + int scan; + int x; /* * Allocate some stuff. */ @@ -280,9 +282,9 @@ writePpmRaster(FILE * const imageoutFileP, /* * Loop through those scan lines. */ - for (scan = 0; scan < height; scan++) - y = rle_getrow(&hdr, scanlines[height - scan - 1]); - for (scan = 0; scan < height; scan++) { + for (scan = 0; scan < height; ++scan) + rle_getrow(&hdr, scanlines[height - scan - 1]); + for (scan = 0; scan < height; ++scan) { scanline = scanlines[scan]; switch (visual) { case GRAYSCALE: /* 8 bits without colormap */ @@ -366,7 +368,6 @@ writePgmRaster(FILE * const imageoutFileP, gray * pixelrow; gray * alpharow; int scan; - int y; /* * Allocate some stuff. */ @@ -383,7 +384,7 @@ writePgmRaster(FILE * const imageoutFileP, * Loop through those scan lines. */ for (scan = 0; scan < height; ++scan) - y = rle_getrow(&hdr, scanlines[height - scan - 1]); + rle_getrow(&hdr, scanlines[height - scan - 1]); for (scan = 0; scan < height; ++scan) { int x; diff --git a/converter/other/svgtopam.c b/converter/other/svgtopam.c index 58e7928f..ca6f4dc7 100644 --- a/converter/other/svgtopam.c +++ b/converter/other/svgtopam.c @@ -26,6 +26,7 @@ ============================================================================*/ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _BSD_SOURCE /* Make sure strdup() is in <string.h> */ #define _POSIX_SOURCE /* Make sure fileno() is in <stdio.h> */ @@ -146,36 +147,36 @@ typedef struct { unsigned int height; pixel ** pixels; pixval maxval; -} canvas; +} Canvas; typedef struct { pixel fillColor; -} style; +} Style; typedef struct { const char * pathText; /* This is e.g. "M0 0 L1 1 L9 8 Z" */ - style style; + Style style; /* This is the style as given by a 'style' attribute of <path> */ unsigned int pathTextLength; /* This is the length in characters of 'pathText'. It's redundant with 'pathText' and exists for convenience. */ -} path; +} Path; static void createPath(const char * const pathText, - style const style, - path ** const pathPP) { + Style const style, + Path ** const pathPP) { /*---------------------------------------------------------------------------- Create a path as described by a <path> element whose "style" attribute indicates style 'style' and whose "d" attribute indicates path data 'pathText'. -----------------------------------------------------------------------------*/ bool error; - path * pathP; + Path * pathP; MALLOCVAR(pathP); if (pathP == NULL) @@ -203,7 +204,7 @@ createPath(const char * const pathText, static void -destroyPath(path * const pathP) { +destroyPath(Path * const pathP) { assert(pathP->pathTextLength == strlen(pathP->pathText)); @@ -217,13 +218,13 @@ destroyPath(path * const pathP) { typedef struct { unsigned int x; unsigned int y; -} point; +} Point; -static point +static Point makePoint(unsigned int const x, unsigned int const y) { - point p; + Point p; p.x = x; p.y = y; @@ -232,7 +233,7 @@ makePoint(unsigned int const x, } static ppmd_point -makePpmdPoint(point const arg) { +makePpmdPoint(Point const arg) { ppmd_point p; @@ -247,16 +248,16 @@ typedef enum { PATH_LINETO, PATH_CLOSEPATH, PATH_CUBIC -} pathCommandVerb; +} PathCommandVerb; typedef struct { - point dest; -} pathMovetoArgs; + Point dest; +} PathMovetoArgs; typedef struct { /* Draw a line segment from current point to 'dest' */ - point dest; -} pathLinetoArgs; + Point dest; +} PathLinetoArgs; typedef struct { /* Draw a cubic spline from current point to 'dest' with control points @@ -271,19 +272,19 @@ typedef struct { A cubic curve is a plot of a polynomial equation of degree 3 (or less, for our purposes). */ - point dest; - point ctl1; - point ctl2; -} pathCubicArgs; + Point dest; + Point ctl1; + Point ctl2; +} PathCubicArgs; typedef struct { - pathCommandVerb verb; + PathCommandVerb verb; union { - pathMovetoArgs moveto; - pathLinetoArgs lineto; - pathCubicArgs cubic; + PathMovetoArgs moveto; + PathLinetoArgs lineto; + PathCubicArgs cubic; } args; -} pathCommand; +} PathCommand; @@ -291,15 +292,15 @@ typedef struct { /*---------------------------------------------------------------------------- This is an object for reading through a path from beginning to end. -----------------------------------------------------------------------------*/ - path * pathP; + Path * pathP; unsigned int cursor; -} pathReader; +} PathReader; static void -createPathReader(path * const pathP, - pathReader ** const pathReaderPP) { +pathReader_create(Path * const pathP, + PathReader ** const pathReaderPP) { - pathReader * pathReaderP; + PathReader * pathReaderP; MALLOCVAR_NOFAIL(pathReaderP); @@ -310,18 +311,31 @@ createPathReader(path * const pathP, } static void -destroyPathReader(pathReader * const pathReaderP) { +pathReader_destroy(PathReader * const pathReaderP) { free(pathReaderP); } +static const char * +pathReader_context(PathReader * const pathReaderP) { + + const char * retval; + + pm_asprintf(&retval, "Character position %u (starting at 0) in '%s'", + pathReaderP->cursor, pathReaderP->pathP->pathText); + + return retval; +} + + + static void -skipWhiteSpace(pathReader * const pathReaderP) { +pathReader_skipWhiteSpace(PathReader * const pathReaderP) { /*---------------------------------------------------------------------------- Move the cursor over any white space where it now points. -----------------------------------------------------------------------------*/ - const path * const pathP = pathReaderP->pathP; + const Path * const pathP = pathReaderP->pathP; while (isspace(pathP->pathText[pathReaderP->cursor]) && pathReaderP->cursor < pathP->pathTextLength) @@ -331,10 +345,10 @@ skipWhiteSpace(pathReader * const pathReaderP) { static void -getNumber(pathReader * const pathReaderP, - unsigned int * const numberP) { +pathReader_getNumber(PathReader * const pathReaderP, + unsigned int * const numberP) { - const path * const pathP = pathReaderP->pathP; + const Path * const pathP = pathReaderP->pathP; const char * const pathText = pathP->pathText; size_t const pathTextLength = pathP->pathTextLength; @@ -342,7 +356,10 @@ getNumber(pathReader * const pathReaderP, if (pathReaderP->cursor >= pathTextLength) pm_error("Path description ends where a number was expected."); - else { + else if (!isdigit(pathText[pathReaderP->cursor])) { + pm_error("Character '%c' instead of a digit where number expected", + pathText[pathReaderP->cursor]); + } else { unsigned int number; number = 0; /* initial value */ @@ -352,6 +369,10 @@ getNumber(pathReader * const pathReaderP, number = 10 * number + (pathText[pathReaderP->cursor] - '0'); ++pathReaderP->cursor; } + if (pathText[pathReaderP->cursor] == '.') + pm_error("Number contains decimal point. This program does not " + "know how to deal with fractional positions"); + *numberP = number; } } @@ -359,15 +380,15 @@ getNumber(pathReader * const pathReaderP, static void -getNextCommand(pathReader * const pathReaderP, - pathCommand * const pathCommandP, - bool * const endOfPathP) { +pathReader_getNextCommand(PathReader * const pathReaderP, + PathCommand * const pathCommandP, + bool * const endOfPathP) { - const path * const pathP = pathReaderP->pathP; + const Path * const pathP = pathReaderP->pathP; const char * const pathText = pathP->pathText; size_t const pathTextLength = pathP->pathTextLength; - skipWhiteSpace(pathReaderP); + pathReader_skipWhiteSpace(pathReaderP); if (pathReaderP->cursor >= pathTextLength) *endOfPathP = true; @@ -375,67 +396,79 @@ getNextCommand(pathReader * const pathReaderP, switch (pathText[pathReaderP->cursor++]) { case 'M': pathCommandP->verb = PATH_MOVETO; - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.moveto.dest.x); - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.moveto.dest.y); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, + &pathCommandP->args.moveto.dest.x); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, + &pathCommandP->args.moveto.dest.y); break; case 'L': pathCommandP->verb = PATH_LINETO; - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.lineto.dest.x); - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.lineto.dest.y); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, + &pathCommandP->args.lineto.dest.x); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, + &pathCommandP->args.lineto.dest.y); break; case 'C': pathCommandP->verb = PATH_CUBIC; - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.cubic.ctl1.x); - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.cubic.ctl1.y); - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.cubic.ctl2.x); - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.cubic.ctl2.y); - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.cubic.dest.x); - skipWhiteSpace(pathReaderP); - getNumber(pathReaderP, &pathCommandP->args.cubic.dest.y); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.ctl1.x); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.ctl1.y); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.ctl2.x); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.ctl2.y); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.dest.x); + pathReader_skipWhiteSpace(pathReaderP); + pathReader_getNumber(pathReaderP, &pathCommandP->args.cubic.dest.y); break; case 'z': pathCommandP->verb = PATH_CLOSEPATH; break; - default: - pm_error("Unrecognized command in <path>: '%c'", - pathText[pathReaderP->cursor++]); + default: { + const char * const context = pathReader_context(pathReaderP); + + pm_errormsg("Unrecognized command in <path>: '%c'. %s", + pathText[pathReaderP->cursor++], context); + + pm_strfree(context); + + pm_longjmp(); + } } } } + static void -outlineObject(path * const pathP, +outlineObject(Path * const pathP, struct fillobj * const fillObjP) { /*---------------------------------------------------------------------------- Create a fill object, which contains and outline of the object and can be used with ppmd_fill() to fill the figure. The outline is as described by *pathP. -----------------------------------------------------------------------------*/ - pathReader * pathReaderP; + PathReader * pathReaderP; bool endOfPath; - point currentPos; - point subpathStart; + Point currentPos; + Point subpathStart; /* Point at which the current subpath starts */ endOfPath = false; subpathStart = makePoint(0,0); currentPos = subpathStart; - createPathReader(pathP, &pathReaderP); + pathReader_create(pathP, &pathReaderP); while (!endOfPath) { - pathCommand pathCommand; - getNextCommand(pathReaderP, &pathCommand, &endOfPath); + PathCommand pathCommand; + pathReader_getNextCommand(pathReaderP, &pathCommand, &endOfPath); if (!endOfPath) { switch (pathCommand.verb) { case PATH_MOVETO: @@ -447,7 +480,7 @@ outlineObject(path * const pathP, currentPos = subpathStart; break; case PATH_LINETO: { - point const dest = pathCommand.args.lineto.dest; + Point const dest = pathCommand.args.lineto.dest; if (traceDraw) pm_message("Lining to (%u, %u)", dest.x, dest.y); ppmd_line(NULL, 0, 0, 0, @@ -465,12 +498,14 @@ outlineObject(path * const pathP, currentPos = subpathStart; break; case PATH_CUBIC: { - point const dest = pathCommand.args.cubic.dest; - point const ctl1 = pathCommand.args.cubic.ctl1; - point const ctl2 = pathCommand.args.cubic.ctl2; + Point const dest = pathCommand.args.cubic.dest; + Point const ctl1 = pathCommand.args.cubic.ctl1; + Point const ctl2 = pathCommand.args.cubic.ctl2; if (traceDraw) pm_message("Doing cubic spline to (%u, %u)", dest.x, dest.y); + pm_error("SVG image contains a cubic spline path. " + "This program cannot process cubic splines."); /* We need to write ppmd_spline4() */ ppmd_spline4p(NULL, 0, 0, 0, makePpmdPoint(currentPos), @@ -483,14 +518,14 @@ outlineObject(path * const pathP, } } } - destroyPathReader(pathReaderP); + pathReader_destroy(pathReaderP); } static void -drawPath(canvas * const canvasP, - path * const pathP) { +drawPath(Canvas * const canvasP, + Path * const pathP) { /*---------------------------------------------------------------------------- Draw the path 'pathP' on the canvas 'canvasP'. -----------------------------------------------------------------------------*/ @@ -517,10 +552,10 @@ drawPath(canvas * const canvasP, -static style +static Style interpretStyle(const char * const styleAttr) { - style style; + Style style; char * buffer; @@ -581,7 +616,7 @@ interpretStyle(const char * const styleAttr) { static void getPathAttributes(xmlTextReaderPtr const xmlReaderP, - style * const styleP, + Style * const styleP, const char ** const pathP) { const char * const style = getAttribute(xmlReaderP, "style"); @@ -627,11 +662,11 @@ processSubPathNode(xmlTextReaderPtr const xmlReaderP, static void processPathElement(xmlTextReaderPtr const xmlReaderP, - canvas * const canvasP) { + Canvas * const canvasP) { - style style; + Style style; const char * pathData; - path * pathP; + Path * pathP; bool endOfPath; assert(xmlTextReaderNodeType(xmlReaderP) == XML_READER_TYPE_ELEMENT); @@ -669,29 +704,6 @@ processPathElement(xmlTextReaderPtr const xmlReaderP, static void -stringToUint(const char * const string, - unsigned int * const uintP, - const char ** const errorP) { - - /* TODO: move this to nstring.c */ - - if (strlen(string) == 0) - pm_asprintf(errorP, "Value is a null string"); - else { - char * tailptr; - - *uintP = strtoul(string, &tailptr, 10); - - if (*tailptr != '\0') - pm_asprintf(errorP, "Non-numeric crap in string: '%s'", tailptr); - else - *errorP = NULL; - } -} - - - -static void getSvgAttributes(xmlTextReaderPtr const xmlReaderP, unsigned int * const colsP, unsigned int * const rowsP) { @@ -701,14 +713,16 @@ getSvgAttributes(xmlTextReaderPtr const xmlReaderP, const char * error; - stringToUint(width, colsP, &error); + pm_string_to_uint(width, colsP, &error); if (error) { - pm_error("'width' attribute of <svg> has invalid value. %s", error); + pm_error("'width' attribute of <svg> has invalid value '%s'. %s", + width, error); pm_strfree(error); } - stringToUint(height, rowsP, &error); + pm_string_to_uint(height, rowsP, &error); if (error) { - pm_error("'height' attribute of <svg> has invalid value. %s", error); + pm_error("'height' attribute of <svg> has invalid value '%s'. %s", + height, error); pm_strfree(error); } } @@ -717,7 +731,7 @@ getSvgAttributes(xmlTextReaderPtr const xmlReaderP, static void processSubSvgElement(xmlTextReaderPtr const xmlReaderP, - canvas * const canvasP) { + Canvas * const canvasP) { const char * const nodeName = currentNodeName(xmlReaderP); @@ -734,7 +748,7 @@ processSubSvgElement(xmlTextReaderPtr const xmlReaderP, static void processSubSvgNode(xmlTextReaderPtr const xmlReaderP, - canvas * const canvasP, + Canvas * const canvasP, bool * const endOfSvgP) { xmlReaderTypes const nodeType = xmlTextReaderNodeType(xmlReaderP); @@ -764,9 +778,9 @@ static void createCanvas(unsigned int const width, unsigned int const height, pixval const maxval, - canvas ** const canvasPP) { + Canvas ** const canvasPP) { - canvas * canvasP; + Canvas * canvasP; MALLOCVAR_NOFAIL(canvasP); @@ -781,7 +795,7 @@ createCanvas(unsigned int const width, static void -destroyCanvas(canvas * const canvasP) { +destroyCanvas(Canvas * const canvasP) { ppm_freearray(canvasP->pixels, canvasP->height); @@ -792,7 +806,7 @@ destroyCanvas(canvas * const canvasP) { static void writePam(FILE * const ofP, - canvas * const canvasP) { + Canvas * const canvasP) { unsigned int row; struct pam pam; @@ -838,7 +852,7 @@ processSvgElement(xmlTextReaderPtr const xmlReaderP, unsigned int width, height; bool endOfSvg; - canvas * canvasP; + Canvas * canvasP; assert(xmlTextReaderNodeType(xmlReaderP) == XML_READER_TYPE_ELEMENT); assert(streq(currentNodeName(xmlReaderP), "svg")); diff --git a/converter/other/tiff.c b/converter/other/tiff.c index d0cbbd74..39e3b0ce 100644 --- a/converter/other/tiff.c +++ b/converter/other/tiff.c @@ -6,6 +6,7 @@ ============================================================================*/ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _BSD_SOURCE /* Make sure strcaseeq() is in nstring.h */ #include <string.h> diff --git a/converter/other/tifftopnm.c b/converter/other/tifftopnm.c index 4a8cf902..c1e7af85 100644 --- a/converter/other/tifftopnm.c +++ b/converter/other/tifftopnm.c @@ -46,12 +46,14 @@ give the user the -byrow option to order (2) only. */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #include <assert.h> #include <string.h> #include <stdio.h> +#include <sys/wait.h> /* WIFSIGNALED, etc. */ #include "pm_c_util.h" #include "shhopt.h" @@ -182,14 +184,14 @@ getBps(TIFF * const tif, unsigned short tiffBps; unsigned short bps; - int rc; + int fldPresent; - rc = TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &tiffBps); - bps = (rc == 0) ? 1 : tiffBps; + fldPresent = TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &tiffBps); + bps = fldPresent ? tiffBps : 1; if (bps < 1 || (bps > 8 && bps != 16 && bps != 32)) pm_error("This program can process Tiff images with only " - "1-8 or 16 bits per sample. The input Tiff image " + "1-8 or 16 or 32 bits per sample. The input Tiff image " "has %hu bits per sample.", bps); else *bpsP = bps; @@ -217,26 +219,30 @@ struct tiffDirInfo { static void -tiffToImageDim(unsigned int const tiffCols, - unsigned int const tiffRows, +tiffToImageDim(unsigned int const tiffWidth, + unsigned int const tiffHeight, unsigned short const orientation, unsigned int * const imageColsP, unsigned int * const imageRowsP) { - +/*---------------------------------------------------------------------------- + Determine the image dimensions (as *imageColsP and *imageRowsP) from the + width, height, and orientation of the TIFF raster ('tiffWidth', + 'tiffHeight', and 'orientation', respectively. +-----------------------------------------------------------------------------*/ switch (orientation) { case ORIENTATION_TOPLEFT: case ORIENTATION_TOPRIGHT: case ORIENTATION_BOTRIGHT: case ORIENTATION_BOTLEFT: - *imageColsP = tiffCols; - *imageRowsP = tiffRows; + *imageColsP = tiffWidth; + *imageRowsP = tiffHeight; break; case ORIENTATION_LEFTTOP: case ORIENTATION_RIGHTTOP: case ORIENTATION_RIGHTBOT: case ORIENTATION_LEFTBOT: - *imageColsP = tiffRows; - *imageRowsP = tiffCols; + *imageColsP = tiffHeight; + *imageRowsP = tiffWidth; break; default: pm_error("Invalid value for orientation tag in TIFF directory: %u", @@ -255,28 +261,96 @@ getTiffDimensions(TIFF * const tiffP, dimensions of the internal raster matrix -- the dimensions of the actual visual image. -----------------------------------------------------------------------------*/ - int ok; + int fldPresent; unsigned int width, length; unsigned short tiffOrientation; unsigned short orientation; - int present; - ok = TIFFGetField(tiffP, TIFFTAG_IMAGEWIDTH, &width); - if (!ok) + fldPresent = TIFFGetField(tiffP, TIFFTAG_IMAGEWIDTH, &width); + if (!fldPresent) pm_error("Input Tiff file is invalid. It has no IMAGEWIDTH tag."); - ok = TIFFGetField(tiffP, TIFFTAG_IMAGELENGTH, &length); - if (!ok) + fldPresent = TIFFGetField(tiffP, TIFFTAG_IMAGELENGTH, &length); + if (!fldPresent) pm_error("Input Tiff file is invalid. It has no IMAGELENGTH tag."); - present = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); - orientation = present ? tiffOrientation : ORIENTATION_TOPLEFT; + fldPresent = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); + orientation = fldPresent ? tiffOrientation : ORIENTATION_TOPLEFT; tiffToImageDim(width, length, orientation, colsP, rowsP); } +static unsigned short +planarConfigFmTiff(TIFF * const tiffP) { + + int fldPresent; + unsigned short retval; + + fldPresent = TIFFGetField(tiffP, TIFFTAG_PLANARCONFIG, &retval); + + if (!fldPresent) + pm_error("PLANARCONFIG tag is not in Tiff file, though it " + "has more than one sample per pixel. " + "TIFFGetField() of it failed. This means the input " + "is not valid Tiff."); + + return retval; +} + + + +static void +validatePlanarConfig(unsigned short const planarconfig, + unsigned short const photomet) { + + switch (planarconfig) { + case PLANARCONFIG_CONTIG: + break; + case PLANARCONFIG_SEPARATE: + if (photomet != PHOTOMETRIC_RGB && + photomet != PHOTOMETRIC_SEPARATED) + pm_error("This program can handle separate planes only " + "with RGB (PHOTOMETRIC tag = %u) or SEPARATED " + "(PHOTOMETRIC tag = %u) data. The input Tiff file " + "has PHOTOMETRIC tag = %hu.", + PHOTOMETRIC_RGB, PHOTOMETRIC_SEPARATED, + photomet); + break; + default: + pm_error("Unrecognized PLANARCONFIG tag value in Tiff input: %u", + planarconfig); + } +} + + + +static unsigned short +orientationFmTiff(TIFF * const tiffP) { + + unsigned short tiffOrientation; + int fldPresent; + + fldPresent = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); + + return fldPresent ? tiffOrientation : ORIENTATION_TOPLEFT; +} + + + +static void +dumpHeader(const struct tiffDirInfo * const headerP) { + + pm_message("%ux%ux%u raster matrix, oriented %u", + headerP->width, headerP->height, + headerP->bps * headerP->spp, headerP->orientation); + pm_message("%hu bits/sample, %hu samples/pixel", + headerP->bps, headerP->spp); +} + + + static void readDirectory(TIFF * const tiffP, bool const headerdump, @@ -285,7 +359,7 @@ readDirectory(TIFF * const tiffP, Read various values of TIFF tags from the TIFF directory, and default them if not in there and make guesses where values are invalid. Exit program with error message if required tags aren't - there or values are inconsistent or beyond our capabilities. if + there or values are inconsistent or beyond our capabilities. If 'headerdump' is true, issue informational messages about what we find. @@ -293,7 +367,7 @@ readDirectory(TIFF * const tiffP, input file contains invalid values). We generally return those invalid values to our caller. -----------------------------------------------------------------------------*/ - int rc; + int fldPresent; unsigned short tiffSpp; if (headerdump) @@ -301,65 +375,35 @@ readDirectory(TIFF * const tiffP, getBps(tiffP, &headerP->bps); - rc = TIFFGetFieldDefaulted(tiffP, TIFFTAG_FILLORDER, &headerP->fillorder); - rc = TIFFGetField(tiffP, TIFFTAG_SAMPLESPERPIXEL, &tiffSpp); - headerP->spp = (rc == 0) ? 1 : tiffSpp; + fldPresent = + TIFFGetFieldDefaulted(tiffP, TIFFTAG_FILLORDER, &headerP->fillorder); + fldPresent = TIFFGetField(tiffP, TIFFTAG_SAMPLESPERPIXEL, &tiffSpp); + headerP->spp = fldPresent ? tiffSpp: 1; - rc = TIFFGetField(tiffP, TIFFTAG_PHOTOMETRIC, &headerP->photomet); - if (rc == 0) + fldPresent = TIFFGetField(tiffP, TIFFTAG_PHOTOMETRIC, &headerP->photomet); + if (!fldPresent) pm_error("PHOTOMETRIC tag is not in Tiff file. " "TIFFGetField() of it failed.\n" "This means the input is not valid Tiff."); - if (headerP->spp > 1) { - rc = TIFFGetField(tiffP, TIFFTAG_PLANARCONFIG, &headerP->planarconfig); - if (rc == 0) - pm_error("PLANARCONFIG tag is not in Tiff file, though it " - "has more than one sample per pixel. " - "TIFFGetField() of it failed. This means the input " - "is not valid Tiff."); - } else + if (headerP->spp > 1) + headerP->planarconfig = planarConfigFmTiff(tiffP); + else headerP->planarconfig = PLANARCONFIG_CONTIG; - switch (headerP->planarconfig) { - case PLANARCONFIG_CONTIG: - break; - case PLANARCONFIG_SEPARATE: - if (headerP->photomet != PHOTOMETRIC_RGB && - headerP->photomet != PHOTOMETRIC_SEPARATED) - pm_error("This program can handle separate planes only " - "with RGB (PHOTOMETRIC tag = %u) or SEPARATED " - "(PHOTOMETRIC tag = %u) data. The input Tiff file " - "has PHOTOMETRIC tag = %hu.", - PHOTOMETRIC_RGB, PHOTOMETRIC_SEPARATED, - headerP->photomet); - break; - default: - pm_error("Unrecognized PLANARCONFIG tag value in Tiff input: %u.\n", - headerP->planarconfig); - } + validatePlanarConfig(headerP->planarconfig, headerP->photomet); - rc = TIFFGetField(tiffP, TIFFTAG_IMAGEWIDTH, &headerP->width); - if (rc == 0) + fldPresent = TIFFGetField(tiffP, TIFFTAG_IMAGEWIDTH, &headerP->width); + if (!fldPresent) pm_error("Input Tiff file is invalid. It has no IMAGEWIDTH tag."); - rc = TIFFGetField(tiffP, TIFFTAG_IMAGELENGTH, &headerP->height); - if (rc == 0) + fldPresent = TIFFGetField(tiffP, TIFFTAG_IMAGELENGTH, &headerP->height); + if (!fldPresent) pm_error("Input Tiff file is invalid. It has no IMAGELENGTH tag."); - { - unsigned short tiffOrientation; - int present; - present = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); - headerP->orientation = - present ? tiffOrientation : ORIENTATION_TOPLEFT; - } - if (headerdump) { - pm_message("%ux%ux%u raster matrix, oriented %u", - headerP->width, headerP->height, - headerP->bps * headerP->spp, headerP->orientation); - pm_message("%hu bits/sample, %hu samples/pixel", - headerP->bps, headerP->spp); - } + headerP->orientation = orientationFmTiff(tiffP); + + if (headerdump) + dumpHeader(headerP); } @@ -533,7 +577,7 @@ computeFillorder(unsigned short const fillorderTag, static void -analyzeImageType(TIFF * const tif, +analyzeImageType(TIFF * const tiffP, unsigned short const bps, unsigned short const spp, unsigned short const photomet, @@ -542,129 +586,147 @@ analyzeImageType(TIFF * const tif, xel * const colormap, bool const headerdump, struct CmdlineInfo const cmdline) { +/*---------------------------------------------------------------------------- + Determine from the TIFF header in *tif certain properties of the image + as well as the proper format of PNM image for the conversion. - bool grayscale; - - /* How come we don't deal with the photometric for the monochrome - case (make sure it's one we know)? -Bryan 00.03.04 - */ - switch (photomet) { - case PHOTOMETRIC_MINISBLACK: - case PHOTOMETRIC_MINISWHITE: - if (spp != 1) - pm_error("This grayscale image has %d samples per pixel. " - "We understand only 1.", spp); - grayscale = TRUE; - *maxvalP = pm_bitstomaxval(MIN(bps,16)); - if (headerdump) - pm_message("grayscale image, (min=%s) output maxval %u ", - photomet == PHOTOMETRIC_MINISBLACK ? - "black" : "white", - *maxvalP - ); - break; + *formatP and *maxvalP are the basic PNM parameters. +-----------------------------------------------------------------------------*/ + switch (photomet) { + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_MINISWHITE: + if (spp != 1) + pm_error("This grayscale image has %d samples per pixel. " + "We understand only 1.", spp); + + *formatP = bps == 1 ? PBM_TYPE : PGM_TYPE; + + *maxvalP = pm_bitstomaxval(MIN(bps, 16)); + + if (headerdump) + pm_message("grayscale image, (min=%s) output maxval %u ", + photomet == PHOTOMETRIC_MINISBLACK ? + "black" : "white", + *maxvalP + ); + break; - case PHOTOMETRIC_PALETTE: { - int i; - int numcolors; - unsigned short* redcolormap; - unsigned short* greencolormap; - unsigned short* bluecolormap; - - if (headerdump) - pm_message("colormapped"); - - if (spp != 1) - pm_error("This paletted image has %d samples per pixel. " - "We understand only 1.", spp); - - if (!TIFFGetField(tif, TIFFTAG_COLORMAP, - &redcolormap, &greencolormap, &bluecolormap)) - pm_error("error getting colormaps"); - - numcolors = 1 << bps; - if (numcolors > MAXCOLORS) - pm_error("too many colors"); - *maxvalP = PNM_MAXMAXVAL; - grayscale = FALSE; - for (i = 0; i < numcolors; ++i) { - xelval r, g, b; - r = (long) redcolormap[i] * PNM_MAXMAXVAL / 65535L; - g = (long) greencolormap[i] * PNM_MAXMAXVAL / 65535L; - b = (long) bluecolormap[i] * PNM_MAXMAXVAL / 65535L; - PPM_ASSIGN(colormap[i], r, g, b); - } + case PHOTOMETRIC_PALETTE: { + int fldPresent; + int i; + int numcolors; + unsigned short* redcolormap; + unsigned short* greencolormap; + unsigned short* bluecolormap; + + if (headerdump) + pm_message("colormapped"); + + if (spp != 1) + pm_error("This paletted image has %d samples per pixel. " + "We understand only 1.", spp); + + fldPresent = TIFFGetField( + tiffP, TIFFTAG_COLORMAP, + &redcolormap, &greencolormap, &bluecolormap); + + if (!fldPresent) + pm_error("error getting colormaps"); + + numcolors = 1 << bps; + if (numcolors > MAXCOLORS) + pm_error("too many colors"); + + *formatP = PPM_TYPE; + + *maxvalP = PNM_MAXMAXVAL; + + for (i = 0; i < numcolors; ++i) { + xelval r, g, b; + r = (long) redcolormap[i] * PNM_MAXMAXVAL / 65535L; + g = (long) greencolormap[i] * PNM_MAXMAXVAL / 65535L; + b = (long) bluecolormap[i] * PNM_MAXMAXVAL / 65535L; + PPM_ASSIGN(colormap[i], r, g, b); } + } break; - case PHOTOMETRIC_SEPARATED: { - unsigned short inkset; - - if (headerdump) - pm_message("color separation"); - if (TIFFGetField(tif, TIFFTAG_INKNAMES, &inkset) == 1 - && inkset != INKSET_CMYK) - if (inkset != INKSET_CMYK) - pm_error("This color separation file uses an inkset (%d) " - "we can't handle. We handle only CMYK.", inkset); - if (spp != 4) - pm_error("This CMYK color separation file is %d samples per " - "pixel. " - "We need 4 samples, though: C, M, Y, and K. ", - spp); - grayscale = FALSE; - *maxvalP = (1 << bps) - 1; - } + case PHOTOMETRIC_SEPARATED: { + unsigned short inkset; + int fldPresent; + + if (headerdump) + pm_message("color separation"); + + fldPresent = TIFFGetField(tiffP, TIFFTAG_INKNAMES, &inkset); + if (fldPresent && inkset != INKSET_CMYK) + pm_error("This color separation file uses an inkset (%d) " + "we can't handle. We handle only CMYK.", inkset); + if (spp != 4) + pm_error("This CMYK color separation file is %d samples per " + "pixel. " + "We need 4 samples, though: C, M, Y, and K. ", + spp); + + *formatP = PPM_TYPE; + + *maxvalP = (1 << bps) - 1; + } break; - case PHOTOMETRIC_RGB: - if (headerdump) - pm_message("RGB truecolor"); - grayscale = FALSE; + case PHOTOMETRIC_RGB: + if (headerdump) + pm_message("RGB truecolor"); - if (spp != 3 && spp != 4) - pm_error("This RGB image has %d samples per pixel. " - "We understand only 3 or 4.", spp); + if (spp != 3 && spp != 4) + pm_error("This RGB image has %d samples per pixel. " + "We understand only 3 or 4.", spp); - *maxvalP = (1 << bps) - 1; - break; + *formatP = PPM_TYPE; - case PHOTOMETRIC_MASK: - pm_error("don't know how to handle PHOTOMETRIC_MASK"); + *maxvalP = (1 << bps) - 1; + break; - case PHOTOMETRIC_DEPTH: - pm_error("don't know how to handle PHOTOMETRIC_DEPTH"); + case PHOTOMETRIC_MASK: + pm_error("don't know how to handle PHOTOMETRIC_MASK"); - case PHOTOMETRIC_YCBCR: - pm_error("don't know how to handle PHOTOMETRIC_YCBCR"); + case PHOTOMETRIC_DEPTH: + pm_error("don't know how to handle PHOTOMETRIC_DEPTH"); - case PHOTOMETRIC_CIELAB: - pm_error("don't know how to handle PHOTOMETRIC_CIELAB"); + case PHOTOMETRIC_YCBCR: + pm_error("don't know how to handle PHOTOMETRIC_YCBCR"); - case PHOTOMETRIC_LOGL: - pm_error("don't know how to handle PHOTOMETRIC_LOGL"); + case PHOTOMETRIC_CIELAB: + pm_error("don't know how to handle PHOTOMETRIC_CIELAB"); - case PHOTOMETRIC_LOGLUV: - pm_error("don't know how to handle PHOTOMETRIC_LOGLUV"); + case PHOTOMETRIC_LOGL: + pm_error("don't know how to handle PHOTOMETRIC_LOGL"); + + case PHOTOMETRIC_LOGLUV: + pm_error("don't know how to handle PHOTOMETRIC_LOGLUV"); - default: - pm_error("unknown photometric: %d", photomet); - } + default: + pm_error("unknown photometric: %d", photomet); + } if (*maxvalP > PNM_OVERALLMAXVAL) - pm_error("bits/sample (%d) in the input image is too large.", - bps); - if (grayscale) { - if (*maxvalP == 1) { - *formatP = PBM_TYPE; - pm_message("writing PBM file"); - } else { - *formatP = PGM_TYPE; - pm_message("writing PGM file"); - } - } else { - *formatP = PPM_TYPE; - pm_message("writing PPM file"); + pm_error("bits/sample (%u) in the input image is too large.", bps); +} + + + +static void +reportOutputFormat(int const format) { + + const char * formatDesc; + + switch (format) { + case PBM_TYPE: formatDesc = "PBM"; break; + case PGM_TYPE: formatDesc = "PGM"; break; + case PPM_TYPE: formatDesc = "PPM"; break; + default: assert(false); } + + pm_message("writing %s file", formatDesc); } @@ -775,14 +837,22 @@ spawnWithInputPipe(const char * const shellCmd, else *errorP = NULL; } else { - int rc; + int terminationStatus; close(fd[PIPE_WRITE]); close(STDIN_FILENO); dup2(fd[PIPE_READ], STDIN_FILENO); - rc = system(shellCmd); + terminationStatus = system(shellCmd); - exit(rc); + if (WIFSIGNALED(terminationStatus)) + pm_error("Shell process was killed " + "by a Class %u signal.", + WTERMSIG(terminationStatus)); + else if (!WIFEXITED(terminationStatus)) + pm_error("Shell process died, but its termination status " + "0x%x doesn't make sense", terminationStatus); + else + exit(WEXITSTATUS(terminationStatus)); } } } @@ -1364,9 +1434,9 @@ warnBrokenTiffLibrary(TIFF * const tiffP) { */ unsigned short tiffOrientation; - int present; - present = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); - if (present) { + int fldPresent; + fldPresent = TIFFGetField(tiffP, TIFFTAG_ORIENTATION, &tiffOrientation); + if (fldPresent) { switch (tiffOrientation) { case ORIENTATION_LEFTTOP: case ORIENTATION_RIGHTTOP: @@ -1438,16 +1508,47 @@ enum convertDisp {CONV_DONE, CONV_FAILED, CONV_NOTATTEMPTED}; + +static void +convertRasterIntoProvidedMemory(pnmOut * const pnmOutP, + unsigned int const cols, + unsigned int const rows, + xelval const maxval, + TIFF * const tif, + bool const verbose, + uint32 * const raster, + enum convertDisp * const statusP) { + + int const stopOnErrorFalse = false; + + TIFFRGBAImage img; + char emsg[1024]; + int ok; + + ok = TIFFRGBAImageBegin(&img, tif, stopOnErrorFalse, emsg); + if (!ok) { + pm_message("%s", emsg); + *statusP = CONV_FAILED; + } else { + int ok; + ok = TIFFRGBAImageGet(&img, raster, cols, rows); + TIFFRGBAImageEnd(&img) ; + if (!ok) { + pm_message("%s", emsg); + *statusP = CONV_FAILED; + } else { + *statusP = CONV_DONE; + convertTiffRaster(raster, cols, rows, maxval, pnmOutP); + } + } +} + + + static void convertRasterInMemory(pnmOut * const pnmOutP, xelval const maxval, TIFF * const tif, - unsigned short const photomet, - unsigned short const planarconfig, - unsigned short const bps, - unsigned short const spp, - unsigned short const fillorder, - xel const colormap[], bool const verbose, enum convertDisp * const statusP) { /*---------------------------------------------------------------------------- @@ -1467,64 +1568,49 @@ convertRasterInMemory(pnmOut * const pnmOutP, programs, we simply abort the program if we are unable to allocate memory for other things. -----------------------------------------------------------------------------*/ - unsigned int cols, rows; /* Dimensions of output image */ + char emsg[1024]; + int ok; if (verbose) pm_message("Converting in memory ..."); warnBrokenTiffLibrary(tif); - getTiffDimensions(tif, &cols, &rows); - - if (rows == 0 || cols == 0) - *statusP = CONV_DONE; - else { - char emsg[1024]; - int ok; - ok = TIFFRGBAImageOK(tif, emsg); - if (!ok) { - pm_message("%s", emsg); - *statusP = CONV_UNABLE; - } else { - uint32 * raster; + ok = TIFFRGBAImageOK(tif, emsg); + if (!ok) { + pm_message("%s", emsg); + *statusP = CONV_UNABLE; + } else { + unsigned int cols, rows; /* Dimensions of output image */ + getTiffDimensions(tif, &cols, &rows); - /* Note that TIFFRGBAImageGet() converts any bits per sample - to 8. Maxval of the raster it returns is always 255. - */ + if (rows == 0 || cols == 0) + *statusP = CONV_DONE; + else { if (cols > UINT_MAX/rows) { pm_message("%u rows of %u columns is too large to compute", rows, cols); *statusP = CONV_OOM; - return; - } - - MALLOCARRAY(raster, cols * rows); - if (raster == NULL) { - pm_message("Unable to allocate space for a raster of %u " - "pixels.", cols * rows); - *statusP = CONV_OOM; } else { - int const stopOnErrorFalse = FALSE; - TIFFRGBAImage img; - int ok; - - ok = TIFFRGBAImageBegin(&img, tif, stopOnErrorFalse, emsg); - if (!ok) { - pm_message("%s", emsg); - *statusP = CONV_FAILED; + unsigned int const pixelCt = rows * cols; + + uint32 * raster; + + /* Note that TIFFRGBAImageGet() converts any bits per sample + to 8. Maxval of the raster it returns is always 255. + */ + MALLOCARRAY(raster, pixelCt); + if (raster == NULL) { + pm_message("Unable to allocate space for a raster of %u " + "pixels.", pixelCt); + *statusP = CONV_OOM; } else { - int ok; - ok = TIFFRGBAImageGet(&img, raster, cols, rows); - TIFFRGBAImageEnd(&img) ; - if (!ok) { - pm_message("%s", emsg); - *statusP = CONV_FAILED; - } else { - *statusP = CONV_DONE; - convertTiffRaster(raster, cols, rows, maxval, pnmOutP); - } - } - free(raster); + convertRasterIntoProvidedMemory( + pnmOutP, cols, rows, maxval, tif, verbose, + raster, statusP); + + free(raster); + } } } } @@ -1549,11 +1635,7 @@ convertRaster(pnmOut * const pnmOutP, if (byrow || !flipOk) status = CONV_NOTATTEMPTED; else { - convertRasterInMemory( - pnmOutP, maxval, - tifP, tiffDir.photomet, tiffDir.planarconfig, - tiffDir.bps, tiffDir.spp, fillorder, - colormap, verbose, &status); + convertRasterInMemory(pnmOutP, maxval, tifP, verbose, &status); } if (status == CONV_DONE) { if (tiffDir.bps > 8) @@ -1602,6 +1684,8 @@ convertImage(TIFF * const tifP, analyzeImageType(tifP, tiffDir.bps, tiffDir.spp, tiffDir.photomet, &maxval, &format, colormap, cmdline.headerdump, cmdline); + reportOutputFormat(format); + pnmOut_init(imageoutFileP, alphaFileP, tiffDir.width, tiffDir.height, tiffDir.orientation, maxval, format, maxval, cmdline.byrow, cmdline.orientraw, diff --git a/converter/other/winicontopam.c b/converter/other/winicontopam.c index 664b4ef9..69ce7f05 100644 --- a/converter/other/winicontopam.c +++ b/converter/other/winicontopam.c @@ -1156,9 +1156,9 @@ convertPng(const unsigned char * const image, imageBuffer.buffer = (unsigned char *)image; fflush (stdout); - pm_system(pm_feed_from_memory, &imageBuffer, - NULL /* stdout accepter */, NULL, - "pngtopam -alphapam"); + pm_system_lp("pngtopam", pm_feed_from_memory, &imageBuffer, + NULL /* stdout accepter */, NULL, + "pngtopam", "-alphapam", NULL); } diff --git a/converter/other/xwdtopnm.c b/converter/other/xwdtopnm.c index d49a2b09..df3c7375 100644 --- a/converter/other/xwdtopnm.c +++ b/converter/other/xwdtopnm.c @@ -23,6 +23,7 @@ */ +#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ |