diff options
Diffstat (limited to 'converter/ppm')
29 files changed, 1803 insertions, 2908 deletions
diff --git a/converter/ppm/ppmtogif.c b/converter/ppm/ppmtogif.c index 3100fea1..2b8a2596 100644 --- a/converter/ppm/ppmtogif.c +++ b/converter/ppm/ppmtogif.c @@ -1,101 +1,56 @@ -/* ppmtogif.c - read a portable pixmap and produce a GIF file -** -** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A -** Lempel-Zim compression based on "compress". -** -** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl> -** -** The non-LZW GIF generation stuff was adapted from the Independent -** JPEG Group's djpeg on 2001.09.29. The uncompressed output subroutines -** are derived directly from the corresponding subroutines in djpeg's -** wrgif.c source file. Its copyright notice say: - - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - The reference README file is README.JPEG in the Netpbm package. -** -** 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. -*/ +/* This is a backward compatibility interface to Pamtogif. + + Pamtogif replaced Ppmtogif in Netpbm 10.37 (December 2006). -/* TODO: merge the LZW and uncompressed subroutines. They are separate - only because they had two different lineages and the code is too - complicated for me quickly to rewrite it. + The only significant way Pamtogif is not backward compatible with + old Ppmtogif is that Pamtogif does not have a -alpha option. */ -#include <assert.h> +#define _BSD_SOURCE /* Make sure strdup() is in string.h */ +#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ + #include <string.h> +#include <stdio.h> +#include <sys/stat.h> +#include <unistd.h> #include "mallocvar.h" #include "shhopt.h" -#include "ppm.h" +#include "nstring.h" +#include "pam.h" -#define MAXCMAPSIZE 256 -static unsigned int const gifMaxval = 255; -static bool verbose; -/* - * a code_int must be able to hold 2**BITS values of type int, and also -1 - */ -typedef int code_int; +static const char * +dirname(const char * const fileName) { -typedef long int count_int; + char * buffer; + char * slashPos; + buffer = strdup(fileName); + + slashPos = strchr(buffer, '/'); + + if (slashPos) + *slashPos = '\0'; + + return buffer; +} -struct cmap { - /* This is the information for the GIF colormap (aka palette). */ - int red[MAXCMAPSIZE], green[MAXCMAPSIZE], blue[MAXCMAPSIZE]; - /* These arrays arrays map a color index, as is found in - the raster part of the GIF, to an intensity value for the indicated - RGB component. - */ - int perm[MAXCMAPSIZE], permi[MAXCMAPSIZE]; - /* perm[i] is the position in the sorted colormap of the color which - is at position i in the unsorted colormap. permi[] is the inverse - function of perm[]. - */ - int cmapsize; - /* Number of entries in the GIF colormap. I.e. number of colors - in the image, plus possibly one fake transparency color. - */ - int transparent; - /* color index number in GIF palette of the color that is to be - transparent. -1 if no color is transparent. - */ - colorhash_table cht; - /* A hash table that relates a PPM pixel value to to a pre-sort - GIF colormap index. - */ - pixval maxval; - /* The maxval for the colors in 'cht'. */ -}; struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char *input_filespec; /* Filespec of input file */ - const char *alpha_filespec; /* Filespec of alpha file; NULL if none */ - const char *alphacolor; /* -alphacolor option value or default */ - unsigned int interlace; /* -interlace option value */ - unsigned int sort; /* -sort option value */ + const char *input_filespec; /* Filespec of input file */ + const char *alpha_filespec; /* Filespec of alpha file; NULL if none */ + const char *alphacolor; /* -alphacolor option value or default */ + unsigned int interlace; /* -interlace option value */ + unsigned int sort; /* -sort option value */ const char *mapfile; /* -mapfile option value. NULL if none. */ 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 nolzw; /* -nolzw option */ unsigned int verbose; }; @@ -122,8 +77,8 @@ handleLatex2htmlHack(void) { -Bryan 2001.11.14 -----------------------------------------------------------------------------*/ pm_error("latex2html, you should just try the -interlace and " - "-transparent options to see if they work instead of " - "expecting a 'usage' message from -h"); + "-transparent options to see if they work instead of " + "expecting a 'usage' message from -h"); } @@ -204,1354 +159,223 @@ parseCommandLine(int argc, char ** argv, -/* - * Write out a word to the GIF file - */ -static void -Putword(int const w, FILE * const fp) { - - fputc( w & 0xff, fp ); - fputc( (w / 256) & 0xff, fp ); -} - - -static int -closestcolor(pixel const color, - pixval const maxval, - struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - Return the pre-sort colormap index of the color in the colormap *cmapP - that is closest to the color 'color', whose maxval is 'maxval'. - - Also add 'color' to the colormap hash, with the colormap index we - are returning. Caller must ensure that the color is not already in - there. ------------------------------------------------------------------------------*/ - unsigned int i; - unsigned int imin, dmin; - - pixval const r = PPM_GETR(color) * gifMaxval / maxval; - pixval const g = PPM_GETG(color) * gifMaxval / maxval; - pixval const b = PPM_GETB(color) * gifMaxval / maxval; - - dmin = SQR(255) * 3; - imin = 0; - for (i=0;i < cmapP->cmapsize; i++) { - int const d = SQR(r-cmapP->red[i]) + - SQR(g-cmapP->green[i]) + - SQR(b-cmapP->blue[i]); - if (d < dmin) { - dmin = d; - imin = i; - } - } - ppm_addtocolorhash(cmapP->cht, &color, cmapP->permi[imin]); - - return cmapP->permi[imin]; -} - - - -enum pass {MULT8PLUS0, MULT8PLUS4, MULT4PLUS2, MULT2PLUS1}; - - -struct pixelCursor { - unsigned int width; - /* Width of the image, in columns */ - unsigned int height; - /* Height of the image, in rows */ - bool interlace; - /* We're accessing the image in interlace fashion */ - unsigned int nPixelsLeft; - /* Number of pixels left to be read */ - unsigned int curCol; - /* Location of pointed-to pixel, column */ - unsigned int curRow; - /* Location of pointed-to pixel, row */ - enum pass pass; - /* The interlace pass. Undefined if !interlace */ -}; +static const char * +pamtogifCommand(const char * const arg0, + struct cmdlineInfo const cmdline) { + const char * const pamtogifName = "pamtogif"; + const char * retval; -static struct pixelCursor pixelCursor; - /* Current location in the input pixels. */ + const char * commandVerb; + const char * mapfileOpt; + const char * transparentOpt; + const char * commentOpt; + if (strchr(arg0, '/')) { + const char * const arg0DirName = dirname(arg0); + const char * progName; -static void -initPixelCursor(unsigned int const width, - unsigned int const height, - bool const interlace) { - - pixelCursor.width = width; - pixelCursor.height = height; - pixelCursor.interlace = interlace; - pixelCursor.pass = MULT8PLUS0; - pixelCursor.curCol = 0; - pixelCursor.curRow = 0; - pixelCursor.nPixelsLeft = width * height; -} + struct stat statbuf; + asprintfN(&progName, "%s/%s", arg0DirName, pamtogifName); - -static void -getPixel(pixel ** const pixels, - pixval const inputMaxval, - gray ** const alpha, - gray const alphaThreshold, - struct cmap * const cmapP, - struct pixelCursor const pixelCursor, - int * const retvalP) { -/*---------------------------------------------------------------------------- - Return as *retvalP the colormap index of the pixel at location - pointed to by 'pixelCursor' in the PPM raster 'pixels', using - colormap *cmapP. ------------------------------------------------------------------------------*/ - unsigned int const x = pixelCursor.curCol; - unsigned int const y = pixelCursor.curRow; - - int colorindex; - - if (alpha && alpha[y][x] < alphaThreshold) - colorindex = cmapP->transparent; - else { - int presortColorindex; - - presortColorindex = ppm_lookupcolor(cmapP->cht, &pixels[y][x]); - if (presortColorindex == -1) - presortColorindex = - closestcolor(pixels[y][x], inputMaxval, cmapP); - colorindex = cmapP->perm[presortColorindex]; - } - *retvalP = colorindex; -} - - - -static void -bumpRowInterlace(struct pixelCursor * const pixelCursorP) { -/*---------------------------------------------------------------------------- - Move *pixelCursorP to the next row in the interlace pattern. ------------------------------------------------------------------------------*/ - /* There are 4 passes: - MULT8PLUS0: Rows 8, 16, 24, 32, etc. - MULT8PLUS4: Rows 4, 12, 20, 28, etc. - MULT4PLUS2: Rows 2, 6, 10, 14, etc. - MULT2PLUS1: Rows 1, 3, 5, 7, 9, etc. - */ - - switch (pixelCursorP->pass) { - case MULT8PLUS0: - pixelCursorP->curRow += 8; - break; - case MULT8PLUS4: - pixelCursorP->curRow += 8; - break; - case MULT4PLUS2: - pixelCursorP->curRow += 4; - break; - case MULT2PLUS1: - pixelCursorP->curRow += 2; - break; - } - /* Set the proper pass for the next read. Note that if there are - more than 4 rows, the sequence of passes is sequential, but - when there are fewer than 4, we may skip e.g. from MULT8PLUS0 - to MULT4PLUS2. - */ - while (pixelCursorP->curRow >= pixelCursorP->height) { - switch (pixelCursorP->pass) { - case MULT8PLUS0: - pixelCursorP->pass = MULT8PLUS4; - pixelCursorP->curRow = 4; - break; - case MULT8PLUS4: - pixelCursorP->pass = MULT4PLUS2; - pixelCursorP->curRow = 2; - break; - case MULT4PLUS2: - pixelCursorP->pass = MULT2PLUS1; - pixelCursorP->curRow = 1; - break; - case MULT2PLUS1: - /* We've read the entire image; pass and current row are - now undefined. - */ - pixelCursorP->curRow = 0; - break; - } - } -} - - - -static void -bumpPixel(struct pixelCursor * const pixelCursorP) { -/*---------------------------------------------------------------------------- - Bump *pixelCursorP to point to the next pixel to go into the GIF - - Must not call when there are no pixels left. ------------------------------------------------------------------------------*/ - assert(pixelCursorP->nPixelsLeft > 0); - - /* Move one column to the right */ - ++pixelCursorP->curCol; - - if (pixelCursorP->curCol >= pixelCursorP->width) { - /* That pushed us past the end of a row. */ - /* Reset to the left edge ... */ - pixelCursorP->curCol = 0; - - /* ... of the next row */ - if (!pixelCursorP->interlace) - /* Go to the following row */ - ++pixelCursorP->curRow; + if (stat(progName, &statbuf) == 0) + commandVerb = progName; else - bumpRowInterlace(pixelCursorP); - } - --pixelCursorP->nPixelsLeft; -} - - - -static int -gifNextPixel(pixel ** const pixels, - pixval const inputMaxval, - gray ** const alpha, - gray const alphaThreshold, - struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - Return the pre-sort color index (index into the unsorted GIF color map) - of the next pixel to be processed from the input image. - - 'alpha_threshold' is the gray level such that a pixel in the alpha - map whose value is less that that represents a transparent pixel - in the output. ------------------------------------------------------------------------------*/ - int retval; - - if (pixelCursor.nPixelsLeft == 0 ) - retval = EOF; - else { - getPixel(pixels, inputMaxval, alpha, alphaThreshold, cmapP, - pixelCursor, &retval); - - bumpPixel(&pixelCursor); - } - return retval; -} - - - -static void -write_transparent_color_index_extension(FILE *fp, const int Transparent) { -/*---------------------------------------------------------------------------- - Write out extension for transparent color index. ------------------------------------------------------------------------------*/ - - fputc( '!', fp ); - fputc( 0xf9, fp ); - fputc( 4, fp ); - fputc( 1, fp ); - fputc( 0, fp ); - fputc( 0, fp ); - fputc( Transparent, fp ); - fputc( 0, fp ); -} - - - -static void -write_comment_extension(FILE *fp, const char comment[]) { -/*---------------------------------------------------------------------------- - Write out extension for a comment ------------------------------------------------------------------------------*/ - char *segment; - - fputc('!', fp); /* Identifies an extension */ - fputc(0xfe, fp); /* Identifies a comment */ - - /* Write it out in segments no longer than 255 characters */ - for (segment = (char *) comment; - segment < comment+strlen(comment); - segment += 255) { - - const int length_this_segment = MIN(255, strlen(segment)); - - fputc(length_this_segment, fp); - - fwrite(segment, 1, length_this_segment, fp); - } - - fputc(0, fp); /* No more comment blocks in this extension */ -} - - - -/*************************************************************************** - * - * GIFCOMPR.C - GIF Image compression routines - * - * Lempel-Ziv compression based on 'compress'. GIF modifications by - * David Rowley (mgardi@watdcsu.waterloo.edu) - * - ***************************************************************************/ - -/* - * General DEFINEs - */ - -#define BITS 12 - -#define HSIZE 5003 /* 80% occupancy */ - -#ifdef NO_UCHAR - typedef char char_type; -#else /*NO_UCHAR*/ - typedef unsigned char char_type; -#endif /*NO_UCHAR*/ - -/* - * - * GIF Image compression - modified 'compress' - * - * Based on: compress.c - File compression ala IEEE Computer, June 1984. - * - * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) - * Jim McKie (decvax!mcvax!jim) - * Steve Davies (decvax!vax135!petsd!peora!srd) - * Ken Turkowski (decvax!decwrl!turtlevax!ken) - * James A. Woods (decvax!ihnp4!ames!jaw) - * Joe Orost (decvax!vax135!petsd!joe) - * - */ -#include <ctype.h> - -#define ARGVAL() (*++(*argv) || (--argc && *++argv)) - -static code_int const maxmaxcode = (code_int)1 << BITS; - /* should NEVER generate this code */ -#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) - -static long htab [HSIZE]; -static unsigned short codetab [HSIZE]; -#define HashTabOf(i) htab[i] -#define CodeTabOf(i) codetab[i] - -/* - * To save much memory, we overlay the table used by compress() with those - * used by decompress(). The tab_prefix table is the same size and type - * as the codetab. The tab_suffix table needs 2**BITS characters. We - * get this from the beginning of htab. The output stack uses the rest - * of htab, and contains characters. There is plenty of room for any - * possible stack (stack used to be 8000 characters). - */ - -#define tab_prefixof(i) CodeTabOf(i) -#define tab_suffixof(i) ((char_type*)(htab))[i] -#define de_stack ((char_type*)&tab_suffixof((code_int)1<<BITS)) - -static code_int free_ent = 0; /* first unused entry */ - -/* - * block compression parameters -- after all codes are used up, - * and compression rate changes, start over. - */ -static int clear_flg = 0; - -static int offset; -static long int in_count = 1; /* length of input */ -static long int out_count = 0; /* # of codes output (for debugging) */ - -/* - * 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 - * secondary probe. Here, the modular division first probe is gives way - * to a faster exclusive-or manipulation. Also do block compression with - * an adaptive reset, whereby the code table is cleared when the compression - * ratio decreases, but after the table fills. The variable-length output - * codes are re-sized at this point, and a special CLEAR code is generated - * for the decompressor. Late addition: construct the table according to - * file size for noticeable speed improvement on small files. Please direct - * questions about this implementation to ames!jaw. - */ - -static int ClearCode; -static int EOFCode; - -/*************************************************************************** -* BYTE OUTPUTTER -***************************************************************************/ - -typedef struct { - FILE * fileP; /* The file to which to output */ - unsigned int count; - /* Number of bytes so far in the current data block */ - unsigned char buffer[256]; - /* The current data block, under construction */ -} byteBuffer; - - - -static byteBuffer * -byteBuffer_create(FILE * const fileP) { - - byteBuffer * byteBufferP; - - MALLOCVAR_NOFAIL(byteBufferP); - - byteBufferP->fileP = fileP; - byteBufferP->count = 0; - - return byteBufferP; -} - - - -static void -byteBuffer_destroy(byteBuffer * const byteBufferP) { - - free(byteBufferP); -} - - - -static void -byteBuffer_flush(byteBuffer * const byteBufferP) { -/*---------------------------------------------------------------------------- - Write the current data block to the output file, then reset the current - data block to empty. ------------------------------------------------------------------------------*/ - if (byteBufferP->count > 0 ) { - if (verbose) - pm_message("Writing %u byte block", byteBufferP->count); - fputc(byteBufferP->count, byteBufferP->fileP); - fwrite(byteBufferP->buffer, 1, byteBufferP->count, byteBufferP->fileP); - byteBufferP->count = 0; - } -} - - - -static void -byteBuffer_flushFile(byteBuffer * const byteBufferP) { - - fflush(byteBufferP->fileP); - - if (ferror(byteBufferP->fileP)) - pm_error("error writing output file"); -} - - + commandVerb = strdup(pamtogifName); -static void -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 254 - characters, flush the data block to the output file. ------------------------------------------------------------------------------*/ - byteBufferP->buffer[byteBufferP->count++] = c; - if (byteBufferP->count >= 254) - byteBuffer_flush(byteBufferP); -} - - - -struct gif_dest { - /* This structure controls output of uncompressed GIF raster */ - - byteBuffer * byteBufferP; /* Where the full bytes go */ - - /* State for packing variable-width codes into a bitstream */ - int n_bits; /* current number of bits/code */ - int maxcode; /* maximum code, given n_bits */ - int cur_accum; /* holds bits not yet output */ - int cur_bits; /* # of bits in cur_accum */ - - /* State for GIF code assignment */ - int ClearCode; /* clear code (doesn't change) */ - int EOFCode; /* EOF code (ditto) */ - int code_counter; /* counts output symbols */ -}; - - - -static unsigned long const masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, - 0x001F, 0x003F, 0x007F, 0x00FF, - 0x01FF, 0x03FF, 0x07FF, 0x0FFF, - 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; - -typedef struct { - byteBuffer * byteBufferP; - unsigned int initBits; - unsigned int n_bits; /* number of bits/code */ - code_int maxcode; /* maximum code, given n_bits */ - unsigned long curAccum; - int curBits; -} codeBuffer; - - - -static codeBuffer * -codeBuffer_create(FILE * const ofP, - unsigned int const initBits) { - - codeBuffer * codeBufferP; - - MALLOCVAR_NOFAIL(codeBufferP); - - codeBufferP->initBits = initBits; - codeBufferP->n_bits = codeBufferP->initBits; - codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits); - codeBufferP->byteBufferP = byteBuffer_create(ofP); - codeBufferP->curAccum = 0; - codeBufferP->curBits = 0; - - return codeBufferP; -} - - - -static void -codeBuffer_destroy(codeBuffer * const codeBufferP) { - - byteBuffer_destroy(codeBufferP->byteBufferP); - - free(codeBufferP); -} - - - -static void -codeBuffer_output(codeBuffer * const codeBufferP, - code_int const code) { -/*---------------------------------------------------------------------------- - Output one GIF code to the file, through the code buffer. - - The code is represented as n_bits bits in the file -- the lower - n_bits bits of 'code'. - - If the code is EOF, flush the code buffer to the file. - - In some cases, change n_bits and recalculate maxcode to go with it. ------------------------------------------------------------------------------*/ - /* - Algorithm: - Maintain a BITS character long buffer (so that 8 codes will - fit in it exactly). Use the VAX insv instruction to insert each - code in turn. When the buffer fills up empty it and start over. - */ - - codeBufferP->curAccum &= masks[codeBufferP->curBits]; + strfree(arg0DirName); + } else + commandVerb = strdup(pamtogifName); - if (codeBufferP->curBits > 0) - codeBufferP->curAccum |= ((long)code << codeBufferP->curBits); + if (cmdline.mapfile) + asprintfN(&mapfileOpt, "-mapfile=%s", cmdline.mapfile); else - codeBufferP->curAccum = code; + mapfileOpt = strdup(""); - codeBufferP->curBits += codeBufferP->n_bits; - - while (codeBufferP->curBits >= 8) { - byteBuffer_out(codeBufferP->byteBufferP, - codeBufferP->curAccum & 0xff); - codeBufferP->curAccum >>= 8; - codeBufferP->curBits -= 8; - } + if (cmdline.transparent) + asprintfN(&transparentOpt, "-transparent=%s", cmdline.transparent); + else + transparentOpt = strdup(""); - if (clear_flg) { - codeBufferP->n_bits = codeBufferP->initBits; - codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits); - clear_flg = 0; - } else if (free_ent > codeBufferP->maxcode) { - /* The next entry is going to be too big for the code size, so - increase it, if possible. - */ - ++codeBufferP->n_bits; - if (codeBufferP->n_bits == BITS) - codeBufferP->maxcode = maxmaxcode; - else - codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits); - } + if (cmdline.comment) + asprintfN(&commentOpt, "-comment=%s", cmdline.comment); + else + commentOpt = strdup(""); + + asprintfN(&retval, "%s - -alphacolor=%s %s %s %s %s %s %s %s", + commandVerb, + cmdline.alphacolor, + cmdline.interlace ? "-interlace" : "", + cmdline.sort ? "-sort" : "", + mapfileOpt, + transparentOpt, + commentOpt, + cmdline.nolzw ? "-nolzw" : "", + cmdline.verbose ? "-verbose" : ""); - if (code == EOFCode) { - /* We're at EOF. Output the possible partial byte in the buffer */ - if (codeBufferP->curBits > 0) { - byteBuffer_out(codeBufferP->byteBufferP, - codeBufferP->curAccum & 0xff); - codeBufferP->curBits = 0; - } - byteBuffer_flush(codeBufferP->byteBufferP); - - byteBuffer_flushFile(codeBufferP->byteBufferP); - } -} - + strfree(mapfileOpt); + strfree(transparentOpt); + strfree(commentOpt); - -static void -cl_hash(long const hsize) { - /* reset code table */ - - long const m1 = -1; - - long * htab_p; - long i; - - htab_p = htab + hsize; /* initial value */ - - i = hsize - 16; - do { /* might use Sys V memset(3) here */ - *(htab_p-16) = m1; - *(htab_p-15) = m1; - *(htab_p-14) = m1; - *(htab_p-13) = m1; - *(htab_p-12) = m1; - *(htab_p-11) = m1; - *(htab_p-10) = m1; - *(htab_p-9) = m1; - *(htab_p-8) = m1; - *(htab_p-7) = m1; - *(htab_p-6) = m1; - *(htab_p-5) = m1; - *(htab_p-4) = m1; - *(htab_p-3) = m1; - *(htab_p-2) = m1; - *(htab_p-1) = m1; - htab_p -= 16; - } while ((i -= 16) >= 0); - - for (i += 16; i > 0; --i) - *--htab_p = m1; + return retval; } static void -cl_block(codeBuffer * const codeBufferP) { -/*---------------------------------------------------------------------------- - Clear out the hash table ------------------------------------------------------------------------------*/ - cl_hash(HSIZE); - free_ent = ClearCode + 2; - clear_flg = 1; +feedPamtogifNoAlpha(struct pam * const inPamP, + FILE * const pipeToPamtogif) { - codeBuffer_output(codeBufferP, (code_int)ClearCode); -} - - - -static void -write_raster_LZW(pixel ** const pixels, - pixval const input_maxval, - gray ** const alpha, - gray const alpha_maxval, - struct cmap * const cmapP, - int const initBits, - FILE * const ofP) { -/*---------------------------------------------------------------------------- - Write the raster to file 'ofP'. - - The raster to write is 'pixels', which has maxval 'input_maxval', - modified by alpha mask 'alpha', which has maxval 'alpha_maxval'. + unsigned int row; + struct pam outPam; + tuple * tuplerow; - Use the colormap 'cmapP' to generate the raster ('pixels' is - composed of RGB samples; the GIF raster is colormap indices). + tuplerow = pnm_allocpamrow(inPamP); - Write the raster using LZW compression. ------------------------------------------------------------------------------*/ - gray const alpha_threshold = (alpha_maxval + 1) / 2; - /* gray levels below this in the alpha mask indicate transparent - pixels in the output image. - */ - code_int ent; - code_int disp; - int hshift; - bool eof; - codeBuffer * codeBufferP; - - codeBufferP = codeBuffer_create(ofP, initBits); + outPam = *inPamP; + outPam.file = pipeToPamtogif; - /* - * Set up the necessary values - */ - offset = 0; - out_count = 0; - clear_flg = 0; - in_count = 1; - - ClearCode = (1 << (initBits - 1)); - EOFCode = ClearCode + 1; - free_ent = ClearCode + 2; - - ent = gifNextPixel(pixels, input_maxval, alpha, alpha_threshold, cmapP); - - { - long fcode; - hshift = 0; - for (fcode = HSIZE; fcode < 65536L; fcode *= 2L) - ++hshift; - hshift = 8 - hshift; /* set hash code range bound */ - } - cl_hash(HSIZE); /* clear hash table */ - - codeBuffer_output(codeBufferP, (code_int)ClearCode); - - eof = FALSE; - while (!eof) { - int gifpixel; - /* The value for the pixel in the GIF image. I.e. the colormap - index. Or -1 to indicate "no more pixels." - */ - gifpixel = gifNextPixel(pixels, - input_maxval, alpha, alpha_threshold, cmapP); - if (gifpixel == EOF) eof = TRUE; - if (!eof) { - long const fcode = (long) (((long) gifpixel << BITS) + ent); - code_int i; - /* xor hashing */ - - ++in_count; - - i = (((code_int)gifpixel << hshift) ^ ent); - - if (HashTabOf (i) == fcode) { - ent = CodeTabOf (i); - continue; - } else if ((long)HashTabOf(i) < 0) /* empty slot */ - goto nomatch; - disp = HSIZE - i; /* secondary hash (after G. Knott) */ - if (i == 0) - disp = 1; - probe: - if ((i -= disp) < 0) - i += HSIZE; - - if (HashTabOf(i) == fcode) { - ent = CodeTabOf(i); - continue; - } - if ((long)HashTabOf(i) > 0) - goto probe; - nomatch: - codeBuffer_output(codeBufferP, (code_int)ent); - ++out_count; - ent = gifpixel; - if (free_ent < maxmaxcode) { - CodeTabOf(i) = free_ent++; /* code -> hashtable */ - HashTabOf(i) = fcode; - } else - cl_block(codeBufferP); - } - } - /* Put out the final code. */ - codeBuffer_output(codeBufferP, (code_int)ent); - ++out_count; - codeBuffer_output(codeBufferP, (code_int) EOFCode); - - codeBuffer_destroy(codeBufferP); -} - + pnm_writepaminit(&outPam); + for (row = 0; row < inPamP->height; ++row) { + pnm_readpamrow(inPamP, tuplerow); -/* Routine to convert variable-width codes into a byte stream */ - -static void -outputUncompressed(struct gif_dest * const dinfoP, - int const code) { - - /* Emit a code of n_bits bits */ - /* Uses cur_accum and cur_bits to reblock into 8-bit bytes */ - dinfoP->cur_accum |= ((int) code) << dinfoP->cur_bits; - dinfoP->cur_bits += dinfoP->n_bits; - - while (dinfoP->cur_bits >= 8) { - byteBuffer_out(dinfoP->byteBufferP, dinfoP->cur_accum & 0xFF); - dinfoP->cur_accum >>= 8; - dinfoP->cur_bits -= 8; + pnm_writepamrow(&outPam, tuplerow); } -} - - -static void -writeRasterUncompressedInit(FILE * const ofP, - struct gif_dest * const dinfoP, - int const i_bits) { -/*---------------------------------------------------------------------------- - Initialize pseudo-compressor ------------------------------------------------------------------------------*/ - - /* init all the state variables */ - dinfoP->n_bits = i_bits; - dinfoP->maxcode = MAXCODE(dinfoP->n_bits); - dinfoP->ClearCode = (1 << (i_bits - 1)); - dinfoP->EOFCode = dinfoP->ClearCode + 1; - dinfoP->code_counter = dinfoP->ClearCode + 2; - /* init output buffering vars */ - dinfoP->byteBufferP = byteBuffer_create(ofP); - dinfoP->cur_accum = 0; - dinfoP->cur_bits = 0; - /* GIF specifies an initial Clear code */ - outputUncompressed(dinfoP, dinfoP->ClearCode); + pnm_freepamrow(tuplerow); } static void -writeRasterUncompressedPixel(struct gif_dest * const dinfoP, - unsigned int const colormapIndex) { -/*---------------------------------------------------------------------------- - "Compress" one pixel value and output it as a symbol. - - 'colormapIndex' must be less than dinfoP->n_bits wide. ------------------------------------------------------------------------------*/ - assert(colormapIndex >> dinfoP->n_bits == 0); - - outputUncompressed(dinfoP, colormapIndex); - /* Issue Clear codes often enough to keep the reader from ratcheting up - * its symbol size. - */ - if (dinfoP->code_counter < dinfoP->maxcode) { - ++dinfoP->code_counter; - } else { - outputUncompressed(dinfoP, dinfoP->ClearCode); - dinfoP->code_counter = dinfoP->ClearCode + 2; /* reset the counter */ - } -} - - - -static void -writeRasterUncompressedTerm(struct gif_dest * const dinfoP) { - - outputUncompressed(dinfoP, dinfoP->EOFCode); - - if (dinfoP->cur_bits > 0) - byteBuffer_out(dinfoP->byteBufferP, dinfoP->cur_accum & 0xFF); - - byteBuffer_flush(dinfoP->byteBufferP); - - byteBuffer_destroy(dinfoP->byteBufferP); -} - - - -static void -writeRasterUncompressed(FILE * const ofP, - pixel ** const pixels, - pixval const inputMaxval, - gray ** const alpha, - gray const alphaMaxval, - struct cmap * const cmapP, - int const initBits) { -/*---------------------------------------------------------------------------- - Write the raster to file 'ofP'. - - Same as write_raster_LZW(), except written out one code per - pixel (plus some clear codes), so no compression. And no use - of the LZW patent. ------------------------------------------------------------------------------*/ - gray const alphaThreshold = (alphaMaxval + 1) / 2; - /* gray levels below this in the alpha mask indicate transparent - pixels in the output image. - */ - bool eof; - - struct gif_dest gifDest; - - writeRasterUncompressedInit(ofP, &gifDest, initBits); - - eof = FALSE; - while (!eof) { - int gifpixel; - /* The value for the pixel in the GIF image. I.e. the colormap - index. Or -1 to indicate "no more pixels." - */ - gifpixel = gifNextPixel(pixels, - inputMaxval, alpha, alphaThreshold, cmapP); - if (gifpixel == EOF) - eof = TRUE; - else - writeRasterUncompressedPixel(&gifDest, gifpixel); - } - writeRasterUncompressedTerm(&gifDest); -} - - - -/****************************************************************************** - * - * GIF Specific routines - * - *****************************************************************************/ - -static void -writeGifHeader(FILE * const fp, - int const Width, int const Height, - int const GInterlace, int const Background, - int const BitsPerPixel, struct cmap * const cmapP, - const char comment[]) { - - int B; - int const Resolution = BitsPerPixel; - int const ColorMapSize = 1 << BitsPerPixel; - - /* Write the Magic header */ - if (cmapP->transparent != -1 || comment) - fwrite("GIF89a", 1, 6, fp); - else - fwrite("GIF87a", 1, 6, fp); - - /* Write out the screen width and height */ - Putword( Width, fp ); - Putword( Height, fp ); - - /* Indicate that there is a global color map */ - B = 0x80; /* Yes, there is a color map */ - - /* OR in the resolution */ - B |= (Resolution - 1) << 4; - - /* OR in the Bits per Pixel */ - B |= (BitsPerPixel - 1); - - /* Write it out */ - fputc( B, fp ); - - /* Write out the Background color */ - fputc( Background, fp ); - - /* Byte of 0's (future expansion) */ - fputc( 0, fp ); - - { - /* Write out the Global Color Map */ - /* Note that the Global Color Map is always a power of two colors - in size, but *cmapP could be smaller than that. So we pad with - black. - */ - int i; - for ( i=0; i < ColorMapSize; ++i ) { - if ( i < cmapP->cmapsize ) { - fputc( cmapP->red[i], fp ); - fputc( cmapP->green[i], fp ); - fputc( cmapP->blue[i], fp ); - } else { - fputc( 0, fp ); - fputc( 0, fp ); - fputc( 0, fp ); - } +copyRasterWithAlpha(struct pam * const inPamP, + struct pam * const alphaPamP, + struct pam * const outPamP, + unsigned int const alphaPlane) { + + tuple * tuplerow; + tuple * alpharow; + unsigned int row; + + inPamP->allocation_depth = outPamP->depth; + + tuplerow = pnm_allocpamrow(inPamP); + alpharow = pnm_allocpamrow(alphaPamP); + + for (row = 0; row < inPamP->height; ++row) { + unsigned int col; + + pnm_readpamrow(inPamP, tuplerow); + pnm_readpamrow(alphaPamP, alpharow); + + for (col = 0; col < inPamP->width; ++col) { + tuplerow[col][alphaPlane] = pnm_scalesample(alpharow[col][0], + alphaPamP->maxval, + inPamP->maxval); } + pnm_writepamrow(outPamP, tuplerow); } - - if ( cmapP->transparent >= 0 ) - write_transparent_color_index_extension(fp, cmapP->transparent); - - if ( comment ) - write_comment_extension(fp, comment); -} - - - -static void -writeImageHeader(FILE * const ofP, - unsigned int const leftOffset, - unsigned int const topOffset, - unsigned int const gWidth, - unsigned int const gHeight, - unsigned int const gInterlace, - unsigned int const initCodeSize) { - - Putword(leftOffset, ofP); - Putword(topOffset, ofP); - Putword(gWidth, ofP); - Putword(gHeight, ofP); - - /* Write out whether or not the image is interlaced */ - if (gInterlace) - fputc(0x40, ofP); - else - fputc(0x00, ofP); - - /* Write out the initial code size */ - fputc(initCodeSize, ofP); -} - - - -static void -gifEncode(FILE * const ofP, - pixel ** const pixels, - pixval const inputMaxval, - int const gWidth, - int const gHeight, - gray ** const alpha, - gray const alphaMaxval, - int const gInterlace, - int const background, - int const bitsPerPixel, - struct cmap * const cmapP, - char const comment[], - bool const nolzw) { - - unsigned int const leftOffset = 0; - unsigned int const topOffset = 0; - - unsigned int const initCodeSize = bitsPerPixel <= 1 ? 2 : bitsPerPixel; - /* The initial code size */ - - writeGifHeader(ofP, gWidth, gHeight, gInterlace, background, - bitsPerPixel, cmapP, comment); - - /* Write an Image separator */ - fputc(',', ofP); - - writeImageHeader(ofP, leftOffset, topOffset, gWidth, gHeight, gInterlace, - initCodeSize); - - initPixelCursor(gWidth, gHeight, gInterlace); - - /* Write the actual raster */ - if (nolzw) - writeRasterUncompressed(ofP, pixels, - inputMaxval, alpha, alphaMaxval, cmapP, - initCodeSize + 1); - else - write_raster_LZW(pixels, - inputMaxval, alpha, alphaMaxval, cmapP, - initCodeSize + 1, ofP); - - /* Write out a zero length data block (to end the series) */ - fputc(0, ofP); - - /* Write the GIF file terminator */ - fputc(';', ofP); -} - - - -static int -compute_transparent(const char colorarg[], - struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - Figure out the color index (index into the colormap) of the color - that is to be transparent in the GIF. - - colorarg[] is the string that specifies the color the user wants to - be transparent (e.g. "red", "#fefefe"). Its maxval is the maxval - of the colormap. 'cmap' is the full colormap except that its - 'transparent' component isn't valid. - - colorarg[] is a standard Netpbm color specification, except that - may have a "=" prefix, which means it specifies a particular exact - color, as opposed to without the "=", which means "the color that - is closest to this and actually in the image." - - Return -1 if colorarg[] specifies an exact color and that color is not - in the image. Also issue an informational message. ------------------------------------------------------------------------------*/ - int retval; - - const char *colorspec; - bool exact; - int presort_colorindex; - pixel transcolor; - - if (colorarg[0] == '=') { - colorspec = &colorarg[1]; - exact = TRUE; - } else { - colorspec = colorarg; - exact = FALSE; - } - - transcolor = ppm_parsecolor((char*)colorspec, cmapP->maxval); - presort_colorindex = ppm_lookupcolor(cmapP->cht, &transcolor); - - if (presort_colorindex != -1) - retval = cmapP->perm[presort_colorindex]; - else if (!exact) - retval = cmapP->perm[closestcolor(transcolor, cmapP->maxval, cmapP)]; - else { - retval = -1; - pm_message( - "Warning: specified transparent color does not occur in image."); - } - return retval; + pnm_freepamrow(alpharow); + pnm_freepamrow(tuplerow); } static void -sort_colormap(int const sort, struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - Sort (in place) the colormap *cmapP. - - Create the perm[] and permi[] mappings for the colormap. - - 'sort' is logical: true means to sort the colormap by red intensity, - then by green intensity, then by blue intensity. False means a null - sort -- leave it in the same order in which we found it. ------------------------------------------------------------------------------*/ - int * const Red = cmapP->red; - int * const Blue = cmapP->blue; - int * const Green = cmapP->green; - int * const perm = cmapP->perm; - int * const permi = cmapP->permi; - unsigned int const cmapsize = cmapP->cmapsize; - - int i; - - for (i=0; i < cmapsize; i++) - permi[i] = i; - - if (sort) { - pm_message("sorting colormap"); - for (i=0; i < cmapsize; i++) { - int j; - for (j=i+1; j < cmapsize; j++) - if (((Red[i]*MAXCMAPSIZE)+Green[i])*MAXCMAPSIZE+Blue[i] > - ((Red[j]*MAXCMAPSIZE)+Green[j])*MAXCMAPSIZE+Blue[j]) { - int tmp; - - tmp=permi[i]; permi[i]=permi[j]; permi[j]=tmp; - tmp=Red[i]; Red[i]=Red[j]; Red[j]=tmp; - tmp=Green[i]; Green[i]=Green[j]; Green[j]=tmp; - tmp=Blue[i]; Blue[i]=Blue[j]; Blue[j]=tmp; } } +feedPamtogifWithAlpha(struct pam * const inPamP, + struct pam * const alphaPamP, + FILE * const pipeToPamtogif) { + + unsigned int alphaPlane; + struct pam outPam; + + if (inPamP->width != alphaPamP->width || + inPamP->height != alphaPamP->height) + pm_error("-alpha image dimensions (%u w x %u h) do not match " + "the input image dimensions (%u x %u)", + alphaPamP->width, alphaPamP->height, + inPamP->width, inPamP->height); + + outPam = *inPamP; + outPam.file = pipeToPamtogif; + outPam.format = PAM_FORMAT; + outPam.plainformat = 0; + + if (inPamP->depth == 1) { + alphaPlane = 1; + strcpy(outPam.tuple_type, "GRAYSCALE_ALPHA"); + } else if (inPamP->depth == 3) { + alphaPlane = 3; + strcpy(outPam.tuple_type, "RGB_ALPHA"); } + outPam.depth = alphaPlane + 1; - for (i=0; i < cmapsize; i++) - perm[permi[i]] = i; -} + pnm_writepaminit(&outPam); - - -static void -normalize_to_255(colorhist_vector const chv, struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - With a PPM color histogram vector 'chv' as input, produce a colormap - of integers 0-255 as output in *cmapP. ------------------------------------------------------------------------------*/ - int i; - pixval const maxval = cmapP->maxval; - - if ( maxval != 255 ) - pm_message( - "maxval is not 255 - automatically rescaling colors" ); - - for ( i = 0; i < cmapP->cmapsize; ++i ) { - if ( maxval == 255 ) { - cmapP->red[i] = (int) PPM_GETR( chv[i].color ); - cmapP->green[i] = (int) PPM_GETG( chv[i].color ); - cmapP->blue[i] = (int) PPM_GETB( chv[i].color ); - } else { - cmapP->red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval; - cmapP->green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval; - cmapP->blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval; - } - } -} - - - -static void add_to_colormap(struct cmap * const cmapP, - const char * const colorspec, - int * const new_indexP) { -/*---------------------------------------------------------------------------- - Add a new entry to the colormap. Make the color that specified by - 'colorspec', and return the index of the new entry as *new_indexP. - - 'colorspec' is a color specification given by the user, e.g. - "red" or "rgb:ff/03.0d". The maxval for this color specification is - that for the colormap *cmapP. ------------------------------------------------------------------------------*/ - pixel const transcolor = ppm_parsecolor((char*)colorspec, cmapP->maxval); - - *new_indexP = cmapP->cmapsize++; - - cmapP->red[*new_indexP] = PPM_GETR(transcolor); - cmapP->green[*new_indexP] = PPM_GETG(transcolor); - cmapP->blue[*new_indexP] = PPM_GETB(transcolor); + copyRasterWithAlpha(inPamP, alphaPamP, &outPam, alphaPlane); } static void -colormap_from_file(const char filespec[], unsigned int const maxcolors, - colorhist_vector * const chvP, pixval * const maxvalP, - int * const colorsP) { -/*---------------------------------------------------------------------------- - Read a colormap from the PPM file filespec[]. Return the color histogram - vector (which is practically a colormap) of the input image as *cvhP - and the maxval for that histogram as *maxvalP. ------------------------------------------------------------------------------*/ - FILE *mapfile; - int cols, rows; - pixel ** colormap_ppm; - - mapfile = pm_openr(filespec); - colormap_ppm = ppm_readppm(mapfile, &cols, &rows, maxvalP); - pm_close(mapfile); +feedPamtogif(struct pam * const inPamP, + const char * const alphaFilespec, + FILE * const pipeToPamtogif) { - /* Figure out the colormap from the <mapfile>. */ - pm_message("computing other colormap..."); - *chvP = - ppm_computecolorhist(colormap_ppm, cols, rows, maxcolors, colorsP); - - ppm_freearray(colormap_ppm, rows); -} - - - -static void -get_alpha(const char * const alpha_filespec, int const cols, int const rows, - gray *** const alphaP, gray * const maxvalP) { - - if (alpha_filespec) { - int alpha_cols, alpha_rows; - *alphaP = pgm_readpgm(pm_openr(alpha_filespec), - &alpha_cols, &alpha_rows, maxvalP); - if (alpha_cols != cols || alpha_rows != rows) - pm_error("alpha mask is not the same dimensions as the " - "input file (alpha is %dW x %dH; image is %dW x %dH)", - alpha_cols, alpha_rows, cols, rows); - } else - *alphaP = NULL; -} - - - -static void -compute_ppm_colormap(pixel ** const pixels, int const cols, int const rows, - int const input_maxval, bool const have_alpha, - const char * const mapfile, colorhist_vector * const chvP, - colorhash_table * const chtP, - pixval * const colormap_maxvalP, - int * const colorsP) { -/*---------------------------------------------------------------------------- - Compute a colormap, PPM style, for the image 'pixels', which is - 'cols' by 'rows' with maxval 'input_maxval'. If 'mapfile' is - non-null, Use the colors in that (PPM) file for the color map - instead of the colors in 'pixels'. - - Return the colormap as *chvP and *chtP. Return the maxval for that - colormap as *colormap_maxvalP. - - While we're at it, count the colors and validate that there aren't - too many. Return the count as *colorsP. In determining if there are - too many, allow one slot for a fake transparency color if 'have_alpha' - is true. If there are too many, issue an error message and abort the - program. ------------------------------------------------------------------------------*/ - unsigned int maxcolors; - /* The most colors we can tolerate in the image. If we have - our own made-up entry in the colormap for transparency, it - isn't included in this count. - */ - - if (have_alpha) - maxcolors = MAXCMAPSIZE - 1; - else - maxcolors = MAXCMAPSIZE; - - if (mapfile) { - /* Read the colormap from a separate colormap file. */ - colormap_from_file(mapfile, maxcolors, chvP, colormap_maxvalP, - colorsP); - } else { - /* Figure out the color map from the input file */ - pm_message("computing colormap..."); - *chvP = ppm_computecolorhist(pixels, cols, rows, maxcolors, colorsP); - *colormap_maxvalP = input_maxval; - } - - if (*chvP == NULL) - pm_error("too many colors - try doing a 'pnmquant %d'", maxcolors); - pm_message("%d colors found", *colorsP); - - /* And make a hash table for fast lookup. */ - *chtP = ppm_colorhisttocolorhash(*chvP, *colorsP); + if (alphaFilespec) { + FILE * afP; + struct pam alphaPam; + afP = pm_openr(alphaFilespec); + pnm_readpaminit(afP, &alphaPam, PAM_STRUCT_SIZE(tuple_type)); + feedPamtogifWithAlpha(inPamP, &alphaPam, pipeToPamtogif); + pm_close(afP); + } else + feedPamtogifNoAlpha(inPamP, pipeToPamtogif); } int -main(int argc, char *argv[]) { +main(int argc, + char * argv[]) { + struct cmdlineInfo cmdline; FILE * ifP; - int rows, cols; - int BitsPerPixel; - pixel ** pixels; /* The input image, in PPM format */ - pixval input_maxval; /* Maxval for 'pixels' */ - gray ** alpha; /* The supplied alpha mask; NULL if none */ - gray alpha_maxval; /* Maxval for 'alpha' */ - - struct cmap cmap; - /* The colormap, with all its accessories */ - colorhist_vector chv; - int fake_transparent; - /* colormap index of the fake transparency color we're using to - implement the alpha mask. Undefined if we're not doing an alpha - mask. - */ + struct pam inPam; + const char * command; + FILE * pipeToPamtogif; + int rc; - ppm_init( &argc, argv ); + pnm_init(&argc, argv); parseCommandLine(argc, argv, &cmdline); - verbose = cmdline.verbose; - - ifP = pm_openr(cmdline.input_filespec); - - pixels = ppm_readppm(ifP, &cols, &rows, &input_maxval); + command = pamtogifCommand(argv[0], cmdline); - pm_close(ifP); - - get_alpha(cmdline.alpha_filespec, cols, rows, &alpha, &alpha_maxval); + if (cmdline.verbose) + pm_message("Executing shell command '%s'", command); + + pipeToPamtogif = popen(command, "w"); - compute_ppm_colormap(pixels, cols, rows, input_maxval, (alpha != NULL), - cmdline.mapfile, - &chv, &cmap.cht, &cmap.maxval, &cmap.cmapsize); + if (pipeToPamtogif == NULL) + pm_error("Shell command '%s', via popen(), failed.", command); - /* Now turn the ppm colormap into the appropriate GIF colormap. */ + ifP = pm_openr(cmdline.input_filespec); + pnm_readpaminit(ifP, &inPam, PAM_STRUCT_SIZE(allocation_depth)); - normalize_to_255(chv, &cmap); + feedPamtogif(&inPam, cmdline.alpha_filespec, pipeToPamtogif); - ppm_freecolorhist(chv); + rc = pclose(pipeToPamtogif); - if (alpha) { - /* Add a fake entry to the end of the colormap for transparency. - Make its color black. - */ - add_to_colormap(&cmap, cmdline.alphacolor, &fake_transparent); - } - sort_colormap(cmdline.sort, &cmap); - - BitsPerPixel = pm_maxvaltobits(cmap.cmapsize-1); - - if (alpha) { - cmap.transparent = cmap.perm[fake_transparent]; - } else { - if (cmdline.transparent) - cmap.transparent = - compute_transparent(cmdline.transparent, &cmap); - else - cmap.transparent = -1; - } - /* All set, let's do it. */ - gifEncode(stdout, pixels, input_maxval, cols, rows, - alpha, alpha_maxval, - cmdline.interlace, 0, BitsPerPixel, &cmap, cmdline.comment, - cmdline.nolzw); + if (rc != 0) + pm_error("Pamtogif process failed. pclose() failed."); - ppm_freearray(pixels, rows); - if (alpha) - pgm_freearray(alpha, rows); + strfree(command); - fclose(stdout); + pm_close(ifP); + pm_close(stdout); return 0; } diff --git a/converter/ppm/ppmtoilbm.c b/converter/ppm/ppmtoilbm.c index 6c04c9be..c0d58edb 100644 --- a/converter/ppm/ppmtoilbm.c +++ b/converter/ppm/ppmtoilbm.c @@ -635,20 +635,9 @@ ppm_to_ham(fp, cols, rows, maxval, colormap, colors, cmapmaxval, hamplanes) static long -#ifdef __STDC__ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, pixval hammaxval, int nPlanes, pixel *colormap, int colors) -#else -do_ham_body(ifP, ofp, cols, rows, maxval, hammaxval, nPlanes, colormap, colors) - FILE *ifP, *ofp; - int cols, rows; - pixval maxval; /* maxval of image color components */ - pixval hammaxval; /* maxval of HAM color changes */ - int nPlanes; - pixel *colormap; - int colors; -#endif { register int col, row, i; rawtype *raw_rowbuf; @@ -876,16 +865,8 @@ ppm_to_deep(fp, cols, rows, maxval, bitspercolor) static long -#if __STDC__ do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, int bitspercolor) -#else -do_deep_body(ifP, ofp, cols, rows, maxval, bitspercolor) - FILE *ifP, *ofp; - int cols, rows; - pixval maxval; - int bitspercolor; -#endif { register int row, col; pixel *pP; @@ -1014,16 +995,8 @@ ppm_to_dcol(fp, cols, rows, maxval, dcol) static long -#if __STDC__ do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, DirectColor *dcol) -#else -do_dcol_body(ifP, ofp, cols, rows, maxval, dcol) - FILE *ifP, *ofp; - int cols, rows; - pixval maxval; - DirectColor *dcol; -#endif { register int row, col; pixel *pP; @@ -1161,18 +1134,8 @@ ppm_to_std(fp, cols, rows, maxval, colormap, colors, cmapmaxval, static long -#if __STDC__ do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, pixel *colormap, int colors, int nPlanes) -#else -do_std_body(ifP, ofp, cols, rows, maxval, colormap, colors, nPlanes) - FILE *ifP, *ofp; - int cols, rows; - pixval maxval; - pixel *colormap; - int colors; - int nPlanes; -#endif { register int row, col, i; pixel *pP; @@ -1783,12 +1746,7 @@ runbyte1(size) /************ other utility functions ************/ static void -#if __STDC__ put_big_short(short s) -#else -put_big_short(s) - short s; -#endif { if ( pm_writebigshort( stdout, s ) == -1 ) pm_error( "write error" ); diff --git a/converter/ppm/ppmtomitsu.c b/converter/ppm/ppmtomitsu.c index 3934ae45..837d9e2b 100644 --- a/converter/ppm/ppmtomitsu.c +++ b/converter/ppm/ppmtomitsu.c @@ -20,362 +20,70 @@ x** - mymalloc() and check_and_rotate() functions for often used ** implied warranty. */ +#include <assert.h> #include <string.h> +#include <stdio.h> #include "pm_c_util.h" -#include "ppm.h" #include "nstring.h" #include "mallocvar.h" +#include "ppm.h" #include "mitsu.h" -#include <stdio.h> - #define HASHSIZE 2048 #define myhash(x) ((PPM_GETR(x)*3 + PPM_GETG(x)*5 + PPM_GETB(x)*7) % HASHSIZE) typedef struct hashinfo { pixel color; long flag; - struct hashinfo *next; + struct hashinfo * next; } hashinfo; -#ifdef __STDC__ -static void lineputinit(int cols, int rows, int sharpness, int enlarge, int - copy, struct mediasize medias); -static void frametransferinit(int cols, int rows, int sharpness, int enlarge, - int copy, struct mediasize medias); -static void lookuptableinit(int sharpness, int enlarge, int copy, - struct mediasize medias); -static void lookuptabledata(int cols, int rows, int enlarge, - struct mediasize medias); -static void check_and_rotate(int cols, int rows, int enlarge, - struct mediasize medias); -#define CONST const -#else /*__STDC__*/ -static int lineputinit(); -static int lookuptableinit(); -static int lookuptabledata(); -static int frametransferinit(); -static int check_and_rotate(); -#define CONST -#endif - #define cmd(arg) fputc((arg), stdout) #define datum(arg) fputc((char)(arg), stdout) #define data(arg,num) fwrite((arg), sizeof(char), (num), stdout) -#ifdef __STDC__ -int main(int argc, char *argv[] ) -#else -int main( argc, argv ) - int argc; - char* argv[]; -#endif - { - FILE *ifp; - /*hashinfo colorhashtable[HASHSIZE];*/ - struct hashinfo *hashrun; - pixel *xP; - int argn; - bool dpi300; - int cols, rows, format, col, row; - int sharpness, enlarge, copy, tiny; - pixval maxval; - struct mediasize medias; - char media[16]; - const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media <a,a4,as,a4s>] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]"; - - ppm_init(&argc, argv); - - dpi300 = FALSE; - argn = 1; - sharpness = 32; - enlarge = 1; - copy = 1; - memset(media, '\0', 16); - tiny = FALSE; - - /* check for flags */ - while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { - if (pm_keymatch(argv[argn], "-sharpness", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1) - pm_usage(usage); - else if (sharpness < 1 || sharpness > 4) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-enlarge", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1) - pm_usage(usage); - else if (enlarge < 1 || enlarge > 3) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-media", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%15s", media) < 1) - pm_usage(usage); - else if (TOUPPER(media[0]) != 'A') - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-copy", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", ©) != 1) - pm_usage(usage); - else if (copy < 1 || copy > 9) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-dpi300", 2)) - dpi300 = TRUE; - else if (pm_keymatch(argv[argn], "-tiny", 2)) - tiny = TRUE; - else - pm_usage(usage); - ++argn; - } - - if (argn < argc) { - ifp = pm_openr(argv[argn]); - ++argn; - } - else - ifp = stdin; - - if (argn != argc) - pm_usage(usage); - - if (TOUPPER(media[0]) == 'A') - switch (TOUPPER(media[1])) { - case 'S': - medias = MSize_AS; - break; - case '4': - if(TOUPPER(media[2]) == 'S') - medias = MSize_A4S; - else { - medias = MSize_A4; - } - break; - default: - medias = MSize_A; - } - else - medias = MSize_User; - if (dpi300) { - medias.maxcols *= 2; - medias.maxrows *= 2; - } +static void +check_and_rotate(int const cols, + int const rows, + int const enlarge, + struct mediasize const medias) { - if (tiny) { - pixel *pixelrow; - char *redrow, *greenrow, *bluerow; - - ppm_readppminit(ifp, &cols, &rows, &maxval, &format); - pixelrow = (pixel *) ppm_allocrow(cols); - MALLOCARRAY_NOFAIL(redrow, cols); - MALLOCARRAY_NOFAIL(greenrow, cols); - MALLOCARRAY_NOFAIL(bluerow, cols); - lineputinit(cols, rows, sharpness, enlarge, copy, medias); - - for ( row = 0; row < rows; ++row ) { - ppm_readppmrow(ifp, pixelrow, cols, maxval, format); - switch(PPM_FORMAT_TYPE(format)) { - /* color */ - case PPM_TYPE: - for (col = 0, xP = pixelrow; col < cols; col++, xP++) { - /* First red. */ - redrow[col] = PPM_GETR(*xP); - /* Then green. */ - greenrow[col] = PPM_GETG(*xP); - /* And blue. */ - bluerow[col] = PPM_GETB(*xP); - } - data(redrow, cols); - data(greenrow, cols); - data(bluerow, cols); - break; - /* grayscale */ - default: - for (col = 0, xP = pixelrow; col < cols; col++, xP++) - bluerow[col] = PPM_GETB(*xP); - data(bluerow, cols); - data(bluerow, cols); - data(bluerow, cols); - break; - } - } - pm_close(ifp); + if (cols > rows) { + ROTATEIMG(DOROTATE); /* rotate image */ + if (enlarge * rows > medias.maxcols || enlarge * cols > medias.maxrows) + pm_error("Image too large, MaxPixels = %u x %u", + medias.maxrows, medias.maxcols); + HPIXELS(cols); + VPIXELS(rows); + HPIXELSOFF((medias.maxcols/enlarge - rows)/2); + VPIXELSOFF((medias.maxrows/enlarge - cols)/2); + pm_message("rotating image for output"); + } else { + ROTATEIMG(DONTROTATE); + if (enlarge * rows > medias.maxrows || enlarge * cols > medias.maxcols) + pm_error("Image too large, MaxPixels = %u x %u", + medias.maxrows, medias.maxcols); + HPIXELS(cols); + VPIXELS(rows); + HPIXELSOFF((medias.maxcols/enlarge - cols)/2); + VPIXELSOFF((medias.maxrows/enlarge - rows)/2); } - else { - pixel **pixelpic; - int colanz, colval; - int i; - colorhist_vector table; - - ppm_readppminit( ifp, &cols, &rows, &maxval, &format ); - pixelpic = ppm_allocarray( cols, rows ); - for (row = 0; row < rows; row++) - ppm_readppmrow( ifp, pixelpic[row], cols, maxval, format ); - pm_close(ifp); - - /* first check wether we can use the lut transfer */ +} - table = ppm_computecolorhist(pixelpic, cols, rows, MAXLUTCOL+1, - &colanz); - if (table != NULL) { - hashinfo *colorhashtable; - MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE); - for (i=0; i<HASHSIZE; i++) { - colorhashtable[i].flag = -1; - colorhashtable[i].next = NULL; - } - /* we can use the lookuptable */ - pm_message("found %d colors - using the lookuptable-method", - colanz); - lookuptableinit(sharpness, enlarge, copy, medias); - switch(PPM_FORMAT_TYPE(format)) { - /* color */ - case PPM_TYPE: - for (colval=0; colval<colanz; colval++) { - cmd('$'); - datum(colval); - datum(PPM_GETR((table[colval]).color)); - datum(PPM_GETG((table[colval]).color)); - datum(PPM_GETB((table[colval]).color)); - - hashrun = &colorhashtable[myhash((table[colval]).color)]; - if (hashrun->flag == -1) { - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - } - else { - while (hashrun->next != NULL) - hashrun = hashrun->next; - MALLOCVAR_NOFAIL(hashrun->next); - hashrun = hashrun->next; - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - hashrun->next = NULL; - } - } - break; - /* other */ - default: - for (colval=0; colval<colanz; colval++) { - cmd('$'); - datum(colval); - datum(PPM_GETB((table[colval]).color)); - datum(PPM_GETB((table[colval]).color)); - datum(PPM_GETB((table[colval]).color)); - - hashrun = &colorhashtable[myhash((table[colval]).color)]; - if (hashrun->flag == -1) { - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - } - else { - while (hashrun->next != NULL) - hashrun = hashrun->next; - MALLOCVAR_NOFAIL(hashrun->next); - hashrun = hashrun->next; - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - hashrun->next = NULL; - } - } - } - lookuptabledata(cols, rows, enlarge, medias); - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) { - hashrun = &colorhashtable[myhash(*xP)]; - while (!PPM_EQUAL((hashrun->color), *xP)) - if (hashrun->next != NULL) - hashrun = hashrun->next; - else { - pm_error("you just found a lethal bug."); - } - datum(hashrun->flag); - } - } - free(colorhashtable); - } - else { - /* $#%@^!& no lut possible, so send the pic as 24bit */ - pm_message("found too many colors for fast lookuptable mode"); - frametransferinit(cols, rows, sharpness, enlarge, copy, medias); - switch(PPM_FORMAT_TYPE(format)) { - /* color */ - case PPM_TYPE: - COLORDES(RED); - DATASTART; /* red coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETR(*xP)); - } - COLORDES(GREEN); - DATASTART; /* green coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETG(*xP)); - } - COLORDES(BLUE); - DATASTART; /* blue coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETB(*xP)); - } - break; - /* grayscale */ - default: - COLORDES(RED); - DATASTART; /* red coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETB(*xP)); - } - COLORDES(GREEN); - DATASTART; /* green coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETB(*xP)); - } - COLORDES(BLUE); - DATASTART; /* blue coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETB(*xP)); - } - } - } - } - PRINTIT; - exit(0); -} - -#ifdef __STDC__ -static void lineputinit(int cols, int rows, - int sharpness, int enlarge, int copy, - struct mediasize medias) -#else /*__STDC__*/ -static int lineputinit(cols, rows, sharpness, enlarge, copy, medias) - int cols, rows; - int sharpness, enlarge, copy; - struct mediasize medias; -#endif /*__STDC__*/ -{ +static void +lineputinit(int const cols, + int const rows, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { ONLINE; CLRMEM; MEDIASIZE(medias); @@ -426,18 +134,16 @@ static int lineputinit(cols, rows, sharpness, enlarge, copy, medias) } check_and_rotate(cols, rows, enlarge, medias); DATASTART; - return; } -#ifdef __STDC__ -static void lookuptableinit(int sharpness, int enlarge, int copy, - struct mediasize medias) -#else /*__STDC__*/ -static int lookuptableinit(sharpness, enlarge, copy, medias) - int sharpness, enlarge, copy; - struct mediasize medias; -#endif /*__STDC__*/ -{ + + +static void +lookuptableinit(int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { + ONLINE; CLRMEM; MEDIASIZE(medias); @@ -486,36 +192,31 @@ static int lookuptableinit(sharpness, enlarge, copy, medias) } LOADLOOKUPTABLE; - return; } -#ifdef __STDC__ -static void lookuptabledata(int cols, int rows, int enlarge, - struct mediasize medias) -#else /*__STDC__*/ -static int lookuptabledata(cols, rows, enlarge, medias) - int rows, cols; - int enlarge; - struct mediasize medias; -#endif /*__STDC__*/ -{ + + +static void +lookuptabledata(int const cols, + int const rows, + int const enlarge, + struct mediasize const medias) { + DONELOOKUPTABLE; check_and_rotate(cols, rows, enlarge, medias); DATASTART; - return; } -#ifdef __STDC__ -static void frametransferinit(int cols, int rows, int sharpness, - int enlarge, int copy, struct mediasize medias) -#else -static int frametransferinit(cols, rows, sharpness, enlarge, copy, medias) - int rows, cols; - int sharpness, enlarge, copy; - struct mediasize medias; -#endif -{ + +static void +frametransferinit(int const cols, + int const rows, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { + ONLINE; CLRMEM; MEDIASIZE(medias); @@ -565,40 +266,411 @@ static int frametransferinit(cols, rows, sharpness, enlarge, copy, medias) SHARPNESS(SP_USER); } check_and_rotate(cols, rows, enlarge, medias); - return; } -#ifdef __STDC__ + +static void +colorRow(colorhist_vector const table, + unsigned int const colanz, + hashinfo * const colorhashtable) { + + unsigned int colval; + for (colval = 0; colval < colanz; ++colval) { + struct hashinfo * const hashchain = + &colorhashtable[myhash((table[colval]).color)]; + + struct hashinfo * hashrun; + + cmd('$'); + datum(colval); + datum(PPM_GETR((table[colval]).color)); + datum(PPM_GETG((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + + hashrun = hashchain; /* start at beginning of chain */ + + if (hashrun->flag == -1) { + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + } else { + while (hashrun->next != NULL) + hashrun = hashrun->next; + MALLOCVAR_NOFAIL(hashrun->next); + hashrun = hashrun->next; + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + hashrun->next = NULL; + } + } +} + + + static void -check_and_rotate(int cols, int rows, int enlarge, struct mediasize medias) -#else -static int -check_and_rotate(cols, rows, enlarge, medias) - int cols, rows, enlarge; +grayRow(colorhist_vector const table, + unsigned int const colanz, + hashinfo * const colorhashtable) { + + unsigned int colval; + for (colval = 0; colval < colanz; ++colval) { + struct hashinfo * const hashchain = + &colorhashtable[myhash((table[colval]).color)]; + struct hashinfo * hashrun; + + cmd('$'); + datum(colval); + datum(PPM_GETB((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + + hashrun = hashchain; /* start at beginning of chain */ + + if (hashrun->flag == -1) { + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + } + else { + while (hashrun->next != NULL) + hashrun = hashrun->next; + MALLOCVAR_NOFAIL(hashrun->next); + hashrun = hashrun->next; + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + hashrun->next = NULL; + } + } +} + + + +static void +useLookupTable(pixel ** const pixels, + colorhist_vector const table, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias, + unsigned int const cols, + unsigned int const rows, + int const format, + unsigned int const colanz) { + + hashinfo * colorhashtable; + + pm_message("found %u colors - using the lookuptable-method", colanz); + + MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE); + { + unsigned int i; + for (i = 0; i < HASHSIZE; ++i) { + colorhashtable[i].flag = -1; + colorhashtable[i].next = NULL; + } + } + + lookuptableinit(sharpness, enlarge, copy, medias); + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: + colorRow(table, colanz, colorhashtable); + break; + default: + grayRow(table, colanz, colorhashtable); + } + lookuptabledata(cols, rows, enlarge, medias); + { + unsigned int row; + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + pixel * const pixrow = pixels[row]; + struct hashinfo * const hashchain = + &colorhashtable[myhash(pixrow[col])]; + struct hashinfo * p; + + p = hashchain; + while (!PPM_EQUAL((p->color), pixrow[col])) { + assert(p->next); + p = p->next; + } + datum(p->flag); + } + } + } + free(colorhashtable); +} + + + +static void +noLookupColor(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows) { + + unsigned int row; + COLORDES(RED); + DATASTART; /* red coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETR(pixrow[col])); + } + COLORDES(GREEN); + DATASTART; /* green coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETG(pixrow[col])); + } + COLORDES(BLUE); + DATASTART; /* blue coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } +} + + + +static void +noLookupGray(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows) { + + unsigned int row; + COLORDES(RED); + DATASTART; /* red coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } + COLORDES(GREEN); + DATASTART; /* green coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } + COLORDES(BLUE); + DATASTART; /* blue coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } +} + + + +static void +useNoLookupTable(pixel ** const pixels, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias, + unsigned int const cols, + unsigned int const rows, + int const format) { + + /* $#%@^!& no lut possible, so send the pic as 24bit */ + + pm_message("found too many colors for fast lookuptable mode"); + + frametransferinit(cols, rows, sharpness, enlarge, copy, medias); + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: + noLookupColor(pixels, cols, rows); + break; + default: + noLookupGray(pixels, cols, rows); + } +} + + + +static void +doTiny(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + int const format, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { + + pixel * pixelrow; + unsigned char * redrow; + unsigned char * grnrow; + unsigned char * blurow; + unsigned int row; + + pixelrow = ppm_allocrow(cols); + MALLOCARRAY_NOFAIL(redrow, cols); + MALLOCARRAY_NOFAIL(grnrow, cols); + MALLOCARRAY_NOFAIL(blurow, cols); + lineputinit(cols, rows, sharpness, enlarge, copy, medias); + + for (row = 0; row < rows; ++row) { + ppm_readppmrow(ifP, pixelrow, cols, maxval, format); + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: { /* color */ + unsigned int col; + for (col = 0; col < cols; ++col) { + redrow[col] = PPM_GETR(pixelrow[col]); + grnrow[col] = PPM_GETG(pixelrow[col]); + blurow[col] = PPM_GETB(pixelrow[col]); + } + data(redrow, cols); + data(grnrow, cols); + data(blurow, cols); + } break; + default: { /* grayscale */ + unsigned int col; + for (col = 0; col < cols; ++col) + blurow[col] = PPM_GETB(pixelrow[col]); + data(blurow, cols); + data(blurow, cols); + data(blurow, cols); + } + } + } +} + + + +int +main(int argc, char * argv[]) { + FILE * ifP; + int argn; + bool dpi300; + int cols, rows, format; + pixval maxval; + int sharpness, enlarge, copy, tiny; struct mediasize medias; -#endif -{ - if (cols > rows) { - ROTATEIMG(DOROTATE); /* rotate image */ - if (enlarge*rows > medias.maxcols || enlarge*cols > medias.maxrows) { - pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols); + char media[16]; + const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media <a,a4,as,a4s>] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]"; + + ppm_init(&argc, argv); + + dpi300 = FALSE; + argn = 1; + sharpness = 32; + enlarge = 1; + copy = 1; + memset(media, '\0', 16); + tiny = FALSE; + + /* check for flags */ + while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { + if (pm_keymatch(argv[argn], "-sharpness", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1) + pm_usage(usage); + else if (sharpness < 1 || sharpness > 4) + pm_usage(usage); } - HPIXELS(cols); - VPIXELS(rows); - HPIXELSOFF((medias.maxcols/enlarge - rows)/2); - VPIXELSOFF((medias.maxrows/enlarge - cols)/2); - pm_message("rotating image for output"); + else if (pm_keymatch(argv[argn], "-enlarge", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1) + pm_usage(usage); + else if (enlarge < 1 || enlarge > 3) + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-media", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%15s", media) < 1) + pm_usage(usage); + else if (TOUPPER(media[0]) != 'A') + pm_usage(usage); } - else { - ROTATEIMG(DONTROTATE); - if (enlarge*rows > medias.maxrows || enlarge*cols > medias.maxcols) { - pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols); + else if (pm_keymatch(argv[argn], "-copy", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", ©) != 1) + pm_usage(usage); + else if (copy < 1 || copy > 9) + pm_usage(usage); } - HPIXELS(cols); - VPIXELS(rows); - HPIXELSOFF((medias.maxcols/enlarge - cols)/2); - VPIXELSOFF((medias.maxrows/enlarge - rows)/2); + else if (pm_keymatch(argv[argn], "-dpi300", 2)) + dpi300 = TRUE; + else if (pm_keymatch(argv[argn], "-tiny", 2)) + tiny = TRUE; + else + pm_usage(usage); + ++argn; } + + if (argn < argc) { + ifP = pm_openr(argv[argn]); + ++argn; + } + else + ifP = stdin; + + if (argn != argc) + pm_usage(usage); + + if (TOUPPER(media[0]) == 'A') + switch (TOUPPER(media[1])) { + case 'S': + medias = MSize_AS; + break; + case '4': + if(TOUPPER(media[2]) == 'S') + medias = MSize_A4S; + else { + medias = MSize_A4; + } + break; + default: + medias = MSize_A; + } + else + medias = MSize_User; + + if (dpi300) { + medias.maxcols *= 2; + medias.maxrows *= 2; + } + + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); + + if (tiny) { + doTiny(ifP, cols, rows, maxval, format, + sharpness, enlarge, copy, medias); + + } else { + pixel ** pixels; + int colanz; + colorhist_vector table; + unsigned int row; + + pixels = ppm_allocarray(cols, rows); + for (row = 0; row < rows; row++) + ppm_readppmrow(ifP, pixels[row], cols, maxval, format); + + /* first check wether we can use the lut transfer */ + + table = ppm_computecolorhist(pixels, cols, rows, MAXLUTCOL+1, + &colanz); + if (table) + useLookupTable(pixels, table, sharpness, enlarge, copy, medias, + cols, rows, format, colanz); + else + useNoLookupTable(pixels, sharpness, enlarge, copy, medias, + cols, rows, format); + ppm_freearray(pixels, rows); + } + PRINTIT; + pm_close(ifP); + return 0; } diff --git a/converter/ppm/ppmtomitsu.test b/converter/ppm/ppmtomitsu.test new file mode 100644 index 00000000..1805838a --- /dev/null +++ b/converter/ppm/ppmtomitsu.test @@ -0,0 +1,12 @@ +echo Test 1. Should print 3110813682 101562 +./ppmtomitsu ../../testimg.ppm | cksum +echo Test 2. Should print 239186803 34399 +pnmquant 100 ../../testimg.ppm | ./ppmtomitsu | cksum +echo Test 3. Should print 816221676 310 +./ppmtomitsu ../../testgrid.pbm | cksum +echo Test 4. Should print 629834989 752 +./ppmtomitsu -tiny ../../testgrid.pbm | cksum +echo Test 5. Should print 3999654426 101549 +./ppmtomitsu -tiny ../../testimg.ppm | cksum +echo Test 2. Should print 3078685526 101549 +pnmquant 100 ../../testimg.ppm | ./ppmtomitsu -tiny | cksum diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile index 6db72ea9..e5ad6c58 100644 --- a/converter/ppm/ppmtompeg/Makefile +++ b/converter/ppm/ppmtompeg/Makefile @@ -39,7 +39,15 @@ endif # MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o -MP_ENCODE_OBJS = iframe.o pframe.o bframe.o psearch.o bsearch.o block.o +MP_ENCODE_OBJS = \ + frames.o \ + iframe.o \ + pframe.o \ + bframe.o \ + psearch.o \ + bsearch.o \ + block.o + MP_OTHER_OBJS = mpeg.o subsample.o param.o rgbtoycc.o \ readframe.o combine.o jrevdct.o frame.o fsize.o frametype.o \ specifics.o rate.o opts.o input.o gethostname.o diff --git a/converter/ppm/ppmtompeg/bframe.c b/converter/ppm/ppmtompeg/bframe.c index 5dfb76d3..1dbc1846 100644 --- a/converter/ppm/ppmtompeg/bframe.c +++ b/converter/ppm/ppmtompeg/bframe.c @@ -84,7 +84,6 @@ static struct bframeStats { *====================*/ extern Block **dct, **dctr, **dctb; -extern dct_data_type **dct_data; #define NO_MOTION 0 #define MOTION 1 #define SKIP 2 /* used in useMotion in dct_data */ diff --git a/converter/ppm/ppmtompeg/bsearch.c b/converter/ppm/ppmtompeg/bsearch.c index 142987f5..70edfef6 100644 --- a/converter/ppm/ppmtompeg/bsearch.c +++ b/converter/ppm/ppmtompeg/bsearch.c @@ -77,6 +77,7 @@ #include "frames.h" #include "motion_search.h" #include "fsize.h" +#include "block.h" /*==================* diff --git a/converter/ppm/ppmtompeg/frames.c b/converter/ppm/ppmtompeg/frames.c new file mode 100644 index 00000000..a0764890 --- /dev/null +++ b/converter/ppm/ppmtompeg/frames.c @@ -0,0 +1,58 @@ +#include "mallocvar.h" +#include "fsize.h" + +#include "frames.h" + + +Block **dct=NULL, **dctr=NULL, **dctb=NULL; +dct_data_type **dct_data; /* used in p/bframe.c */ + + +/*===========================================================================* + * + * AllocDctBlocks + * + * allocate memory for dct blocks + * + * RETURNS: nothing + * + * SIDE EFFECTS: creates dct, dctr, dctb + * + *===========================================================================*/ +void +AllocDctBlocks(void) { + + int dctx, dcty; + int i; + + dctx = Fsize_x / DCTSIZE; + dcty = Fsize_y / DCTSIZE; + + MALLOCARRAY(dct, dcty); + ERRCHK(dct, "malloc"); + for (i = 0; i < dcty; ++i) { + dct[i] = (Block *) malloc(sizeof(Block) * dctx); + ERRCHK(dct[i], "malloc"); + } + + MALLOCARRAY(dct_data, dcty); + ERRCHK(dct_data, "malloc"); + for (i = 0; i < dcty; ++i) { + MALLOCARRAY(dct_data[i], dctx); + ERRCHK(dct[i], "malloc"); + } + + MALLOCARRAY(dctr, dcty/2); + ERRCHK(dctr, "malloc"); + MALLOCARRAY(dctb, dcty/2); + ERRCHK(dctb, "malloc"); + for (i = 0; i < dcty/2; ++i) { + MALLOCARRAY(dctr[i], dctx/2); + ERRCHK(dctr[i], "malloc"); + MALLOCARRAY(dctb[i], dctx/2); + ERRCHK(dctb[i], "malloc"); + } +} + + + diff --git a/converter/ppm/ppmtompeg/headers/bitio.h b/converter/ppm/ppmtompeg/headers/bitio.h index 89e61fbb..a24c21cd 100644 --- a/converter/ppm/ppmtompeg/headers/bitio.h +++ b/converter/ppm/ppmtompeg/headers/bitio.h @@ -60,9 +60,7 @@ #define BIT_IO_INCLUDED -/*==============* - * HEADER FILES * - *==============*/ +#include <stdio.h> #include "general.h" #include "ansi.h" diff --git a/converter/ppm/ppmtompeg/headers/block.h b/converter/ppm/ppmtompeg/headers/block.h index 46050492..22d306a1 100644 --- a/converter/ppm/ppmtompeg/headers/block.h +++ b/converter/ppm/ppmtompeg/headers/block.h @@ -1,3 +1,46 @@ +#ifndef BLOCK_H_INCLUDED + +#include "frame.h" +#include "mtypes.h" + +/* DIFFERENCE FUNCTIONS */ + +int32 +LumBlockMAD(const LumBlock * const currentBlockP, + const LumBlock * const motionBlockP, + int32 const bestSoFar); + +int32 +LumBlockMSE(const LumBlock * const currentBlockP, + const LumBlock * const motionBlockP, + int32 const bestSoFar); + +int32 +LumMotionError(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumAddMotionError(const LumBlock * const currentBlockP, + const LumBlock * const blockSoFarP, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorSubSampled(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int const startY, + int const startX); + void ComputeDiffDCTs(MpegFrame * const current, MpegFrame * const prev, @@ -51,3 +94,4 @@ AddBMotionBlock(Block block, void BlockifyFrame(MpegFrame * const frameP); +#endif diff --git a/converter/ppm/ppmtompeg/headers/frame.h b/converter/ppm/ppmtompeg/headers/frame.h index 6df3d19f..acd74419 100644 --- a/converter/ppm/ppmtompeg/headers/frame.h +++ b/converter/ppm/ppmtompeg/headers/frame.h @@ -130,18 +130,4 @@ Frame_Resize(MpegFrame * const omf, int const outsize_x, int const outsize_y); - -extern void Frame_Free _ANSI_ARGS_((MpegFrame * const frame)); -extern void Frame_Exit _ANSI_ARGS_((void)); -extern void Frame_AllocPPM _ANSI_ARGS_((MpegFrame * frame)); -extern void Frame_AllocYCC _ANSI_ARGS_((MpegFrame * const mf)); -extern void Frame_AllocDecoded _ANSI_ARGS_((MpegFrame * const frame, - boolean const makeReference)); -extern void Frame_AllocHalf _ANSI_ARGS_((MpegFrame * const frame)); -extern void Frame_AllocBlocks _ANSI_ARGS_((MpegFrame * const mf)); -extern void Frame_Resize _ANSI_ARGS_((MpegFrame * const omf, MpegFrame * const mf, - int const insize_x, int const insize_y, - int const outsize_x, int const outsize_y)); - - -#endif /* FRAME_INCLUDED */ +#endif diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h index 14304c48..17820127 100644 --- a/converter/ppm/ppmtompeg/headers/frames.h +++ b/converter/ppm/ppmtompeg/headers/frames.h @@ -16,6 +16,7 @@ #include "ansi.h" #include "mtypes.h" #include "mheaders.h" +#include "iframe.h" #include "frame.h" @@ -86,11 +87,13 @@ typedef struct dct_data_tye_struct { int fmotionX, fmotionY, bmotionX, bmotionY; } dct_data_type; -void EncodeYDC _ANSI_ARGS_((int32 const dc_term, int32 * const pred_term, BitBucket * const bb)); -void -EncodeCDC(int32 const dc_term, - int32 * const pred_term, - BitBucket * const bb); + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern Block **dct, **dctr, **dctb; +extern dct_data_type **dct_data; /*========* @@ -101,63 +104,6 @@ EncodeCDC(int32 const dc_term, #define int_ceil_div(a,b,c) ((b*(c = a/b) < a) ? (c+1) : c) #define int_floor_div(a,b,c) ((b*(c = a/b) > a) ? (c-1) : c) -/* assumes many things: - * block indices are (y,x) - * variables y_dc_pred, cr_dc_pred, and cb_dc_pred - * flat block fb exists - */ -#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) { \ - boolean overflow, overflowChange=FALSE; \ - int overflowValue = 0; \ - do { \ - overflow = Mpost_QuantZigBlock(dct[y][x], fb[0], \ - qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1], \ - qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2], \ - qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3], \ - qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], \ - fb[4], qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], \ - fb[5], qscale, TRUE)==MPOST_OVERFLOW; \ - if ((overflow) && (qscale!=31)) { \ - overflowChange = TRUE; overflowValue++; \ - qscale++; \ - } else overflow = FALSE; \ - } while (overflow); \ - Mhead_GenMBHeader(bb, \ - frameType /* pict_code_type */, mbAI /* addr_incr */, \ - qscale /* q_scale */, \ - 0 /* forw_f_code */, 0 /* back_f_code */, \ - 0 /* horiz_forw_r */, 0 /* vert_forw_r */, \ - 0 /* horiz_back_r */, 0 /* vert_back_r */, \ - 0 /* motion_forw */, 0 /* m_horiz_forw */, \ - 0 /* m_vert_forw */, 0 /* motion_back */, \ - 0 /* m_horiz_back */, 0 /* m_vert_back */, \ - 0 /* mb_pattern */, TRUE /* mb_intra */); \ - \ - /* Y blocks */ \ - EncodeYDC(fb[0][0], &y_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[0], bb); \ - EncodeYDC(fb[1][0], &y_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[1], bb); \ - EncodeYDC(fb[2][0], &y_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[2], bb); \ - EncodeYDC(fb[3][0], &y_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[3], bb); \ - \ - /* CB block */ \ - EncodeCDC(fb[4][0], &cb_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[4], bb); \ - \ - /* CR block */ \ - EncodeCDC(fb[5][0], &cr_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[5], bb); \ - if (overflowChange) qscale -= overflowValue; \ - } - #define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) { \ x1 = (bx1)*DCTSIZE; \ x2 = (bx2)*DCTSIZE; \ @@ -254,6 +200,9 @@ encodeMotionVector(int const x, *===============================*/ void +AllocDctBlocks(void); + +void ComputeBMotionLumBlock(MpegFrame * const prev, MpegFrame * const next, int const by, @@ -271,8 +220,6 @@ BMotionSearch(const LumBlock * const currentBlockP, motion * const motionP, int const oldMode); -void GenIFrame (BitBucket * const bb, - MpegFrame * const mf); void GenPFrame (BitBucket * const bb, MpegFrame * const current, MpegFrame * const prev); @@ -280,11 +227,6 @@ void GenBFrame (BitBucket * const bb, MpegFrame * const curr, MpegFrame * const prev, MpegFrame * const next); -void AllocDctBlocks _ANSI_ARGS_((void )); - - -float -IFrameTotalTime(void); float PFrameTotalTime(void); @@ -293,11 +235,6 @@ float BFrameTotalTime(void); void -ShowIFrameSummary(unsigned int const inputFrameBits, - unsigned int const totalBits, - FILE * const fpointer); - -void ShowPFrameSummary(unsigned int const inputFrameBits, unsigned int const totalBits, FILE * const fpointer); @@ -307,87 +244,6 @@ ShowBFrameSummary(unsigned int const inputFrameBits, unsigned int const totalBits, FILE * const fpointer); -/* DIFFERENCE FUNCTIONS */ - -int32 -LumBlockMAD(const LumBlock * const currentBlockP, - const LumBlock * const motionBlockP, - int32 const bestSoFar); - -int32 -LumBlockMSE(const LumBlock * const currentBlockP, - const LumBlock * const motionBlockP, - int32 const bestSoFar); - -int32 -LumMotionError(const LumBlock * const currentBlockP, - MpegFrame * const prev, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumAddMotionError(const LumBlock * const currentBlockP, - const LumBlock * const blockSoFarP, - MpegFrame * const prev, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorA(const LumBlock * const currentBlockP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorB(const LumBlock * const currentP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorC(const LumBlock * const currentP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorD(const LumBlock * const currentP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorSubSampled(const LumBlock * const currentBlockP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int const startY, - int const startX); - -void -BlockComputeSNR(MpegFrame * const current, - float * const snr, - float * const psnr); - -int32 -time_elapsed(void); - -void -AllocDctBlocks(void); - /*==================* * GLOBAL VARIABLES * *==================*/ @@ -413,7 +269,7 @@ extern int fCodeI,fCodeP,fCodeB; extern boolean forceEncodeLast; extern int TIME_RATE; -#endif /* FRAMES_INCLUDED */ +#endif /* diff --git a/converter/ppm/ppmtompeg/headers/iframe.h b/converter/ppm/ppmtompeg/headers/iframe.h new file mode 100644 index 00000000..c4f77c74 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/iframe.h @@ -0,0 +1,118 @@ +#ifndef IFRAME_H_INCLUDED +#define IFRAME_H_INCLUDED + +#include "frame.h" + +void +SetFCode(void); + +void +SetSlicesPerFrame(int const number); + +void +SetBlocksPerSlice(void); + +void +SetIQScale(int const qI); + +int +GetIQScale(void); + +void +GenIFrame(BitBucket * const bb, + MpegFrame * const current); + +void +ResetIFrameStats(void); + +float +IFrameTotalTime(void); + + +void +ShowIFrameSummary(unsigned int const inputFrameBits, + unsigned int const totalBits, + FILE * const fpointer); + +void +EncodeYDC(int32 const dc_term, + int32 * const pred_term, + BitBucket * const bb); + +void +EncodeCDC(int32 const dc_term, + int32 * const pred_term, + BitBucket * const bb); + +void +BlockComputeSNR(MpegFrame * const current, + float * const snr, + float * const psnr); + +void +WriteDecodedFrame(MpegFrame * const frame); + +void +PrintItoIBitRate(int const numBits, + int const frameNum); + +int32 time_elapsed(void); + +/* assumes many things: + * block indices are (y,x) + * variables y_dc_pred, cr_dc_pred, and cb_dc_pred + * flat block fb exists + */ +#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) { \ + boolean overflow, overflowChange=FALSE; \ + int overflowValue = 0; \ + do { \ + overflow = Mpost_QuantZigBlock(dct[y][x], fb[0], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], \ + fb[4], qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], \ + fb[5], qscale, TRUE)==MPOST_OVERFLOW; \ + if ((overflow) && (qscale!=31)) { \ + overflowChange = TRUE; overflowValue++; \ + qscale++; \ + } else overflow = FALSE; \ + } while (overflow); \ + Mhead_GenMBHeader(bb, \ + frameType /* pict_code_type */, mbAI /* addr_incr */, \ + qscale /* q_scale */, \ + 0 /* forw_f_code */, 0 /* back_f_code */, \ + 0 /* horiz_forw_r */, 0 /* vert_forw_r */, \ + 0 /* horiz_back_r */, 0 /* vert_back_r */, \ + 0 /* motion_forw */, 0 /* m_horiz_forw */, \ + 0 /* m_vert_forw */, 0 /* motion_back */, \ + 0 /* m_horiz_back */, 0 /* m_vert_back */, \ + 0 /* mb_pattern */, TRUE /* mb_intra */); \ + \ + /* Y blocks */ \ + EncodeYDC(fb[0][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[0], bb); \ + EncodeYDC(fb[1][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[1], bb); \ + EncodeYDC(fb[2][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[2], bb); \ + EncodeYDC(fb[3][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[3], bb); \ + \ + /* CB block */ \ + EncodeCDC(fb[4][0], &cb_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[4], bb); \ + \ + /* CR block */ \ + EncodeCDC(fb[5][0], &cr_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[5], bb); \ + if (overflowChange) qscale -= overflowValue; \ + } + +#endif diff --git a/converter/ppm/ppmtompeg/headers/motion_search.h b/converter/ppm/ppmtompeg/headers/motion_search.h index ab83cbca..62f3abab 100644 --- a/converter/ppm/ppmtompeg/headers/motion_search.h +++ b/converter/ppm/ppmtompeg/headers/motion_search.h @@ -100,6 +100,9 @@ PMotionSearch(const LumBlock * const currentBlockP, int const bx, vector * const motionP); +void +MotionSearchPreComputation(MpegFrame * const frameP); + /*==================* * GLOBAL VARIABLES * *==================*/ diff --git a/converter/ppm/ppmtompeg/headers/mpeg.h b/converter/ppm/ppmtompeg/headers/mpeg.h index 23875c2c..56862c42 100644 --- a/converter/ppm/ppmtompeg/headers/mpeg.h +++ b/converter/ppm/ppmtompeg/headers/mpeg.h @@ -90,8 +90,9 @@ void ReadDecodedRefFrame(MpegFrame * const frameP, unsigned int const frameNumber); -extern void WriteDecodedFrame _ANSI_ARGS_((MpegFrame * const frame)); -extern void SetBitRateFileName _ANSI_ARGS_((char *fileName)); +void +SetBitRateFileName(const char * const fileName); + extern void SetFrameRate _ANSI_ARGS_((void)); diff --git a/converter/ppm/ppmtompeg/headers/mproto.h b/converter/ppm/ppmtompeg/headers/mproto.h index c3b0f4b3..d8fefd84 100644 --- a/converter/ppm/ppmtompeg/headers/mproto.h +++ b/converter/ppm/ppmtompeg/headers/mproto.h @@ -74,7 +74,6 @@ #include "bitio.h" -#define DCTSIZE2 DCTSIZE*DCTSIZE typedef short DCTELEM; typedef DCTELEM DCTBLOCK[DCTSIZE2]; @@ -111,9 +110,6 @@ void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width, boolean ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer)); void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); -void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); -boolean PMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, - int by, int bx, int *motionY, int *motionX)); void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); void mp_validate_size _ANSI_ARGS_((int *x, int *y)); void AllocYCC _ANSI_ARGS_((MpegFrame * mf)); @@ -126,7 +122,3 @@ void j_rev_dct _ANSI_ARGS_((DCTBLOCK data )); void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos )); void j_rev_dct _ANSI_ARGS_((DCTBLOCK data )); -/* block.c */ -void BlockToData _ANSI_ARGS_((uint8 **data, Block block, int by, int bx)); -void AddMotionBlock _ANSI_ARGS_((Block block, uint8 **prev, int by, int bx, - int my, int mx)); diff --git a/converter/ppm/ppmtompeg/headers/parallel.h b/converter/ppm/ppmtompeg/headers/parallel.h index 90edd874..cf27ce66 100644 --- a/converter/ppm/ppmtompeg/headers/parallel.h +++ b/converter/ppm/ppmtompeg/headers/parallel.h @@ -87,7 +87,7 @@ void NoteFrameDone(int frameStart, int frameEnd); void -SetIOConvert(boolean const separate); +SetIOConvert(bool const separate); void SetRemoteShell(const char * const shell); diff --git a/converter/ppm/ppmtompeg/headers/prototypes.h b/converter/ppm/ppmtompeg/headers/prototypes.h index a284888f..b421af35 100644 --- a/converter/ppm/ppmtompeg/headers/prototypes.h +++ b/converter/ppm/ppmtompeg/headers/prototypes.h @@ -44,33 +44,26 @@ void ResetBFrameStats _ANSI_ARGS_((void)); void ResetPFrameStats _ANSI_ARGS_((void)); void SetSearchRange (int const pixelsP, int const pixelsB); -void ResetIFrameStats _ANSI_ARGS_((void)); void SetPixelSearch(const char * const searchType); -void SetIQScale _ANSI_ARGS_((int const qI)); void SetPQScale _ANSI_ARGS_((int qP)); void SetBQScale _ANSI_ARGS_((int qB)); -float EstimateSecondsPerIFrame _ANSI_ARGS_((void)); float EstimateSecondsPerPFrame _ANSI_ARGS_((void)); float EstimateSecondsPerBFrame _ANSI_ARGS_((void)); void SetGOPSize _ANSI_ARGS_((int size)); void SetStatFileName(const char * const fileName); -void SetSlicesPerFrame _ANSI_ARGS_((int const number)); -void SetBlocksPerSlice _ANSI_ARGS_((void)); void DCTFrame _ANSI_ARGS_((MpegFrame * mf)); void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); -void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame * const frame)); +void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); void mp_validate_size _ANSI_ARGS_((int *x, int *y)); -extern void SetFCode _ANSI_ARGS_((void)); - /* psearch.c */ void ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer)); diff --git a/converter/ppm/ppmtompeg/headers/subsample.h b/converter/ppm/ppmtompeg/headers/subsample.h new file mode 100644 index 00000000..deedf251 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/subsample.h @@ -0,0 +1,39 @@ +#ifndef SUBSAMPLE_H_INCLUDED +#define SUBSAMPLE_H_INCLUDED + +#include "frame.h" +#include "mtypes.h" + +int32 +LumMotionErrorA(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorB(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorC(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorD(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +#endif diff --git a/converter/ppm/ppmtompeg/iframe.c b/converter/ppm/ppmtompeg/iframe.c index f4d7665a..c6735505 100644 --- a/converter/ppm/ppmtompeg/iframe.c +++ b/converter/ppm/ppmtompeg/iframe.c @@ -11,10 +11,9 @@ * GetIQScale * * ResetIFrameStats * * ShowIFrameSummary * - * EstimateSecondsPerIFrame * * EncodeYDC * * EncodeCDC * - * time_elapsed * + * time_elapsed * * * *===========================================================================*/ @@ -67,6 +66,8 @@ #include "specifics.h" #include "opts.h" +#include "iframe.h" + /*==================* * STATIC VARIABLES * *==================*/ @@ -128,24 +129,11 @@ int fCodeI, fCodeP, fCodeB; boolean printSNR = FALSE; boolean printMSE = FALSE; boolean decodeRefFrames = FALSE; -Block **dct=NULL, **dctr=NULL, **dctb=NULL; -dct_data_type **dct_data; /* used in p/bframe.c */ int TIME_RATE; -/*=====================* - * EXPORTED PROCEDURES * - *=====================*/ -extern void PrintItoIBitRate _ANSI_ARGS_((int const numBits, int const frameNum)); - -/*===============================* - * INTERNAL PROCEDURE prototypes * - *===============================*/ -void AllocDctBlocks(void ); -int SetFCodeHelper (int const sr); -void CalcDistortion (MpegFrame * const current, int const y, int const x); -int +static int SetFCodeHelper(int const SR) { int range,fCode; @@ -296,6 +284,68 @@ GetIQScale(void) { +static void +CalcDistortion(MpegFrame * const current, + int const y, + int const x) { + + int qscale, distort=0; + Block decblk; + FlatBlock fblk; + int datarate = 0; + + for (qscale = 1; qscale < 32; qscale ++) { + distort = 0; + datarate = 0; + Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y][x], decblk); + + Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y][x+1], decblk); + + Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y+1][x], decblk); + + Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y+1][x+1], decblk); + + Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->cb_blocks[y>>1][x>>1], decblk); + + Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk); + + if (!collect_distortion_detailed) { + fprintf(distortion_fp, "\t%d\n", distort); + } else if (collect_distortion_detailed == 1) { + fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate); + } else { + fprintf(fp_table_rate[qscale-1], "%d\n", datarate); + fprintf(fp_table_dist[qscale-1], "%d\n", distort); + } + } +} + + + /*===========================================================================* * * GenIFrame @@ -618,24 +668,6 @@ ShowIFrameSummary(unsigned int const inputFrameBits, /*===========================================================================* * - * EstimateSecondsPerIFrame - * - * estimates the number of seconds required per I-frame - * - * RETURNS: seconds (floating point value) - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -float -EstimateSecondsPerIFrame() -{ - return (float)totalTime/((float)TIME_RATE*(float)numFrames); -} - - -/*===========================================================================* - * * EncodeYDC * * Encode the DC portion of a DCT of a luminance block @@ -926,53 +958,6 @@ PrintItoIBitRate(int const numBits, -/*===========================================================================* - * - * AllocDctBlocks - * - * allocate memory for dct blocks - * - * RETURNS: nothing - * - * SIDE EFFECTS: creates dct, dctr, dctb - * - *===========================================================================*/ -void -AllocDctBlocks(void) { - int dctx, dcty; - int i; - - dctx = Fsize_x / DCTSIZE; - dcty = Fsize_y / DCTSIZE; - - dct = (Block **) malloc(sizeof(Block *) * dcty); - ERRCHK(dct, "malloc"); - for (i = 0; i < dcty; i++) { - dct[i] = (Block *) malloc(sizeof(Block) * dctx); - ERRCHK(dct[i], "malloc"); - } - - dct_data = (dct_data_type **) malloc(sizeof(dct_data_type *) * dcty); - ERRCHK(dct_data, "malloc"); - for (i = 0; i < dcty; i++) { - dct_data[i] = (dct_data_type *) malloc(sizeof(dct_data_type) * dctx); - ERRCHK(dct[i], "malloc"); - } - - dctr = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); - dctb = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); - ERRCHK(dctr, "malloc"); - ERRCHK(dctb, "malloc"); - for (i = 0; i < (dcty >> 1); i++) { - dctr[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); - dctb[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); - ERRCHK(dctr[i], "malloc"); - ERRCHK(dctb[i], "malloc"); - } -} - - - /*======================================================================* * * time_elapsed @@ -997,66 +982,4 @@ int32 time_elapsed(void) { -void -CalcDistortion(MpegFrame * const current, - int const y, - int const x) { - - int qscale, distort=0; - Block decblk; - FlatBlock fblk; - int datarate = 0; - - for (qscale = 1; qscale < 32; qscale ++) { - distort = 0; - datarate = 0; - Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->y_blocks[y][x], decblk); - - Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->y_blocks[y][x+1], decblk); - - Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->y_blocks[y+1][x], decblk); - - Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->y_blocks[y+1][x+1], decblk); - - Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->cb_blocks[y>>1][x>>1], decblk); - - Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk); - - if (!collect_distortion_detailed) { - fprintf(distortion_fp, "\t%d\n", distort); - } else if (collect_distortion_detailed == 1) { - fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate); - } else { - fprintf(fp_table_rate[qscale-1], "%d\n", datarate); - fprintf(fp_table_dist[qscale-1], "%d\n", distort); - } - } -} - - - diff --git a/converter/ppm/ppmtompeg/jpeg.c b/converter/ppm/ppmtompeg/jpeg.c index 3aad6364..a6e1eced 100644 --- a/converter/ppm/ppmtompeg/jpeg.c +++ b/converter/ppm/ppmtompeg/jpeg.c @@ -15,6 +15,7 @@ * HEADER FILES * *==============*/ #define _XOPEN_SOURCE /* Make sure stdio.h contains fileno() */ +#include <unistd.h> #include <stdio.h> #include "all.h" /* With the lossless jpeg patch applied to the Jpeg library diff --git a/converter/ppm/ppmtompeg/mheaders.c b/converter/ppm/ppmtompeg/mheaders.c index 8a51c089..4cfe49ac 100644 --- a/converter/ppm/ppmtompeg/mheaders.c +++ b/converter/ppm/ppmtompeg/mheaders.c @@ -278,24 +278,350 @@ const double VidRateNum[9]={1.0, 23.976, 24.0, 25.0, 29.97, 30.0, 50.0 ,59.94, 60.0}; -/*===============================* - * INTERNAL PROCEDURE prototypes * - *===============================*/ - -static void GenMBAddrIncr _ANSI_ARGS_((BitBucket *bb, uint32 addr_incr)); -static void GenPictHead _ANSI_ARGS_((BitBucket *bb, uint32 temp_ref, - uint32 code_type, uint32 vbv_delay, - int32 full_pel_forw_flag, uint32 forw_f_code, - int32 full_pel_back_flag, uint32 back_f_code, - uint8 *extra_info, uint32 extra_info_size, - uint8 *ext_data, uint32 ext_data_size, - uint8 *user_data, uint32 user_data_size)); -static void GenMBType _ANSI_ARGS_((BitBucket *bb, uint32 pict_code_type, - uint32 mb_quant, uint32 motion_forw, uint32 motion_back, - uint32 mb_pattern, uint32 mb_intra)); -static void GenMotionCode _ANSI_ARGS_((BitBucket * const bb, int32 const vector)); -static void GenBlockPattern _ANSI_ARGS_((BitBucket *bb, - uint32 mb_pattern)); +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * GenMBType + * + * generate macroblock type with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, + mb_pattern, mb_intra) + BitBucket *bbPtr; + uint32 pict_code_type; + uint32 mb_quant; + uint32 motion_forw; + uint32 motion_back; + uint32 mb_pattern; + uint32 mb_intra; +{ + int code; + + switch (pict_code_type) { + case 1: + if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) { + perror("Illegal parameters for macroblock type."); + exit(-1); + } + if (mb_quant) { + Bitio_Write(bbPtr, 0x1, 2); + } else { + Bitio_Write(bbPtr, 0x1, 1); + } + break; + + case 2: + code = 0; + if (mb_quant) { + code += 16; + } + if (motion_forw) { + code += 8; + } + if (motion_back) { + code += 4; + } + if (mb_pattern) { + code += 2; + } + if (mb_intra) { + code += 1; + } + + switch (code) { + case 1: + Bitio_Write(bbPtr, 0x3, 5); + break; + case 2: + Bitio_Write(bbPtr, 0x1, 2); + break; + case 8: + Bitio_Write(bbPtr, 0x1, 3); + break; + case 10: + Bitio_Write(bbPtr, 0x1, 1); + break; + case 17: + Bitio_Write(bbPtr, 0x1, 6); + break; + case 18: + Bitio_Write(bbPtr, 0x1, 5); + break; + case 26: + Bitio_Write(bbPtr, 0x2, 5); + break; + default: + perror("Illegal parameters for macroblock type."); + exit(-1); + break; + } + break; + + case 3: + code = 0; + if (mb_quant) { + code += 16; + } + if (motion_forw) { + code += 8; + } + if (motion_back) { + code += 4; + } + if (mb_pattern) { + code += 2; + } + if (mb_intra) { + code += 1; + } + + switch (code) { + case 12: + Bitio_Write(bbPtr, 0x2, 2); + break; + case 14: + Bitio_Write(bbPtr, 0x3, 2); + break; + case 4: + Bitio_Write(bbPtr, 0x2, 3); + break; + case 6: + Bitio_Write(bbPtr, 0x3, 3); + break; + case 8: + Bitio_Write(bbPtr, 0x2, 4); + break; + case 10: + Bitio_Write(bbPtr, 0x3, 4); + break; + case 1: + Bitio_Write(bbPtr, 0x3, 5); + break; + case 30: + Bitio_Write(bbPtr, 0x2, 5); + break; + case 26: + Bitio_Write(bbPtr, 0x3, 6); + break; + case 22: + Bitio_Write(bbPtr, 0x2, 6); + break; + case 17: + Bitio_Write(bbPtr, 0x1, 6); + break; + default: + perror("Illegal parameters for macroblock type."); + exit(-1); + break; + } + break; + } +} + + +/*===========================================================================* + * + * GenMotionCode + * + * generate motion vector output with given value + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMotionCode(BitBucket * const bbPtr, + int32 const vector) { + + uint32 code, num; + + if ((vector < -16) || (vector > 16)) { + perror("Motion vector out of range."); + fprintf(stderr, "Motion vector out of range: vector = %d\n", vector); + exit(-1); + } + code = mbMotionVectorTable[vector + 16][0]; + num = mbMotionVectorTable[vector + 16][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenBlockPattern + * + * generate macroblock pattern output + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenBlockPattern(bbPtr, mb_pattern) + BitBucket *bbPtr; + uint32 mb_pattern; +{ + uint32 code, num; + + code = mbPatTable[mb_pattern][0]; + num = mbPatTable[mb_pattern][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenMBAddrIncr + * + * generate macroblock address increment output + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMBAddrIncr(bbPtr, addr_incr) + BitBucket *bbPtr; + uint32 addr_incr; +{ + uint32 code; + uint32 num; + + code = mbAddrIncrTable[addr_incr][0]; + num = mbAddrIncrTable[addr_incr][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenPictHead + * + * generate picture header with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag, + forw_f_code, full_pel_back_flag, back_f_code, extra_info, + extra_info_size, ext_data, ext_data_size, user_data, + user_data_size) + BitBucket *bbPtr; + uint32 temp_ref; + uint32 code_type; + uint32 vbv_delay; + int32 full_pel_forw_flag; + uint32 forw_f_code; + int32 full_pel_back_flag; + uint32 back_f_code; + uint8 *extra_info; + uint32 extra_info_size; + uint8 *ext_data; + uint32 ext_data_size; + uint8 *user_data; + uint32 user_data_size; +{ + /* Write picture start code. */ + Bitio_Write(bbPtr, PICT_START_CODE, 32); + + /* Temp reference. */ + Bitio_Write(bbPtr, temp_ref, 10); + + /* Code_type. */ + if (code_type == 0) + code_type = 1; + + Bitio_Write(bbPtr, code_type, 3); + + /* vbv_delay. */ + vbv_delay = 0xffff; /* see page 36 (section 2.4.3.4) */ + Bitio_Write(bbPtr, vbv_delay, 16); + + if ((code_type == 2) || (code_type == 3)) { + + /* Full pel forw flag. */ + + if (full_pel_forw_flag) + Bitio_Write(bbPtr, 0x01, 1); + else + Bitio_Write(bbPtr, 0x00, 1); + + /* Forw f code. */ + + Bitio_Write(bbPtr, forw_f_code, 3); + } + if (code_type == 3) { + + /* Full pel back flag. */ + + if (full_pel_back_flag) + Bitio_Write(bbPtr, 0x01, 1); + else + Bitio_Write(bbPtr, 0x00, 1); + + /* Back f code. */ + + Bitio_Write(bbPtr, back_f_code, 3); + } + /* Extra bit picture info. */ + + if (extra_info != NULL) { + unsigned int i; + for (i = 0; i < extra_info_size; ++i) { + Bitio_Write(bbPtr, 0x01, 1); + Bitio_Write(bbPtr, extra_info[i], 8); + } + } + Bitio_Write(bbPtr, 0x00, 1); + + /* next start code */ + Bitio_BytePad(bbPtr); + + /* Write ext data if present. */ + + if (ext_data != NULL) { + unsigned int i; + + Bitio_Write(bbPtr, EXT_START_CODE, 32); + + for (i = 0; i < ext_data_size; ++i) + Bitio_Write(bbPtr, ext_data[i], 8); + Bitio_BytePad(bbPtr); + } + /* Write user data if present. */ + if (user_data != NULL) { + unsigned int i; + Bitio_Write(bbPtr, USER_START_CODE, 32); + + for (i = 0; i < user_data_size; ++i) + Bitio_Write(bbPtr, user_data[i], 8); + + Bitio_BytePad(bbPtr); + } +} /*=====================* @@ -767,7 +1093,8 @@ if ( addr_incr != 1 ) } /* Generate mb type code. */ - GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, mb_pattern, mb_intra); + GenMBType(bbPtr, pict_code_type, mb_quant, + motion_forw, motion_back, mb_pattern, mb_intra); /* MB quant. */ if (mb_quant) { @@ -831,353 +1158,6 @@ if ( addr_incr != 1 ) } -/*=====================* - * INTERNAL PROCEDURES * - *=====================*/ - -/*===========================================================================* - * - * GenMBType - * - * generate macroblock type with given attributes - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, - mb_pattern, mb_intra) - BitBucket *bbPtr; - uint32 pict_code_type; - uint32 mb_quant; - uint32 motion_forw; - uint32 motion_back; - uint32 mb_pattern; - uint32 mb_intra; -{ - int code; - - switch (pict_code_type) { - case 1: - if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) { - perror("Illegal parameters for macroblock type."); - exit(-1); - } - if (mb_quant) { - Bitio_Write(bbPtr, 0x1, 2); - } else { - Bitio_Write(bbPtr, 0x1, 1); - } - break; - - case 2: - code = 0; - if (mb_quant) { - code += 16; - } - if (motion_forw) { - code += 8; - } - if (motion_back) { - code += 4; - } - if (mb_pattern) { - code += 2; - } - if (mb_intra) { - code += 1; - } - - switch (code) { - case 1: - Bitio_Write(bbPtr, 0x3, 5); - break; - case 2: - Bitio_Write(bbPtr, 0x1, 2); - break; - case 8: - Bitio_Write(bbPtr, 0x1, 3); - break; - case 10: - Bitio_Write(bbPtr, 0x1, 1); - break; - case 17: - Bitio_Write(bbPtr, 0x1, 6); - break; - case 18: - Bitio_Write(bbPtr, 0x1, 5); - break; - case 26: - Bitio_Write(bbPtr, 0x2, 5); - break; - default: - perror("Illegal parameters for macroblock type."); - exit(-1); - break; - } - break; - - case 3: - code = 0; - if (mb_quant) { - code += 16; - } - if (motion_forw) { - code += 8; - } - if (motion_back) { - code += 4; - } - if (mb_pattern) { - code += 2; - } - if (mb_intra) { - code += 1; - } - - switch (code) { - case 12: - Bitio_Write(bbPtr, 0x2, 2); - break; - case 14: - Bitio_Write(bbPtr, 0x3, 2); - break; - case 4: - Bitio_Write(bbPtr, 0x2, 3); - break; - case 6: - Bitio_Write(bbPtr, 0x3, 3); - break; - case 8: - Bitio_Write(bbPtr, 0x2, 4); - break; - case 10: - Bitio_Write(bbPtr, 0x3, 4); - break; - case 1: - Bitio_Write(bbPtr, 0x3, 5); - break; - case 30: - Bitio_Write(bbPtr, 0x2, 5); - break; - case 26: - Bitio_Write(bbPtr, 0x3, 6); - break; - case 22: - Bitio_Write(bbPtr, 0x2, 6); - break; - case 17: - Bitio_Write(bbPtr, 0x1, 6); - break; - default: - perror("Illegal parameters for macroblock type."); - exit(-1); - break; - } - break; - } -} - - -/*===========================================================================* - * - * GenMotionCode - * - * generate motion vector output with given value - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenMotionCode(BitBucket * const bbPtr, - int32 const vector) { - - uint32 code, num; - - if ((vector < -16) || (vector > 16)) { - perror("Motion vector out of range."); - fprintf(stderr, "Motion vector out of range: vector = %d\n", vector); - exit(-1); - } - code = mbMotionVectorTable[vector + 16][0]; - num = mbMotionVectorTable[vector + 16][1]; - - Bitio_Write(bbPtr, code, num); -} - - -/*===========================================================================* - * - * GenBlockPattern - * - * generate macroblock pattern output - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenBlockPattern(bbPtr, mb_pattern) - BitBucket *bbPtr; - uint32 mb_pattern; -{ - uint32 code, num; - - code = mbPatTable[mb_pattern][0]; - num = mbPatTable[mb_pattern][1]; - - Bitio_Write(bbPtr, code, num); -} - - -/*===========================================================================* - * - * GenMBAddrIncr - * - * generate macroblock address increment output - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenMBAddrIncr(bbPtr, addr_incr) - BitBucket *bbPtr; - uint32 addr_incr; -{ - uint32 code; - uint32 num; - - code = mbAddrIncrTable[addr_incr][0]; - num = mbAddrIncrTable[addr_incr][1]; - - Bitio_Write(bbPtr, code, num); -} - - -/*===========================================================================* - * - * GenPictHead - * - * generate picture header with given attributes - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag, - forw_f_code, full_pel_back_flag, back_f_code, extra_info, - extra_info_size, ext_data, ext_data_size, user_data, - user_data_size) - BitBucket *bbPtr; - uint32 temp_ref; - uint32 code_type; - uint32 vbv_delay; - int32 full_pel_forw_flag; - uint32 forw_f_code; - int32 full_pel_back_flag; - uint32 back_f_code; - uint8 *extra_info; - uint32 extra_info_size; - uint8 *ext_data; - uint32 ext_data_size; - uint8 *user_data; - uint32 user_data_size; -{ - int i; - - /* Write picture start code. */ - Bitio_Write(bbPtr, PICT_START_CODE, 32); - - /* Temp reference. */ - Bitio_Write(bbPtr, temp_ref, 10); - - /* Code_type. */ - if (code_type == 0) { - code_type = 1; - } - Bitio_Write(bbPtr, code_type, 3); - - /* vbv_delay. */ - vbv_delay = 0xffff; /* see page 36 (section 2.4.3.4) */ - Bitio_Write(bbPtr, vbv_delay, 16); - - if ((code_type == 2) || (code_type == 3)) { - - /* Full pel forw flag. */ - - if (full_pel_forw_flag) { - Bitio_Write(bbPtr, 0x01, 1); - } else { - Bitio_Write(bbPtr, 0x00, 1); - } - - /* Forw f code. */ - - Bitio_Write(bbPtr, forw_f_code, 3); - } - if (code_type == 3) { - - /* Full pel back flag. */ - - if (full_pel_back_flag) { - Bitio_Write(bbPtr, 0x01, 1); - } else { - Bitio_Write(bbPtr, 0x00, 1); - } - - /* Back f code. */ - - Bitio_Write(bbPtr, back_f_code, 3); - } - /* Extra bit picture info. */ - - if (extra_info != NULL) { - for (i = 0; i < extra_info_size; i++) { - Bitio_Write(bbPtr, 0x01, 1); - Bitio_Write(bbPtr, extra_info[i], 8); - } - } - Bitio_Write(bbPtr, 0x00, 1); - - /* next start code */ - Bitio_BytePad(bbPtr); - - /* Write ext data if present. */ - - if (ext_data != NULL) { - Bitio_Write(bbPtr, EXT_START_CODE, 32); - - for (i = 0; i < ext_data_size; i++) { - Bitio_Write(bbPtr, ext_data[i], 8); - } - Bitio_BytePad(bbPtr); - } - /* Write user data if present. */ - if (user_data != NULL) { - Bitio_Write(bbPtr, USER_START_CODE, 32); - - for (i = 0; i < user_data_size; i++) { - Bitio_Write(bbPtr, user_data[i], 8); - } - Bitio_BytePad(bbPtr); - } -} - - #ifdef UNUSED_PROCEDURES /* GenMBEnd only used for `D` pictures. Shouldn't really ever be called. */ diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c index fafbb97a..de662e88 100644 --- a/converter/ppm/ppmtompeg/mpeg.c +++ b/converter/ppm/ppmtompeg/mpeg.c @@ -276,9 +276,8 @@ SetReferenceFrameType(const char * const type) { void -SetBitRateFileName(fileName) - char *fileName; -{ +SetBitRateFileName(const char * const fileName) { + strcpy(bitRateFileName, fileName); } @@ -318,7 +317,7 @@ finishFrameOutput(MpegFrame * const frameP, static void outputIFrame(MpegFrame * const frameP, - BitBucket * const bb, + BitBucket * const bbP, int const realStart, int const realEnd, MpegFrame * const pastRefFrameP, @@ -326,7 +325,7 @@ outputIFrame(MpegFrame * const frameP, /* only start a new GOP with I */ /* don't start GOP if only doing frames */ - if ((!separateFiles) && (currentGOP >= gopSize)) { + if (!separateFiles && currentGOP >= gopSize) { boolean const closed = (totalFramesSent == frameP->id || pastRefFrameP == NULL); @@ -344,7 +343,7 @@ outputIFrame(MpegFrame * const frameP, } Mhead_GenSequenceHeader( - bb, Fsize_x, Fsize_y, + bbP, Fsize_x, Fsize_y, /* pratio */ aspectRatio, /* pict_rate */ frameRate, /* bit_rate */ bit_rate, /* buf_size */ buf_size, /* c_param_flag */ 1, @@ -359,7 +358,7 @@ outputIFrame(MpegFrame * const frameP, closed ? "YES" : "NO", frameP->id); ++num_gop; - Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0, + Mhead_GenGOPHeader(bbP, /* drop_frame_flag */ 0, tc_hrs, tc_min, tc_sec, tc_pict, closed, /* broken_link */ 0, /* ext_data */ NULL, /* ext_data_size */ 0, @@ -368,16 +367,16 @@ outputIFrame(MpegFrame * const frameP, if (pastRefFrameP == NULL) SetGOPStartTime(0); else - SetGOPStartTime(pastRefFrameP->id+1); + SetGOPStartTime(pastRefFrameP->id + 1); } - if ((frameP->id >= realStart) && (frameP->id <= realEnd)) - GenIFrame(bb, frameP); + if (frameP->id >= realStart && frameP->id <= realEnd) + GenIFrame(bbP, frameP); - numI--; + --numI; timeMask &= 0x6; - currentGOP++; + ++currentGOP; IncrementTCTime(); } @@ -393,10 +392,10 @@ outputPFrame(MpegFrame * const frameP, if ((frameP->id >= realStart) && (frameP->id <= realEnd)) GenPFrame(bbP, frameP, pastRefFrameP); - numP--; + --numP; timeMask &= 0x5; - currentGOP++; + ++currentGOP; IncrementTCTime(); } @@ -498,6 +497,9 @@ processBFrames(MpegFrame * const pastRefFrameP, But do only those B frames whose frame numbers are within the range 'realStart' through 'realEnd'. + + Output the frames to the output stream 'wholeStreamBbP'. If NULL, + output each frame to its own individual file instead. -----------------------------------------------------------------------------*/ boolean const separateFiles = (wholeStreamBbP == NULL); unsigned int const firstBFrameNum = pastRefFrameP->id + 1; @@ -551,7 +553,7 @@ processBFrames(MpegFrame * const pastRefFrameP, static void processRefFrame(MpegFrame * const frameP, - BitBucket * const bb_arg, + BitBucket * const wholeStreamBbP, int const realStart, int const realEnd, MpegFrame * const pastRefFrameP, @@ -564,26 +566,28 @@ processRefFrame(MpegFrame * const frameP, But only if its frame number is within the range 'realStart' through 'realEnd'. + + Output the frame to the output stream 'wholeStreamBbP'. If NULL, + output it to its own individual file instead. -----------------------------------------------------------------------------*/ if (frameP->id >= realStart && frameP->id <= realEnd) { - boolean separateFiles; - BitBucket * bb; + bool const separateFiles = (wholeStreamBbP == NULL); - separateFiles = (bb_arg == NULL); + BitBucket * bbP; - if ( separateFiles ) - bb = bitioNew(outputFileName, frameP->id, remoteIO); + if (separateFiles) + bbP = bitioNew(outputFileName, frameP->id, remoteIO); else - bb = bb_arg; + bbP = wholeStreamBbP; /* first, output this reference frame */ switch (frameP->type) { case TYPE_IFRAME: - outputIFrame(frameP, bb, realStart, realEnd, pastRefFrameP, + outputIFrame(frameP, bbP, realStart, realEnd, pastRefFrameP, separateFiles); break; case TYPE_PFRAME: - outputPFrame(frameP, bb, realStart, realEnd, pastRefFrameP); + outputPFrame(frameP, bbP, realStart, realEnd, pastRefFrameP); ShowRemainingTime(childProcess); break; default: @@ -593,7 +597,7 @@ processRefFrame(MpegFrame * const frameP, ++(*framesOutputP); - finishFrameOutput(frameP, bb, separateFiles, referenceFrame, + finishFrameOutput(frameP, bbP, separateFiles, referenceFrame, childProcess, remoteIO); } } @@ -702,7 +706,7 @@ readAndSaveFrame(struct inputSource * const inputSourceP, static void doFirstFrameStuff(enum frameContext const context, const char * const userDataFileName, - BitBucket * const bb, + BitBucket * const bbP, int const fsize_x, int const fsize_y, int const aspectRatio, @@ -713,8 +717,12 @@ doFirstFrameStuff(enum frameContext const context, /*---------------------------------------------------------------------------- Do stuff we have to do after reading the first frame in a sequence of frames requested of GenMPEGStream(). + + *bbP is the output stream to which to write any header stuff we have + to write. If 'context' is such that there is no header stuff to write, + then 'bbP' is irrelevant. -----------------------------------------------------------------------------*/ - *inputFrameBitsP = 24*Fsize_x*Fsize_y; + *inputFrameBitsP = 24 * Fsize_x * Fsize_y; SetBlocksPerSlice(); if (context == CONTEXT_WHOLESTREAM) { @@ -722,7 +730,7 @@ doFirstFrameStuff(enum frameContext const context, char * userData; unsigned int userDataSize; - assert(bb != NULL); + assert(bbP != NULL); DBG_PRINT(("Generating sequence header\n")); if (bitstreamMode == FIXED_RATE) { @@ -770,7 +778,7 @@ doFirstFrameStuff(enum frameContext const context, userDataSize = strlen(userData); strfree(userDataString); } - Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, + Mhead_GenSequenceHeader(bbP, Fsize_x, Fsize_y, /* pratio */ aspectRatio, /* pict_rate */ frameRate, /* bit_rate */ bit_rate, @@ -990,13 +998,21 @@ doAFrame(unsigned int const frameNumber, unsigned int * const framesReadP, unsigned int * const framesOutputP, bool * const firstFrameDoneP, - BitBucket * const bbP, + BitBucket * const wholeStreamBbP, unsigned int * const inputFrameBitsP, bool * const endOfStreamP) { /*---------------------------------------------------------------------------- *endOfStreamP returned means we were unable to do a frame because the input stream has ended. In that case, none of the other outputs are valid. + + Process an input frame. This can involve writing its description + to the output stream, saving it for later use, and/or writing + descriptions of previously saved frames to the output stream + because we now have enough information to do so. + + Output the frames to the output stream 'wholeStreamBbP'. If NULL, + output each frame to its own individual file instead. -----------------------------------------------------------------------------*/ char const frameType = FType_Type(frameNumber); @@ -1026,21 +1042,21 @@ doAFrame(unsigned int const frameNumber, *endOfStreamP = FALSE; if (!*firstFrameDoneP) { - doFirstFrameStuff(context, userDataFileName, - bbP, Fsize_x, Fsize_y, aspectRatio, + doFirstFrameStuff(context, userDataFileName, wholeStreamBbP, + Fsize_x, Fsize_y, aspectRatio, frameRate, qtable, niqtable, inputFrameBitsP); *firstFrameDoneP = TRUE; } - processRefFrame(frameP, bbP, frameStart, frameEnd, + processRefFrame(frameP, wholeStreamBbP, frameStart, frameEnd, pastRefFrameP, childProcess, outputFileName, framesReadP, framesOutputP); if (pastRefFrameP) { processBFrames(pastRefFrameP, frameP, realStart, realEnd, inputSourceP, remoteIO, childProcess, - &IOtime, bbP, outputFileName, + &IOtime, wholeStreamBbP, outputFileName, framesReadP, framesOutputP, ¤tGOP); } if (pastRefFrameP != NULL) @@ -1086,17 +1102,20 @@ GenMPEGStream(struct inputSource * const inputSourceP, we stop where the stream ends if that is before 'frameEnd'. -----------------------------------------------------------------------------*/ - BitBucket * bbP; + BitBucket * streamBbP; + /* The output stream to which we write all the frames. NULL + means the frames are going to individual frame files. + */ unsigned int frameNumber; bool endOfStream; bool firstFrameDone; int numBits; unsigned int firstFrame, lastFrame; - /* Frame numbers of the first and last frames we look at. This - could be more than the the frames we actually encode because - we may need context (i.e. to encode a B frame, we need the subsequent - I or P frame). - */ + /* Frame numbers of the first and last frames we look at. + This could be more than the the frames we actually encode + because we may need context (i.e. to encode a B frame, we + need the subsequent I or P frame). + */ unsigned int framesRead; /* Number of frames we have read; for statistical purposes */ MpegFrame * pastRefFrameP; @@ -1150,10 +1169,10 @@ GenMPEGStream(struct inputSource * const inputSourceP, if (showBitRatePerFrame) OpenBitRateFile(); /* May modify showBitRatePerFrame */ - if (context == CONTEXT_WHOLESTREAM || context == CONTEXT_GOP) - bbP = Bitio_New(ofP); + if (context == CONTEXT_JUSTFRAMES) + streamBbP = NULL; else - bbP = NULL; + streamBbP = Bitio_New(ofP); initTCTime(firstFrame); @@ -1171,7 +1190,7 @@ GenMPEGStream(struct inputSource * const inputSourceP, frameStart, frameEnd, realStart, realEnd, childProcess, outputFileName, pastRefFrameP, &pastRefFrameP, - &framesRead, &framesOutput, &firstFrameDone, bbP, + &framesRead, &framesOutput, &firstFrameDone, streamBbP, inputFrameBitsP, &endOfStream); } @@ -1180,10 +1199,10 @@ GenMPEGStream(struct inputSource * const inputSourceP, /* SEQUENCE END CODE */ if (context == CONTEXT_WHOLESTREAM) - Mhead_GenSequenceEnder(bbP); + Mhead_GenSequenceEnder(streamBbP); - if (context == CONTEXT_WHOLESTREAM) - numBits = bbP->cumulativeBits; + if (streamBbP) + numBits = streamBbP->cumulativeBits; else { /* What should the correct value be? Most likely 1. "numBits" is used below, so we need to make sure it's properly initialized @@ -1192,9 +1211,8 @@ GenMPEGStream(struct inputSource * const inputSourceP, numBits = 1; } - if (context != CONTEXT_JUSTFRAMES) { - Bitio_Flush(bbP); - bbP = NULL; + if (streamBbP) { + Bitio_Flush(streamBbP); fclose(ofP); } handleBitRate(realEnd, numBits, childProcess, showBitRatePerFrame); diff --git a/converter/ppm/ppmtompeg/pframe.c b/converter/ppm/ppmtompeg/pframe.c index e72fe5d6..de91e32c 100644 --- a/converter/ppm/ppmtompeg/pframe.c +++ b/converter/ppm/ppmtompeg/pframe.c @@ -60,8 +60,6 @@ static int32 totalTime = 0; static int qscaleP; static float totalSNR = 0.0; static float totalPSNR = 0.0; -extern Block **dct, **dctr, **dctb; -extern dct_data_type **dct_data; /*=====================* * INTERNAL PROCEDURES * diff --git a/converter/ppm/ppmtompeg/psearch.c b/converter/ppm/ppmtompeg/psearch.c index aea1a29b..83c62d04 100644 --- a/converter/ppm/ppmtompeg/psearch.c +++ b/converter/ppm/ppmtompeg/psearch.c @@ -16,6 +16,8 @@ #include "prototypes.h" #include "fsize.h" #include "param.h" +#include "subsample.h" +#include "block.h" /*==================* diff --git a/converter/ppm/ppmtompeg/subsample.c b/converter/ppm/ppmtompeg/subsample.c index 5ec71814..69401a1d 100644 --- a/converter/ppm/ppmtompeg/subsample.c +++ b/converter/ppm/ppmtompeg/subsample.c @@ -43,6 +43,7 @@ #include "bitio.h" #include "prototypes.h" +#include "subsample.h" static void diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c index e2428fb6..22456857 100644 --- a/converter/ppm/ppmtopict.c +++ b/converter/ppm/ppmtopict.c @@ -282,15 +282,8 @@ int i; (void) putc(i & 0xff, fd); } -#if __STDC__ static void putLong( FILE *fd, long i ) -#else /*__STDC__*/ -static void -putLong(fd, i) -FILE *fd; -long i; -#endif /*__STDC__*/ { (void) putc((int)((i >> 24) & 0xff), fd); (void) putc(((int)(i >> 16) & 0xff), fd); diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c index 6b51f291..e0760448 100644 --- a/converter/ppm/sldtoppm.c +++ b/converter/ppm/sldtoppm.c @@ -66,15 +66,9 @@ struct svector { struct spoint t; /* To point */ }; -static int extend ARGS((smallint ch)); -static int sli ARGS((void)); -static int slib ARGS((void)); -static void vscale ARGS((int *px, int *py)); -static void slider ARGS((void (*slvec) ARGS((struct svector *vec, int color)), - void (*slflood) ARGS((struct spolygon *poly, int color)) )); -static void slidefind ARGS((char *sname, int dironly, int ucasen)); -static void draw ARGS((struct svector *vec, int color)); -static void flood ARGS((struct spolygon *const poly, int const color)); +typedef void (slvecfn)(struct svector * vec, int color); +typedef void (slfloodfn)(struct spolygon * poly, int color); + static int ixdots, iydots; /* Screen size in dots */ static FILE *slfile; /* Slide file descriptor */ @@ -104,21 +98,26 @@ static int adjust = FALSE; /* Adjust to correct aspect ratio ? */ static struct slhead slfrof; /* Slide file header */ static long xfac, yfac; /* Aspect ratio scale factors */ -static int sdrawkcab; /* Slide drawing kinematic conversion of - ass-backwards data flag */ +static int sdrawkcab; + /* Slide drawing kinematic conversion of ass-backwards data flag */ + + /* EXTEND -- Turn a smallint into an int with sign extension, whether - or not that happens automatically. */ + or not that happens automatically. +*/ -static int extend(smallint ch) -{ +static int +extend(smallint ch) { return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch)); } + + /* SLI -- Input word from slide file */ -static int sli() -{ +static int +sli(void) { short wd; if (fread(&wd, sizeof wd, 1, slfile) != 1) { @@ -131,10 +130,12 @@ static int sli() return wd; } + + /* SLIB -- Input byte from slide file */ -static int slib() -{ +static int +slib(void) { smallint ch = 0; if (fread(&ch, sizeof ch, 1, slfile) != 1) { @@ -143,25 +144,171 @@ static int slib() return extend(ch); } + + /* VSCALE -- scale screen coordinates for mismatched display. */ -static void vscale(px, py) - int *px, *py; -{ +static void +vscale(int * const px, + int * const py) { + *px = (((unsigned) *px) * xfac) >> 16; *py = (((unsigned) *py) * yfac) >> 16; } + + +/* SLIDEFIND -- Find a slide in a library or, if DIRONLY is + nonzero, print a directory listing of the library. + If UCASEN is nonzero, the requested slide name is + converted to upper case. */ + +static void +slidefind(const char * const sname, + bool const dironly, + bool const ucasen) { + + char uname[32]; + unsigned char libent[36]; + long pos; + + if (dironly) + pm_message("Slides in library:"); + else { + int i; + const char * ip; + + ip = sname; /* initial value */ + + for (i = 0; i < 31; i++) { + char ch = *ip++; + if (ch == EOS) + break; + if (ucasen && ISLOWER(ch)) + ch = TOUPPER(ch); + uname[i] = ch; + } + uname[i] = EOS; + } + + /* Read slide library header and verify. */ + + if ((fread(libent, 32, 1, slfile) != 1) || + (!STREQ((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) { + pm_error("not an AutoCAD slide library file."); + } + pos = 32; + + /* Search for a slide with the requested name. */ + + while (TRUE) { + if ((fread(libent, 36, 1, slfile) != 1) || + (strlen((char *)libent) == 0)) { + if (dironly) { + return; + } + pm_error("slide %s not in library.", sname); + } + pos += 36; + if (dironly) { + pm_message(" %s", libent); + } else if (STREQ((char *)libent, uname)) { + long dpos = (((((libent[35] << 8) | libent[34]) << 8) | + libent[33]) << 8) | libent[32]; + if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) { + dpos -= pos; + + while (dpos-- > 0) + getc(slfile); + } + break; + } + } +} + + + +/* DRAW -- Draw a vector in the given AutoCAD color. */ + +static slvecfn draw; + +static void +draw(struct svector * vec, + int color) { + + pixel rgbcolor; + + if (blither) { + pm_message("Vector (%d, %d) - (%d, %d) Color %d", + vec->f.x, vec->f.y, vec->t.x, vec->t.y, color); + } + assert(vec->f.x >= 0 && vec->f.x < pixcols); + assert(vec->f.y >= 0 && vec->f.y < pixrows); + assert(vec->t.x >= 0 && vec->t.x < pixcols); + assert(vec->t.y >= 0 && vec->t.y < pixrows); + PPM_ASSIGN(rgbcolor, + acadcol[color][0], acadcol[color][1], acadcol[color][2]); + ppmd_line(pixels, pixcols, pixrows, pixmaxval, + vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y, + PPMD_NULLDRAWPROC, + (char *) &rgbcolor); +} + + + +/* FLOOD -- Draw a filled polygon. */ + +static slfloodfn flood; + +static void +flood(struct spolygon * const poly, + int const color) { + + unsigned int i; + struct fillobj * handle; + pixel rgbcolor; + + handle = ppmd_fill_create(); + + if (blither) { + unsigned int i; + pm_message("Polygon: %d points, fill type %d, color %d", + poly->npoints, poly->fill, color); + for (i = 0; i < poly->npoints; i++) { + pm_message(" Point %d: (%d, %d)", i + 1, + poly->pt[i].x, poly->pt[i].y); + } + } + + PPM_ASSIGN(rgbcolor, + acadcol[color][0], acadcol[color][1], acadcol[color][2]); + for (i = 0; i < poly->npoints; i++) { + assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols); + assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows); + ppmd_line(pixels, pixcols, pixrows, pixmaxval, + poly->pt[i].x, iydots - poly->pt[i].y, + poly->pt[(i + 1) % poly->npoints].x, + iydots - poly->pt[(i + 1) % poly->npoints].y, + ppmd_fill_drawproc, handle); + } + ppmd_fill(pixels, pixcols, pixrows, pixmaxval, + handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor); + + ppmd_fill_destroy(handle); +} + + + /* SLIDER -- Read slide file. This is called with the name of the file to be read and function pointers to the routines which process vectors and polygon fill requests respectively. */ -static void slider(slvec, slflood) - void (*slvec) ARGS((struct svector *vec, int color)); - void (*slflood) ARGS((struct spolygon *poly, int color)); -{ +static void +slider(slvecfn slvec, + slfloodfn slflood) { + int i, rescale; unsigned char ubfr[4]; /* Utility character buffer */ int lx, ly; /* Last x and y point */ @@ -174,14 +321,14 @@ static void slider(slvec, slflood) short rtest; /* Value to test byte reversal */ short btest = 0x1234; /* Value to test byte-reversal */ static struct slhead slhi = /* Master slide header sample */ - {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0}; + {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0}; int curcolor = 7; /* Current vector color */ pixel rgbcolor; /* Pixel used to clear pixmap */ - + lx = ly = 32000; - + /* Process the header of the slide file. */ - + sdrawkcab = FALSE; /* Initially guess byte order is OK */ fread(slfrof.slh, 17, 1, slfile); fread(&slfrof.sntype, sizeof(char), 1, slfile); @@ -194,48 +341,46 @@ static void slider(slvec, slflood) /* Verify that slide format is compatible with this program. */ - if (STREQ(slfrof.slh, slhi.slh)) { + if (STREQ(slfrof.slh, slhi.slh)) pm_error("this is not an AutoCAD slide file."); - } /* Verify that the number format and file level in the header are compatible. All slides written by versions of AutoCAD released since September of 1987 are compatible with this format. */ - if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel)) { + if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel)) pm_error("incompatible slide file format"); - } /* Build SDSAR value from long scaled version. */ - + ldsar = 0L; - for (i = 3; i >= 0; i--) { - ldsar = (ldsar << 8) | ubfr[i]; - } + for (i = 3; i >= 0; --i) + ldsar = (ldsar << 8) | ubfr[i]; slfrof.sdsar = ((double) ldsar) / 1E7; - + /* Examine the byte order test value. If it's backwards, set the byte-reversal flag and correct all of the values we've read in - so far. */ + so far. + */ if (btest != rtest) { - sdrawkcab = TRUE; + sdrawkcab = TRUE; #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8) - rshort(slfrof.sxdots); - rshort(slfrof.sydots); - rshort(slfrof.shwfill); + rshort(slfrof.sxdots); + rshort(slfrof.sydots); + rshort(slfrof.shwfill); #undef rshort } - + /* Dump the header if we're blithering. */ if (blither || info) { pm_message("Slide file type %d, level %d, hwfill type %d.", - slfrof.sntype, slfrof.slevel, slfrof.shwfill); + slfrof.sntype, slfrof.slevel, slfrof.shwfill); pm_message("Original screen size %dx%d, aspect ratio %.3f.", - slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar); + slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar); pm_message("Byte order is %s.", - sdrawkcab ? "being reversed" : "the same"); + sdrawkcab ? "being reversed" : "the same"); } /* If the display aspect ratio indicates that the pixels on the @@ -246,405 +391,284 @@ static void slider(slvec, slflood) We always correct the aspect ratio by adjusting the width of the image. This guarantees that output from the SHADE command, which is essentially scan-line data written in vector form, - will not be corrupted. */ + will not be corrupted. + */ dsar = ((double) slfrof.sxdots) / slfrof.sydots; if (fabs(slfrof.sdsar - dsar) > 0.0001) { - if (adjust) { - ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5; - iydots = slfrof.sydots; - dsar = ((double) ixdots) / iydots; + if (adjust) { + ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5; + iydots = slfrof.sydots; + dsar = ((double) ixdots) / iydots; + } else { + pm_message("Warning - pixels on source screen were non-square. " + "Specifying -adjust will correct image width " + "to compensate."); + ixdots = slfrof.sxdots; + iydots = slfrof.sydots; + dsar = slfrof.sdsar; + } } else { - pm_message("Warning - pixels on source screen were non-square."); - pm_message(" Specifying -adjust will correct image width to compensate."); + /* Source pixels were square. */ ixdots = slfrof.sxdots; iydots = slfrof.sydots; dsar = slfrof.sdsar; - } - } else { - /* Source pixels were square. */ - ixdots = slfrof.sxdots; - iydots = slfrof.sydots; - dsar = slfrof.sdsar; - adjust = FALSE; /* Mark no adjustment needed */ + adjust = FALSE; /* Mark no adjustment needed */ } /* If there's a uniform scale factor specified, apply it. */ if (uscale > 0) { - ixdots = (ixdots * uscale) + 0.5; - iydots = (iydots * uscale) + 0.5; + ixdots = (ixdots * uscale) + 0.5; + iydots = (iydots * uscale) + 0.5; } /* If the image is to be stretched to a given width, set the output image sizes accordingly. If only a height or width is given, scale the other direction proportionally to preserve the - aspect ratio. */ + aspect ratio. + */ if (sxsize > 0) { - if (sysize > 0) { - iydots = sysize - 1; - } else { - iydots = ((((long) iydots) * (sxsize - 1)) + - (iydots / 2)) / ixdots; - } - ixdots = sxsize - 1; - } else if (sysize > 0) { - if (sxsize > 0) { + if (sysize > 0) { + iydots = sysize - 1; + } else { + iydots = ((((long) iydots) * (sxsize - 1)) + + (iydots / 2)) / ixdots; + } ixdots = sxsize - 1; - } else { - ixdots = ((((long) ixdots) * (sysize - 1)) + - (ixdots / 2)) / iydots; - } - iydots = sysize - 1; + } else if (sysize > 0) { + if (sxsize > 0) { + ixdots = sxsize - 1; + } else { + ixdots = ((((long) ixdots) * (sysize - 1)) + + (ixdots / 2)) / iydots; + } + iydots = sysize - 1; } - + if (adjust) { - pm_message( + pm_message( "Resized from %dx%d to %dx%d to correct pixel aspect ratio.", - slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1); + slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1); } - + /* Allocate image buffer and clear it to black. */ - + pixels = ppm_allocarray(pixcols = ixdots + 1, pixrows = iydots + 1); PPM_ASSIGN(rgbcolor, 0, 0, 0); ppmd_filledrectangle(pixels, pixcols, pixrows, pixmaxval, 0, 0, pixcols, pixrows, PPMD_NULLDRAWPROC, (char *) &rgbcolor); - + if ((rescale = slfrof.sxdots != ixdots || - slfrof.sydots != iydots || - slfrof.sdsar != dsar) != 0) { - + slfrof.sydots != iydots || + slfrof.sdsar != dsar) != 0) { + /* Rescale all coords. so they'll look (more or less) - right on this display. */ - - xfac = (ixdots + 1) * 0x10000L; - xfac /= (long) (slfrof.sxdots + 1); - yfac = (iydots + 1) * 0x10000L; - yfac /= (long) (slfrof.sydots + 1); - if (dsar < slfrof.sdsar) { - yfac = yfac * dsar / slfrof.sdsar; - } else { - xfac = xfac * slfrof.sdsar / dsar; - } + right on this display. + */ + + xfac = (ixdots + 1) * 0x10000L; + xfac /= (long) (slfrof.sxdots + 1); + yfac = (iydots + 1) * 0x10000L; + yfac /= (long) (slfrof.sydots + 1); + if (dsar < slfrof.sdsar) { + yfac = yfac * dsar / slfrof.sdsar; + } else { + xfac = xfac * slfrof.sdsar / dsar; + } } poly.npoints = 0; /* No flood in progress. */ - + while ((cw = sli()) != 0xFC00) { - switch (cw & 0xFF00) { + switch (cw & 0xFF00) { case 0xFB00: /* Short vector compressed */ - vec.f.x = lx + extend(cw & 0xFF); - vec.f.y = ly + slib(); - vec.t.x = lx + slib(); - vec.t.y = ly + slib(); - lx = vec.f.x; - ly = vec.f.y; - if (rescale) { - vscale(&vec.f.x, &vec.f.y); - vscale(&vec.t.x, &vec.t.y); - } - (*slvec)(&vec, curcolor);/* Draw vector on screen */ - slx = vec.f.x; /* Save scaled point */ - sly = vec.f.y; - break; - + vec.f.x = lx + extend(cw & 0xFF); + vec.f.y = ly + slib(); + vec.t.x = lx + slib(); + vec.t.y = ly + slib(); + lx = vec.f.x; + ly = vec.f.y; + if (rescale) { + vscale(&vec.f.x, &vec.f.y); + vscale(&vec.t.x, &vec.t.y); + } + (*slvec)(&vec, curcolor);/* Draw vector on screen */ + slx = vec.f.x; /* Save scaled point */ + sly = vec.f.y; + break; + case 0xFC00: /* End of file */ - break; - + break; + case 0xFD00: /* Flood command */ - vec.f.x = sli(); - vec.f.y = sli(); - if ((int) vec.f.y < 0) { /* start or end */ - if (poly.npoints != 0) { /* end? */ - if (poly.npoints > 2 && poly.npoints < 11) { - (*slflood)(&poly, curcolor); - } else { - pm_error("Bad polygon vertex count (%d)", - poly.npoints); - } - poly.npoints = 0; - } else { - poly.fill = -vec.f.y; /* Start */ + vec.f.x = sli(); + vec.f.y = sli(); + if ((int) vec.f.y < 0) { /* start or end */ + if (poly.npoints != 0) { /* end? */ + if (poly.npoints > 2 && poly.npoints < 11) { + (*slflood)(&poly, curcolor); + } else { + pm_error("Bad polygon vertex count (%d)", + poly.npoints); + } + poly.npoints = 0; + } else { + poly.fill = -vec.f.y; /* Start */ + } + } else { /* Polygon vertex */ + if (poly.npoints < 10) { + if (rescale) { + vscale(&vec.f.x, &vec.f.y); + } + poly.pt[poly.npoints].x = vec.f.x; + poly.pt[poly.npoints].y = vec.f.y; + } + poly.npoints++; } - } else { /* Polygon vertex */ - if (poly.npoints < 10) { + break; + + case 0xFE00: /* Common endpoint compressed */ + vec.f.x = lx + extend(cw & 0xFF); + vec.f.y = ly + slib(); + lx = vec.f.x; + ly = vec.f.y; + vec.t.x = slx; + vec.t.y = sly; if (rescale) { vscale(&vec.f.x, &vec.f.y); } - poly.pt[poly.npoints].x = vec.f.x; - poly.pt[poly.npoints].y = vec.f.y; - } - poly.npoints++; - } - break; - - case 0xFE00: /* Common endpoint compressed */ - vec.f.x = lx + extend(cw & 0xFF); - vec.f.y = ly + slib(); - lx = vec.f.x; - ly = vec.f.y; - vec.t.x = slx; - vec.t.y = sly; - if (rescale) { - vscale(&vec.f.x, &vec.f.y); - } - (*slvec)(&vec, curcolor);/* Draw vector */ - slx = vec.f.x; /* Save scaled point */ - sly = vec.f.y; - break; - + (*slvec)(&vec, curcolor);/* Draw vector */ + slx = vec.f.x; /* Save scaled point */ + sly = vec.f.y; + break; + case 0xFF00: /* Change color */ - curcolor = cw & 0xFF; - break; + curcolor = cw & 0xFF; + break; default: /* Co-ordinates */ - lx = vec.f.x = cw; - ly = vec.f.y = sli(); - vec.t.x = sli(); - vec.t.y = sli(); - if (rescale) { - vscale(&vec.f.x, &vec.f.y); - vscale(&vec.t.x, &vec.t.y); - } - (*slvec)(&vec, curcolor); - slx = vec.f.x; /* Save scaled point */ - sly = vec.f.y; - break; - } - } -} - -/* SLIDEFIND -- Find a slide in a library or, if DIRONLY is - nonzero, print a directory listing of the library. - If UCASEN is nonzero, the requested slide name is - converted to upper case. */ - -static void slidefind(sname, dironly, ucasen) - char *sname; - int dironly, ucasen; -{ - char uname[32]; - unsigned char libent[36]; - long pos; - - if (dironly) { - pm_message("Slides in library:"); - } else { - int i; - char *ip = sname; - - for (i = 0; i < 31; i++) { - char ch = *ip++; - if (ch == EOS) { - break; - } - if (ucasen && ISLOWER(ch)) { - ch = TOUPPER(ch); - } - uname[i] = ch; - } - uname[i] = EOS; - } - - /* Read slide library header and verify. */ - - if ((fread(libent, 32, 1, slfile) != 1) || - (!STREQ((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) { - pm_error("not an AutoCAD slide library file."); - } - pos = 32; - - /* Search for a slide with the requested name. */ - - while (TRUE) { - if ((fread(libent, 36, 1, slfile) != 1) || - (strlen((char *)libent) == 0)) { - if (dironly) { - return; - } - pm_error("slide %s not in library.", sname); - } - pos += 36; - if (dironly) { - pm_message(" %s", libent); - } else if (STREQ((char *)libent, uname)) { - long dpos = (((((libent[35] << 8) | libent[34]) << 8) | - libent[33]) << 8) | libent[32]; - if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) { - dpos -= pos; - - while (dpos-- > 0) { - (void) getc(slfile); - } + lx = vec.f.x = cw; + ly = vec.f.y = sli(); + vec.t.x = sli(); + vec.t.y = sli(); + if (rescale) { + vscale(&vec.f.x, &vec.f.y); + vscale(&vec.t.x, &vec.t.y); + } + (*slvec)(&vec, curcolor); + slx = vec.f.x; /* Save scaled point */ + sly = vec.f.y; + break; } - break; - } } } -/* DRAW -- Draw a vector in the given AutoCAD color. */ -static void draw(vec, color) - struct svector *vec; - int color; -{ - pixel rgbcolor; - - if (blither) { - pm_message("Vector (%d, %d) - (%d, %d) Color %d", - vec->f.x, vec->f.y, vec->t.x, vec->t.y, color); - } - assert(vec->f.x >= 0 && vec->f.x < pixcols); - assert(vec->f.y >= 0 && vec->f.y < pixrows); - assert(vec->t.x >= 0 && vec->t.x < pixcols); - assert(vec->t.y >= 0 && vec->t.y < pixrows); - PPM_ASSIGN(rgbcolor, - acadcol[color][0], acadcol[color][1], acadcol[color][2]); - ppmd_line(pixels, pixcols, pixrows, pixmaxval, - vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y, - PPMD_NULLDRAWPROC, - (char *) &rgbcolor); -} - -/* FLOOD -- Draw a filled polygon. */ - -static void -flood(struct spolygon * const poly, - int const color) { - - int i; - struct fillobj * handle; - pixel rgbcolor; - - handle = ppmd_fill_create(); - - if (blither) { - pm_message("Polygon: %d points, fill type %d, color %d", - poly->npoints, poly->fill, color); - for (i = 0; i < poly->npoints; i++) { - pm_message(" Point %d: (%d, %d)", i + 1, - poly->pt[i].x, poly->pt[i].y); - } - } - - PPM_ASSIGN(rgbcolor, - acadcol[color][0], acadcol[color][1], acadcol[color][2]); - for (i = 0; i < poly->npoints; i++) { - assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols); - assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows); - ppmd_line(pixels, pixcols, pixrows, pixmaxval, - poly->pt[i].x, iydots - poly->pt[i].y, - poly->pt[(i + 1) % poly->npoints].x, - iydots - poly->pt[(i + 1) % poly->npoints].y, - ppmd_fill_drawproc, handle); - } - ppmd_fill(pixels, pixcols, pixrows, pixmaxval, - handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor); - - ppmd_fill_destroy(handle); -} /* Main program. */ -int main(argc, argv) - int argc; - char *argv[]; -{ +int +main(int argc, + char * argv[]) { + int argn; const char * const usage = "[-verbose] [-info] [-adjust] [-scale <s>]\n\ - [-dir] [-lib|-Lib <name>]\n\ - [-xsize|-width <x>] [-ysize|-height <y>] [sldfile]"; +[-dir] [-lib|-Lib <name>]\n\ +[-xsize|-width <x>] [-ysize|-height <y>] [sldfile]"; int scalespec = FALSE, widspec = FALSE, hgtspec = FALSE, dironly = FALSE, - ucasen; - char *slobber = (char *) 0; /* Slide library item */ + ucasen; + const char * slobber; /* Slide library item */ + slobber = NULL; + ppm_init(&argc, argv); argn = 1; while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { if (pm_keymatch(argv[argn], "-verbose", 2)) { - blither = TRUE; + blither = TRUE; } else if (pm_keymatch(argv[argn], "-adjust", 2)) { - adjust = TRUE; + adjust = TRUE; } else if (pm_keymatch(argv[argn], "-dir", 2)) { - dironly = TRUE; + dironly = TRUE; } else if (pm_keymatch(argv[argn], "-info", 2)) { - info = TRUE; + info = TRUE; } else if (pm_keymatch(argv[argn], "-lib", 2)) { - if (slobber != (char *) 0) { + if (slobber) pm_error("already specified a library item"); - } ucasen = argv[argn][1] != 'L'; - argn++; - if (argn == argc) { - pm_usage(usage); - } - slobber = argv[argn]; + argn++; + if (argn == argc) { + pm_usage(usage); + } + slobber = argv[argn]; } else if (pm_keymatch(argv[argn], "-scale", 2)) { - if (scalespec) { + if (scalespec) { pm_error("already specified a scale factor"); - } - argn++; + } + argn++; if ((argn == argc) || (sscanf(argv[argn], "%lf", &uscale) != 1)) - pm_usage(usage); - if (uscale <= 0.0) { + pm_usage(usage); + if (uscale <= 0.0) { pm_error("scale factor must be greater than 0"); - } - scalespec = TRUE; + } + scalespec = TRUE; } else if (pm_keymatch(argv[argn], "-xsize", 2) || pm_keymatch(argv[argn], "-width", 2)) { - if (widspec) { + if (widspec) { pm_error("already specified a width/xsize"); - } - argn++; + } + argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1)) - pm_usage(usage); - widspec = TRUE; + pm_usage(usage); + widspec = TRUE; } else if (pm_keymatch(argv[argn], "-ysize", 2) || pm_keymatch(argv[argn], "-height", 2)) { - if (hgtspec) { + if (hgtspec) { pm_error("already specified a height/ysize"); + } + argn++; + if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) + pm_usage(usage); + hgtspec = TRUE; + } else { + pm_usage(usage); } argn++; - if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) - pm_usage(usage); - hgtspec = TRUE; - } else { - pm_usage(usage); - } - argn++; } /* If a file name is specified, open it. Otherwise read from - standard input. */ + standard input. + */ if (argn < argc) { - slfile = pm_openr(argv[argn]); - argn++; + slfile = pm_openr(argv[argn]); + argn++; } else { - slfile = stdin; + slfile = stdin; } - + if (argn != argc) { /* Extra bogus arguments ? */ - pm_usage(usage); + pm_usage(usage); } - + /* If we're extracting an item from a slide library, position the - input stream to the start of the chosen slide. */ - - if (dironly || (slobber != (char *) 0)) { - slidefind(slobber, dironly, ucasen); - } - + input stream to the start of the chosen slide. + */ + + if (dironly || slobber) + slidefind(slobber, dironly, ucasen); + if (!dironly) { - slider(draw, flood); - ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE); + slider(draw, flood); + ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE); } pm_close(slfile); pm_close(stdout); - exit(0); + + return 0; } diff --git a/converter/ppm/spctoppm.c b/converter/ppm/spctoppm.c index 3eea7821..d2a48187 100644 --- a/converter/ppm/spctoppm.c +++ b/converter/ppm/spctoppm.c @@ -165,15 +165,8 @@ DoBitmap( ifp ) sscreen[i] = ( screen[i<<1] << 8 ) + ( 0xff & screen[(i<<1)+1] ); } -#if __STDC__ static void DoChar( int n, char c ) -#else /*__STDC__*/ -static void -DoChar( n, c ) - int n; - char c; -#endif /*__STDC__*/ { int i; |