diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2016-03-27 01:46:26 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2016-03-27 01:46:26 +0000 |
commit | dff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa (patch) | |
tree | b147568ccffc4cdba9e2a98de1452450ba8e55c3 /converter/ppm | |
parent | 4ce684c4978610d1ea42be1b00f7332f3f5f337a (diff) | |
download | netpbm-mirror-dff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa.tar.gz netpbm-mirror-dff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa.tar.xz netpbm-mirror-dff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa.zip |
Promote Advanced (10.73) to Stable
git-svn-id: http://svn.code.sf.net/p/netpbm/code/stable@2692 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/ppm')
85 files changed, 6887 insertions, 4901 deletions
diff --git a/converter/ppm/411toppm.c b/converter/ppm/411toppm.c index 6ece4c4b..eb2372a5 100644 --- a/converter/ppm/411toppm.c +++ b/converter/ppm/411toppm.c @@ -30,7 +30,7 @@ Bryan Henderson reworked the program to use the Netpbm libraries to create the PPM output and follow some other Netpbm conventions. - 2001-03-03. Bryan's contribution is public domain. + 2001-03-03. Bryan's contribution is public domain. */ /* * Copyright (c) 1995 The Regents of the University of California. @@ -56,22 +56,21 @@ * HEADER FILES * *==============*/ #include <stdio.h> -#include <stdlib.h> #include "pm_c_util.h" -#include "ppm.h" -#include "shhopt.h" #include "mallocvar.h" +#include "shhopt.h" +#include "ppm.h" typedef unsigned char uint8; #define CHOP(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x)) -struct cmdline_info { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char *input_filespec; /* Filespec of input file */ + const char * inputFileName; int width; int height; }; @@ -79,38 +78,42 @@ struct cmdline_info { static void -parse_command_line(int argc, char ** argv, - struct cmdline_info *cmdline_p) { +parseCommandLine(int argc, const char ** argv, + struct CmdlineInfo *cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. -----------------------------------------------------------------------------*/ - optStruct *option_def = malloc(100*sizeof(optStruct)); + optEntry * option_def; /* Instructions to OptParseOptions2 on how to parse our options. */ - optStruct2 opt; + optStruct3 opt; unsigned int option_def_index; - option_def_index = 0; /* incremented by OPTENTRY */ - OPTENTRY(0, "width", OPT_INT, &cmdline_p->width, 0); - OPTENTRY(0, "height", OPT_INT, &cmdline_p->height, 0); + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "width", OPT_INT, &cmdlineP->width, NULL, 0); + OPTENT3(0, "height", OPT_INT, &cmdlineP->height, NULL, 0); /* Set the defaults */ - cmdline_p->width = 64; - cmdline_p->height = 48; + cmdlineP->width = 64; + cmdlineP->height = 48; opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions2(&argc, argv, opt, 0); - /* Uses and sets argc, argv, and some of *cmdline_p and others. */ + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - if (cmdline_p->width <= 0) + if (cmdlineP->width <= 0) pm_error("-width must be positive."); - if (cmdline_p->height <= 0) + if (cmdlineP->width %4 != 0) + pm_error("-width must be a multiple of 4."); + if (cmdlineP->height <= 0) pm_error("-height must be positive."); if (argc > 2) @@ -118,145 +121,111 @@ parse_command_line(int argc, char ** argv, "You supplied %d", argc-1); else { if (argc > 1) - cmdline_p->input_filespec = argv[1]; + cmdlineP->inputFileName = argv[1]; else - cmdline_p->input_filespec = "-"; + cmdlineP->inputFileName = "-"; } + free(option_def); } -static void -ReadYUV(FILE *fpointer, const int width, const int height, - uint8 ** const orig_y, uint8 ** const orig_cb, - uint8 ** const orig_cr) { +static void +ReadYUV(FILE * const ifP, + uint8 * const inbuff) { + + size_t bytesRead; - int y, x, i; + bytesRead = fread(inbuff, 1, 6, ifP); - for (y = 0; y < height; y++) { - for (x = 0, i = 0; x < width; x+=4, i++) { - fread(orig_y[y]+x , 1, 4, fpointer); - fread(orig_cb[y]+i, 1, 1, fpointer); - fread(orig_cr[y]+i, 1, 1, fpointer); - } - } + if (bytesRead != 6 ) { + if (feof(ifP)) + pm_error("Premature end of input."); + else + pm_error("Error reading input."); + } } static void -AllocYCC(const int width, const int height, - uint8 *** const orig_yP, uint8 *** const orig_crP, - uint8 *** const orig_cbP) { - int y; - - MALLOCARRAY_NOFAIL(*orig_yP, height); - for (y = 0; y < height; y++) - MALLOCARRAY_NOFAIL((*orig_yP)[y], width); - - MALLOCARRAY_NOFAIL(*orig_crP, height); - for (y = 0; y < height; y++) - MALLOCARRAY_NOFAIL((*orig_crP)[y], width/4); - - MALLOCARRAY_NOFAIL(*orig_cbP, height); - for (y = 0; y < height; y++) - MALLOCARRAY_NOFAIL((*orig_cbP)[y], width/4); -} +YUVtoPPM(FILE * const ifP, + int const width, + int const height, + pixel * const pixrow ) { + unsigned int col; + for (col = 0; col < width; ++col) { -static void -YUVtoPPM(const int width, const int height, - uint8 ** const orig_y, - uint8 ** const orig_cb, - uint8 ** const orig_cr, - pixel ** const ppm_image - ) { - int **Y, **U, **V; - int y; + uint8 inbuff[6]; - /* first, allocate tons of memory */ + uint8 * const origY = &inbuff[0]; + uint8 * const origCb = &inbuff[4]; + uint8 * const origCr = &inbuff[5]; + int y, u, v; + int32_t tempR, tempG, tempB; + pixval r, g, b; - MALLOCARRAY_NOFAIL(Y, height); - for (y = 0; y < height; y++) - MALLOCARRAY_NOFAIL(Y[y], width); - - MALLOCARRAY_NOFAIL(U, height); - for (y = 0; y < height; y++) - MALLOCARRAY_NOFAIL(U[y], width / 4); - - MALLOCARRAY_NOFAIL(V, height); - for (y = 0; y < height; y++) - MALLOCARRAY_NOFAIL(V[y], width/4); - - for ( y = 0; y < height; y ++ ) { - int x; - for ( x = 0; x < width/4; x ++ ) { - U[y][x] = orig_cb[y][x] - 128; - V[y][x] = orig_cr[y][x] - 128; - } - } - for ( y = 0; y < height; y ++ ) { - int x; - for ( x = 0; x < width; x ++ ) - { - Y[y][x] = orig_y[y][x] - 16; - } - } - for ( y = 0; y < height; y++ ) { - int x; - for ( x = 0; x < width; x++ ) { - pixval r, g, b; - long tempR, tempG, tempB; - /* look at yuvtoppm source for explanation */ - - tempR = 104635*V[y][x/4]; - tempG = -25690*U[y][x/4] + -53294 * V[y][x/4]; - tempB = 132278*U[y][x/4]; - - tempR += (Y[y][x]*76310); - tempG += (Y[y][x]*76310); - tempB += (Y[y][x]*76310); - - r = CHOP((int)(tempR >> 16)); - g = CHOP((int)(tempG >> 16)); - b = CHOP((int)(tempB >> 16)); - - PPM_ASSIGN(ppm_image[y][x], r, g, b); + if (col % 4 == 0) { + ReadYUV(ifP, inbuff); + u = origCb[0] - 128; + v = origCr[0] - 128; } + + y = origY[col % 4] - 16; + + tempR = 104635 * v + y * 76310; + tempG = -25690 * u + -53294 * v + y * 76310; + tempB = 132278 * u + y * 76310; + + r = CHOP((int)(tempR >> 16)); + g = CHOP((int)(tempG >> 16)); + b = CHOP((int)(tempB >> 16)); + + PPM_ASSIGN(pixrow[col], r, g, b); } - /* We really should free the Y, U, and V arrays now */ } int -main(int argc, char **argv) { - FILE *infile; - struct cmdline_info cmdline; - uint8 **orig_y, **orig_cb, **orig_cr; - pixel **ppm_image; +main(int argc, const char **argv) { - ppm_init(&argc, argv); + pixval const maxval = 255; + struct CmdlineInfo cmdline; + FILE * ifP; + pixel * pixrow; + unsigned int row; - parse_command_line(argc, argv, &cmdline); + pm_proginit(&argc, argv); - AllocYCC(cmdline.width, cmdline.height, &orig_y, &orig_cr, &orig_cb); - ppm_image = ppm_allocarray(cmdline.width, cmdline.height); + parseCommandLine(argc, argv, &cmdline); - pm_message("Reading (%dx%d): %s\n", cmdline.width, cmdline.height, - cmdline.input_filespec); - infile = pm_openr(cmdline.input_filespec); - ReadYUV(infile, cmdline.width, cmdline.height, orig_y, orig_cb, orig_cr); - pm_close(infile); + pixrow = ppm_allocrow(cmdline.width); - YUVtoPPM(cmdline.width, cmdline.height, orig_y, orig_cb, orig_cr, - ppm_image); + pm_message("Reading (%ux%u): '%s'", cmdline.width, cmdline.height, + cmdline.inputFileName); - ppm_writeppm(stdout, ppm_image, cmdline.width, cmdline.height, 255, 0); + ifP = pm_openr(cmdline.inputFileName); - ppm_freearray(ppm_image, cmdline.height); + ppm_writeppminit(stdout, cmdline.width, cmdline.height, maxval, 0); + + for (row = 0; row < cmdline.height; ++row) { + YUVtoPPM(ifP, cmdline.width, cmdline.height, pixrow); + ppm_writeppmrow(stdout, pixrow, cmdline.width, maxval, 0); + } + + if (fgetc(ifP) != EOF) + pm_message("Extraneous data at end of image."); + + pm_close(ifP); + ppm_freerow(pixrow); return 0; } +/* + By default a .411 file is width=64, height=48, 4608 bytes. + There is no header. +*/ diff --git a/converter/ppm/Makefile b/converter/ppm/Makefile index adc3a400..003ef8d3 100644 --- a/converter/ppm/Makefile +++ b/converter/ppm/Makefile @@ -12,15 +12,16 @@ SUBDIRS = hpcdtoppm ppmtompeg PORTBINARIES = 411toppm eyuvtoppm gouldtoppm ilbmtoppm imgtoppm \ leaftoppm mtvtoppm neotoppm \ pcxtoppm pc1toppm pi1toppm picttoppm pjtoppm \ - ppmtoacad ppmtoarbtxt \ + ppmtoacad ppmtoapplevol ppmtoarbtxt ppmtoascii \ ppmtobmp ppmtoeyuv ppmtogif ppmtoicr ppmtoilbm \ ppmtoleaf ppmtolj ppmtomitsu ppmtoneo \ ppmtopcx ppmtopi1 ppmtopict ppmtopj \ - ppmtopjxl ppmtoppm ppmtopuzz ppmtorgb3 ppmtosixel ppmtoterm \ + ppmtopjxl ppmtoppm ppmtopuzz ppmtorgb3 \ + ppmtosixel ppmtospu ppmtoterm \ ppmtowinicon ppmtoxpm ppmtoyuv ppmtoyuvsplit \ qrttoppm rawtoppm rgb3toppm spctoppm \ sputoppm tgatoppm winicontoppm ximtoppm xpmtoppm xvminitoppm \ - yuvtoppm yuvsplittoppm + yuvsplittoppm yuvtoppm MATHBINARIES = sldtoppm diff --git a/converter/ppm/eyuvtoppm.c b/converter/ppm/eyuvtoppm.c index 33d57409..910a125b 100644 --- a/converter/ppm/eyuvtoppm.c +++ b/converter/ppm/eyuvtoppm.c @@ -36,9 +36,9 @@ #include <unistd.h> #include "pm_c_util.h" -#include "ppm.h" #include "shhopt.h" #include "mallocvar.h" +#include "ppm.h" typedef unsigned char uint8; @@ -46,11 +46,11 @@ typedef unsigned char uint8; -struct cmdline_info { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char *input_filespec; /* Filespecs of input file */ + const char * inputFileName; /* Name of input file */ unsigned int width; unsigned int height; }; @@ -59,11 +59,13 @@ struct cmdline_info { static void parseCommandLine(int argc, char ** argv, - struct cmdline_info *cmdlineP) { + struct CmdlineInfo * const cmdlineP) { optStruct3 opt; /* Set by OPTENT3 */ unsigned int option_def_index; - optEntry *option_def = malloc(100*sizeof(optEntry)); + optEntry * option_def; + + MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENT3 */ OPTENT3('w', "width", OPT_UINT, &cmdlineP->width, NULL, 0); @@ -77,7 +79,7 @@ parseCommandLine(int argc, char ** argv, opt.short_allowed = TRUE; opt.allowNegNum = FALSE; - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); if (cmdlineP->width == 0) pm_error("The width cannot be zero."); @@ -92,32 +94,34 @@ parseCommandLine(int argc, char ** argv, if (argc-1 == 0) - cmdlineP->input_filespec = "-"; + cmdlineP->inputFileName = "-"; else if (argc-1 != 1) pm_error("Program takes zero or one argument (filename). You " - "specified %d", argc-1); + "specified %u", argc-1); else - cmdlineP->input_filespec = argv[1]; + cmdlineP->inputFileName = argv[1]; + free(option_def); } static uint8 ** -AllocUint8Array(unsigned int const cols, unsigned int const rows) { +allocUint8Array(unsigned int const cols, + unsigned int const rows) { - uint8 **retval; - unsigned int y; + uint8 ** retval; + unsigned int row; MALLOCARRAY(retval, rows); if (retval == NULL) - pm_error("Unable to allocate storage for %d x %d byte array.", + pm_error("Unable to allocate storage for %u x %u byte array.", cols, rows); - for (y = 0; y < rows; y++) { - MALLOCARRAY(retval[y], cols); - if (retval[y] == NULL) - pm_error("Unable to allocate storage for %d x %d byte array.", + for (row = 0; row < rows; ++row) { + MALLOCARRAY(retval[row], cols); + if (retval[row] == NULL) + pm_error("Unable to allocate storage for %u x %u byte array.", cols, rows); } return retval; @@ -125,216 +129,191 @@ AllocUint8Array(unsigned int const cols, unsigned int const rows) { -static int ** -AllocIntArray(unsigned int const cols, unsigned int const rows) { +static void +freeUint8Array(uint8 ** const array, + unsigned int const rows) { - int **retval; - unsigned int y; + unsigned int row; - MALLOCARRAY(retval, rows); - if (retval == NULL) - pm_error("Unable to allocate storage for %d x %d byte array.", - cols, rows); + for (row = 0; row < rows; ++row) + free(array[row]); - for (y = 0; y < rows; y++) { - MALLOCARRAY(retval[y], cols); - if (retval[y] == NULL) - pm_error("Unable to allocate storage for %d x %d byte array.", - cols, rows); - } - return retval; + free(array); } static void -allocateStorage(int const cols, int const rows, - int *** const YP, int *** const UP, int *** const VP, - pixel *** const pixelsP, - uint8 *** const orig_yP, uint8 *** const orig_cbP, - uint8 *** const orig_crP) { - - *YP = AllocIntArray(cols, rows); - *UP = AllocIntArray(cols, rows); - *VP = AllocIntArray(cols, rows); - - *pixelsP = ppm_allocarray(cols, rows); - - *orig_yP = AllocUint8Array(cols, rows); - *orig_cbP = AllocUint8Array(cols, rows); - *orig_crP = AllocUint8Array(cols, rows); -} - - - -static void -FreeArray(void ** const array, unsigned int const rows) { - - unsigned int y; - - for (y = 0; y < rows; y++) - free(array[y]); - free(array); +allocateStorage(unsigned int const cols, + unsigned int const rows, + uint8 *** const orig_yP, + uint8 *** const orig_cbP, + uint8 *** const orig_crP) { + + *orig_yP = allocUint8Array(cols, rows); + *orig_cbP = allocUint8Array(cols, rows); + *orig_crP = allocUint8Array(cols, rows); } static void -freeStorage(int const rows, - int ** const Y, int ** const U, int ** const V, - pixel ** const pixels, - uint8 ** const orig_y, uint8 ** const orig_cb, - uint8 ** const orig_cr) { +freeStorage(unsigned int const rows, + uint8 ** const orig_y, + uint8 ** const orig_cb, + uint8 ** const orig_cr) { - FreeArray((void**) orig_y, rows); - FreeArray((void**) orig_cb, rows); - FreeArray((void**) orig_cr, rows); - - ppm_freearray(pixels, rows); + freeUint8Array(orig_y, rows); + freeUint8Array(orig_cb, rows); + freeUint8Array(orig_cr, rows); - FreeArray((void**) Y, rows); - FreeArray((void**) U, rows); - FreeArray((void**) V, rows); } static void -YUVtoPPM(unsigned int const cols, unsigned int const rows, - uint8 ** const orig_y, uint8 ** const orig_cb, uint8 ** const orig_cr, - pixel ** const pixels, - int ** const Y, int ** const U, int ** const V) { +YUVtoPPM(FILE * const ofP, + unsigned int const cols, + unsigned int const rows, + uint8 ** const orig_y, + uint8 ** const orig_cb, + uint8 ** const orig_cr) { /*---------------------------------------------------------------------------- Convert the YUV image in arrays orig_y[][], orig_cb[][], and orig_cr[][] - to a PPM image in the array (already allocated) pixels[][]. - - Use the preallocated areas Y[][], U[][], and V[][] for working space. + to a PPM image and write it to file *ofP. -----------------------------------------------------------------------------*/ + pixel * const pixrow = ppm_allocrow(cols); - int y; + unsigned int row; - for ( y = 0; y < rows/2; y ++ ) { - int x; - for ( x = 0; x < cols/2; x ++ ) { - U[y][x] = orig_cb[y][x] - 128; - V[y][x] = orig_cr[y][x] - 128; - } - } + ppm_writeppminit(ofP, cols, rows, 255, FALSE); - for ( y = 0; y < rows; y ++ ) { - int x; - for ( x = 0; x < cols; x ++ ) - Y[y][x] = orig_y[y][x] - 16; - } + for (row = 0; row < rows; ++row) { + unsigned int col; - for ( y = 0; y < rows; y++ ) { - int x; - for ( x = 0; x < cols; x++ ) { + for (col = 0; col < cols; ++col) { + int const y = orig_y[row][col] - 16; + int const u = orig_cb[row/2][col/2] - 128; + int const v = orig_cr[row/2][col/2] - 128; long tempR, tempG, tempB; - int r, g, b; + int r, g, b; /* look at yuvtoppm source for explanation */ - tempR = 104635*V[y/2][x/2]; - tempG = -25690*U[y/2][x/2] + -53294 * V[y/2][x/2]; - tempB = 132278*U[y/2][x/2]; - - tempR += (Y[y][x]*76310); - tempG += (Y[y][x]*76310); - tempB += (Y[y][x]*76310); + tempR = 104635*v + 76310*y; + tempG = -25690*u + -53294*v + 76310*y; + tempB = 132278*u + 76310*y; r = CHOP((int)(tempR >> 16)); g = CHOP((int)(tempG >> 16)); b = CHOP((int)(tempB >> 16)); - PPM_ASSIGN(pixels[y][x], r, g, b); + PPM_ASSIGN(pixrow[col], r, g, b); } + ppm_writeppmrow(stdout, pixrow, cols, 255, FALSE); } + ppm_freerow(pixrow); } static void -ReadYUV(FILE * const yuvfile, - unsigned int const cols, unsigned int const rows, - uint8 ** const orig_y, - uint8 ** const orig_cb, - uint8 ** const orig_cr, - bool * const eofP) { - - unsigned int y; - int c; - - c = fgetc(yuvfile); - if (c < 0) - *eofP = TRUE; - else { - *eofP = FALSE; - ungetc(c, yuvfile); +ReadYUV(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, + uint8 ** const orig_y, + uint8 ** const orig_cb, + uint8 ** const orig_cr, + bool * const eofP) { + + unsigned int row; + unsigned int totalRead; + bool eof; + + eof = false; /* initial value */ + totalRead = 0; /* initial value */ + + for (row = 0; row < rows && !eof; ++row) { /* Y */ + size_t bytesRead; + + bytesRead = fread(orig_y[row], 1, cols, ifP); + totalRead += bytesRead; + if (bytesRead != cols) + eof = true; } - if (!*eofP) { - for (y = 0; y < rows; y++) /* Y */ - fread(orig_y[y], 1, cols, yuvfile); - for (y = 0; y < rows / 2; y++) /* U */ - fread(orig_cb[y], 1, cols / 2, yuvfile); + for (row = 0; row < rows / 2 && !eof; ++row) { /* U */ + size_t bytesRead; + + bytesRead = fread(orig_cb[row], 1, cols / 2, ifP); + totalRead += bytesRead; + if (bytesRead != cols / 2) + eof = true; + } - for (y = 0; y < rows / 2; y++) /* V */ - fread(orig_cr[y], 1, cols / 2, yuvfile); - if (feof(yuvfile)) - pm_error("Premature end of file reading EYUV input file"); + for (row = 0; row < rows / 2 && !eof; ++row) { /* V */ + size_t bytesRead; + + bytesRead = fread(orig_cr[row], 1, cols / 2, ifP); + totalRead += bytesRead; + if (bytesRead != cols / 2) + eof = true; } + + if (eof) { + if (totalRead == 0) + *eofP = TRUE; + else + pm_error("Premature end of file reading EYUV input file"); + } else + *eofP = FALSE; } int -main(int argc, char **argv) { +main(int argc, const char **argv) { - FILE *ifp; - struct cmdline_info cmdline; + FILE * ifP; + struct CmdlineInfo cmdline; unsigned int frameSeq; /* The following are addresses of malloc'ed storage areas for use by subroutines. */ - int ** Y; - int ** U; - int ** V; - uint8 **orig_y, **orig_cb, **orig_cr; - pixel ** pixels; + uint8 ** orig_y; + uint8 ** orig_cb; + uint8 ** orig_cr; + bool eof; - ppm_init(&argc, argv); + pm_proginit(&argc, argv); - parseCommandLine(argc, argv, &cmdline); + parseCommandLine(argc, (char **)argv, &cmdline); - /* Allocate all the storage once, to save time. */ + /* Allocate all the storage at once, to save time. */ allocateStorage(cmdline.width, cmdline.height, - &Y, &U, &V, &pixels, &orig_y, &orig_cb, &orig_cr); + &orig_y, &orig_cb, &orig_cr); - ifp = pm_openr(cmdline.input_filespec); + ifP = pm_openr(cmdline.inputFileName); - for (frameSeq = 0; !feof(ifp); frameSeq++) { - bool eof; + for (frameSeq = 0, eof = false; !eof; ++frameSeq) { - ReadYUV(ifp, cmdline.width, cmdline.height, + ReadYUV(ifP, cmdline.width, cmdline.height, orig_y, orig_cb, orig_cr, &eof); + if (!eof) { pm_message("Converting Frame %u", frameSeq); - YUVtoPPM(cmdline.width, cmdline.height, orig_y, orig_cb, orig_cr, - pixels, Y, U, V); - ppm_writeppm(stdout, pixels, cmdline.width, cmdline.height, - 255, FALSE); - } + YUVtoPPM(stdout, cmdline.width, cmdline.height, + orig_y, orig_cb, orig_cr); + } else if (frameSeq == 0) + pm_error("Empty EYUV input file"); } - freeStorage(cmdline.height, Y, U, V, pixels, orig_y, orig_cb, orig_cr); - - pm_close(ifp); - exit(0); -} - + freeStorage(cmdline.height, orig_y, orig_cb, orig_cr); + pm_close(ifP); + return 0; +} diff --git a/converter/ppm/hpcdtoppm/pcdovtoppm b/converter/ppm/hpcdtoppm/pcdovtoppm index 1f8b3006..dbf6f53d 100755 --- a/converter/ppm/hpcdtoppm/pcdovtoppm +++ b/converter/ppm/hpcdtoppm/pcdovtoppm @@ -195,7 +195,7 @@ if [ ${#imagefiles[*]} -gt 0 ] ; then rowfiles="$rowfiles $rowfile" fi -if [ ${#rowfiles[*]} == 1 ]; then +if [ ${#rowfiles[*]} = 1 ]; then cat $rowfiles else if [ "$colors" = "n" ] ; then diff --git a/converter/ppm/ilbm.h b/converter/ppm/ilbm.h index 68657956..dbe47758 100644 --- a/converter/ppm/ilbm.h +++ b/converter/ppm/ilbm.h @@ -23,7 +23,7 @@ typedef struct { #define mskNone 0 #define mskHasMask 1 #define mskHasTransparentColor 2 -#define mskLasso 3 /* not supported */ +#define mskLasso 3 /* can't handle this */ #define mskMAXKNOWN mskLasso static const char * mskNAME[] = { "none", "mask plane", "transparent color", "lasso" @@ -127,8 +127,8 @@ typedef struct { #define CLUT_RED 1 #define CLUT_GREEN 2 #define CLUT_BLUE 3 -#define CLUT_HUE 4 /* not supported */ -#define CLUT_SAT 5 /* not supported */ +#define CLUT_HUE 4 /* can't handle this */ +#define CLUT_SAT 5 /* can't handle this */ /* unofficial DCOL chunk for direct-color */ diff --git a/converter/ppm/ilbmtoppm.c b/converter/ppm/ilbmtoppm.c index 5ceb70b6..662be0b5 100644 --- a/converter/ppm/ilbmtoppm.c +++ b/converter/ppm/ilbmtoppm.c @@ -9,7 +9,7 @@ ** documentation. This software is provided "as is" without express or ** implied warranty. ** -** Modified by Mark Thompson on 10/4/90 to accomodate 24-bit IFF files +** Modified by Mark Thompson on 10/4/90 to accommodate 24-bit IFF files ** as used by ASDG, NewTek, etc. ** ** Modified by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de) @@ -89,11 +89,10 @@ static unsigned char *ilbmrow; static pixel *pixelrow; static FILE *maskfile = NULL; static bit *maskrow = NULL; -static short wrotemask = 0; +static bool wrotemask; static IFF_ID typeid; /* ID_ILBM, ID_RGBN, ID_RGB8 */ -static pixel *transpColor = NULL; /* transparent color */ -static char *transpName = NULL; +static char *transpName = NULL; /* -transparent option value */ static bool debug = FALSE; @@ -192,8 +191,8 @@ read_bytes(FILE * const ifP, static unsigned char -get_byte(ifp, iffid, counter) - FILE* ifp; +get_byte(ifP, iffid, counter) + FILE* ifP; IFF_ID iffid; long *counter; { @@ -204,9 +203,9 @@ get_byte(ifp, iffid, counter) pm_error("insufficient data in %s chunk", ID2string(iffid)); --(*counter); } - i = getc(ifp); + i = getc(ifP); if( i == EOF ) - readerr(ifp, iffid); + readerr(ifP, iffid); return (unsigned char) i; } @@ -311,7 +310,7 @@ display_chunk(FILE * const ifP, static void -read_cmap(FILE * const ifp, +read_cmap(FILE * const ifP, IFF_ID const iffid, long const chunksize, ColorMap * const cmap) { @@ -321,7 +320,7 @@ read_cmap(FILE * const ifp, colors = chunksize / 3; if( colors == 0 ) { pm_error("warning - empty %s colormap", ID2string(iffid)); - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); } else { unsigned int i; if( cmap->color ) /* prefer CMAP-chunk over CMYK-chunk */ @@ -331,30 +330,30 @@ read_cmap(FILE * const ifp, for( i = 0; i < colors; ++i ) { int r, g, b; - r = get_byte(ifp, iffid, &chunksize); - g = get_byte(ifp, iffid, &chunksize); - b = get_byte(ifp, iffid, &chunksize); + r = get_byte(ifP, iffid, &chunksize); + g = get_byte(ifP, iffid, &chunksize); + b = get_byte(ifP, iffid, &chunksize); PPM_ASSIGN(cmap->color[i], r, g, b); } - chunk_end(ifp, iffid, chunksize); + chunk_end(ifP, iffid, chunksize); } } static void -read_cmyk(FILE * const ifp, +read_cmyk(FILE * const ifP, IFF_ID const iffid, long const chunksize, ColorMap * const cmap) { if( HAS_COLORMAP(cmap) ) { /* prefer RGB color map */ - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); } else { long const colors = chunksize/4; if( colors == 0 ) { pm_error("warning - empty %s colormap", ID2string(iffid)); - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); } else { unsigned int i; cmap->color = ppm_allocrow(colors); @@ -362,10 +361,10 @@ read_cmyk(FILE * const ifp, for( i = 0; i < colors; ++i ) { int c, m, y, k; - c = get_byte(ifp, iffid, &chunksize); - m = get_byte(ifp, iffid, &chunksize); - y = get_byte(ifp, iffid, &chunksize); - k = get_byte(ifp, iffid, &chunksize); + c = get_byte(ifP, iffid, &chunksize); + m = get_byte(ifP, iffid, &chunksize); + y = get_byte(ifP, iffid, &chunksize); + k = get_byte(ifP, iffid, &chunksize); { pixval const red = @@ -381,7 +380,7 @@ read_cmyk(FILE * const ifp, PPM_ASSIGN(cmap->color[i], red, green, blue); } } - chunk_end(ifp, iffid, chunksize); + chunk_end(ifP, iffid, chunksize); } } } @@ -389,7 +388,7 @@ read_cmyk(FILE * const ifp, static void -read_clut(FILE * const ifp, +read_clut(FILE * const ifP, IFF_ID const iffid, unsigned long const chunksize, ColorMap * const cmap) { @@ -397,19 +396,19 @@ read_clut(FILE * const ifp, if (chunksize != CLUTSize) { pm_message("invalid size for %s chunk - skipping it", ID2string(iffid)); - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); } else { long type; unsigned char * lut; unsigned long remainingChunksize; unsigned int i; - type = get_big_long(ifp, iffid, &remainingChunksize); - get_big_long(ifp, iffid, &remainingChunksize); /* skip reserved fld */ + type = get_big_long(ifP, iffid, &remainingChunksize); + get_big_long(ifP, iffid, &remainingChunksize); /* skip reserved fld */ MALLOCARRAY_NOFAIL(lut, 256); for( i = 0; i < 256; ++i ) - lut[i] = get_byte(ifp, iffid, &remainingChunksize); + lut[i] = get_byte(ifP, iffid, &remainingChunksize); switch( type ) { case CLUT_MONO: @@ -434,6 +433,27 @@ read_clut(FILE * const ifp, +static void +warnNonsquarePixels(uint8_t const xAspect, + uint8_t const yAspect) { + + if (xAspect != yAspect) { + const char * const baseMsg = "warning - non-square pixels"; + + if (pm_have_float_format()) + pm_message("%s; to fix do a 'pamscale -%cscale %g'", + baseMsg, + xAspect > yAspect ? 'x' : 'y', + xAspect > yAspect ? + (float)xAspect/yAspect : + (float)yAspect/xAspect); + else + pm_message("%s", baseMsg); + } +} + + + static BitMapHeader * read_bmhd(FILE * const ifP, IFF_ID const iffid, @@ -441,7 +461,7 @@ read_bmhd(FILE * const ifP, BitMapHeader * bmhdP; - if( chunksize != BitMapHeaderSize ) { + if (chunksize != BitMapHeaderSize) { pm_message("invalid size for %s chunk - skipping it", ID2string(iffid)); skip_chunk(ifP, iffid, chunksize); @@ -468,24 +488,24 @@ read_bmhd(FILE * const ifP, bmhdP->pageWidth = get_big_short(ifP, iffid, &remainingChunksize); bmhdP->pageHeight = get_big_short(ifP, iffid, &remainingChunksize); - if( verbose ) { - if( typeid == ID_ILBM ) + if (verbose) { + if (typeid == ID_ILBM) pm_message("dimensions: %dx%d, %d planes", bmhdP->w, bmhdP->h, bmhdP->nPlanes); else pm_message("dimensions: %dx%d", bmhdP->w, bmhdP->h); - if( typeid == ID_ILBM || typeid == ID_PBM ) { + if (typeid == ID_ILBM || typeid == ID_PBM) { pm_message("compression: %s", bmhdP->compression <= cmpMAXKNOWN ? cmpNAME[bmhdP->compression] : "unknown"); - switch( bmhdP->masking ) { + switch(bmhdP->masking) { case mskNone: break; case mskHasMask: case mskHasTransparentColor: - if( !maskfile ) + if (!maskfile) pm_message("use '-maskfile <filename>' " "to generate a PBM mask file from %s", mskNAME[bmhdP->masking]); @@ -499,27 +519,20 @@ read_bmhd(FILE * const ifP, } } else /* RGBN/RGB8 */ - if( !maskfile ) + if (!maskfile) pm_message("use '-maskfile <filename>' " "to generate a PBM mask file " "from genlock bits"); } /* fix aspect ratio */ - if( bmhdP->xAspect == 0 || bmhdP->yAspect == 0 ) { + if (bmhdP->xAspect == 0 || bmhdP->yAspect == 0) { pm_message("warning - illegal aspect ratio %d:%d, using 1:1", bmhdP->xAspect, bmhdP->yAspect); bmhdP->xAspect = bmhdP->yAspect = 1; } - if( bmhdP->xAspect != bmhdP->yAspect ) { - pm_message("warning - non-square pixels; " - "to fix do a 'pnmscale -%cscale %g'", - bmhdP->xAspect > bmhdP->yAspect ? 'x' : 'y', - bmhdP->xAspect > bmhdP->yAspect ? - (float)(bmhdP->xAspect)/bmhdP->yAspect : - (float)(bmhdP->yAspect)/bmhdP->xAspect); - } + warnNonsquarePixels(bmhdP->xAspect, bmhdP->yAspect); } return bmhdP; } @@ -628,42 +641,42 @@ decode_mask(FILE * const ifP, unsigned char *ilp; cols = bmhdP->w; - switch( bmhdP->masking ) { + switch (bmhdP->masking) { case mskNone: break; case mskHasMask: /* mask plane */ read_ilbm_plane(ifP, remainingChunksizeP, RowBytes(cols), bmhdP->compression); - if( maskfile ) { + if (maskfile) { ilp = ilbmrow; cbit = 7; - for( col = 0; col < cols; col++, cbit-- ) { - if( cbit < 0 ) { + for (col = 0; col < cols; ++col, --cbit) { + if (cbit < 0) { cbit = 7; - ilp++; + ++ilp; } - if( *ilp & bit_mask[cbit] ) + if (*ilp & bit_mask[cbit]) maskrow[col] = PBM_BLACK; else maskrow[col] = PBM_WHITE; } pbm_writepbmrow(maskfile, maskrow, cols, 0); - wrotemask = 1; + wrotemask = true; } break; case mskHasTransparentColor: - if( !chunkyrow ) + if (!chunkyrow) pm_error("decode_mask(): chunkyrow == NULL - can't happen"); - if( maskfile ) { - for( col = 0; col < cols; col++ ) { - if( chunkyrow[col] == bmhdP->transparentColor ) + if (maskfile) { + for (col = 0; col < cols; ++col) { + if (chunkyrow[col] == bmhdP->transparentColor) maskrow[col] = PBM_WHITE; else maskrow[col] = PBM_BLACK; } pbm_writepbmrow(maskfile, maskrow, cols, 0); - wrotemask = 1; + wrotemask = true; } break; case mskLasso: @@ -758,83 +771,66 @@ multi_free(cmap) } + /**************************************************************************** Colormap handling ****************************************************************************/ + + static void -prepareCmap(const BitMapHeader * const bmhd, - ColorMap * const cmap) { -/*---------------------------------------------------------------------------- - This is a really ugly subroutine that 1) analyzes a colormap and its - context (returning the analysis in global variables); and 2) modifies that - color map, because it's really one type of data structure as input and - another as output. +analyzeCmapSamples(const ColorMap * const cmapP, + pixval * const maxSampleP, + bool * const shiftedP) { ------------------------------------------------------------------------------*/ - pixval colmaxval = 0; - int shifted = 1; - int i, r, g, b; - - if( bmhd ) { - if( bmhd->masking == mskHasTransparentColor || - bmhd->masking == mskLasso ) { - unsigned short const transpIdx = bmhd->transparentColor; - if( !transpName ) { - MALLOCVAR_NOFAIL(transpColor); - if (HAS_COLORMAP(cmap)) { - if( transpIdx >= cmap->ncolors ) { - pm_message("using default transparent color (black)"); - PPM_ASSIGN(*transpColor, 0, 0, 0); - } else - *transpColor = cmap->color[transpIdx]; - } else { - /* The color index is just a direct gray level */ - PPM_ASSIGN(*transpColor, transpIdx, transpIdx, transpIdx); - } - } - } + pixval maxSample; + bool shifted; + unsigned int i; + + for (i = 0, maxSample = 0, shifted = true; i < cmapP->ncolors; ++i) { + pixval const r = PPM_GETR(cmapP->color[i]); + pixval const g = PPM_GETG(cmapP->color[i]); + pixval const b = PPM_GETB(cmapP->color[i]); - if( bmhd->flags & BMHD_FLAGS_CMAPOK ) - return; + maxSample = MAX(maxSample, MAX(r, MAX(g, b))); + + if (r & 0x0f || g & 0x0f || b & 0x0f) + shifted = false; } + *shiftedP = shifted; + *maxSampleP = maxSample; +} - if( !HAS_COLORMAP(cmap) ) - return; - for( i = 0; i < cmap->ncolors; i++ ) { - r = PPM_GETR(cmap->color[i]); - if( r > colmaxval ) colmaxval = r; - if( r & 0x0f ) shifted = 0; - g = PPM_GETG(cmap->color[i]); - if( g > colmaxval ) colmaxval = g; - if( g & 0x0f ) shifted = 0; +static void +transformCmap(ColorMap * const cmapP) { - b = PPM_GETB(cmap->color[i]); - if( b > colmaxval ) colmaxval = b; - if( b & 0x0f ) shifted = 0; - } + pixval maxSample; + /* The maximum sample value in *cmapP input */ + bool shifted; + /* Samples in the *cmapP input appear to be 4 bit (maxval 15) original + values shifted left 4 places to make 8 bit (maxval 255) samples. + */ -#ifdef DEBUG - pm_message("colormap maxval is %d", colmaxval); -#endif - if( colmaxval == 0 ) + analyzeCmapSamples(cmapP, &maxSample, &shifted); + + if (maxSample == 0) pm_message("warning - black colormap"); - else - if( shifted || colmaxval <= 15 ) { - if( !adjustcolors ) { + else if (shifted || maxSample <= 15) { + if (!adjustcolors) { pm_message("warning - probably %s4-bit colormap", - shifted ? "shifted " : ""); - pm_message(" use '-adjustcolors' to scale colormap to 8 bits"); - } - else { + shifted ? "shifted " : ""); + pm_message("Use '-adjustcolors' to scale colormap to 8 bits"); + } else { + unsigned int i; pm_message("scaling colormap to 8 bits"); - for( i = 0; i < cmap->ncolors; i++ ) { - r = PPM_GETR(cmap->color[i]); - g = PPM_GETG(cmap->color[i]); - b = PPM_GETB(cmap->color[i]); - if( shifted ) { + for (i = 0; i < cmapP->ncolors; ++i) { + pixval r, g, b; + r = PPM_GETR(cmapP->color[i]); + g = PPM_GETG(cmapP->color[i]); + b = PPM_GETB(cmapP->color[i]); + if (shifted) { r >>= 4; g >>= 4; b >>= 4; @@ -842,13 +838,74 @@ prepareCmap(const BitMapHeader * const bmhd, r *= FACTOR_4BIT; g *= FACTOR_4BIT; b *= FACTOR_4BIT; - PPM_ASSIGN(cmap->color[i], r, g, b); + PPM_ASSIGN(cmapP->color[i], r, g, b); } } } } + +static pixel * +transpColor(const BitMapHeader * const bmhdP, + ColorMap * const cmapP, + const char * const transpName, + pixval const maxval) { + + pixel * transpColorP; + + if (bmhdP) { + if (bmhdP->masking == mskHasTransparentColor || + bmhdP->masking == mskLasso) { + MALLOCVAR_NOFAIL(transpColorP); + + if (transpName) + *transpColorP = ppm_parsecolor(transpName, maxval); + else { + unsigned short const transpIdx = bmhdP->transparentColor; + if (HAS_COLORMAP(cmapP)) { + if (transpIdx >= cmapP->ncolors) { + pm_message("using default transparent color (black)"); + PPM_ASSIGN(*transpColorP, 0, 0, 0); + } else + *transpColorP = cmapP->color[transpIdx]; + } else { + /* The color index is just a direct gray level */ + PPM_ASSIGN(*transpColorP, transpIdx, transpIdx, transpIdx); + } + } + } else + transpColorP = NULL; + } else + transpColorP = NULL; + + return transpColorP; +} + + + +static void +prepareCmap(const BitMapHeader * const bmhdP, + ColorMap * const cmapP) { +/*---------------------------------------------------------------------------- + This is a really ugly subroutine that 1) analyzes a colormap and its + context (returning the analysis in global variables); and 2) modifies that + color map, because it's really one type of data structure as input and + another as output. +-----------------------------------------------------------------------------*/ + bool bmhdCmapOk; + + if (bmhdP) + bmhdCmapOk = (bmhdP->flags & BMHD_FLAGS_CMAPOK); + else + bmhdCmapOk = false; + + if (HAS_COLORMAP(cmapP) && !bmhdCmapOk) + transformCmap(cmapP); +} + + + static pixval lookup_red(cmap, oldval) ColorMap *cmap; @@ -988,18 +1045,18 @@ get_color(cmap, idx, red, green, blue) ****************************************************************************/ static void -std_to_ppm(FILE * const ifp, +std_to_ppm(FILE * const ifP, long const chunksize, - BitMapHeader * const bmhd, + BitMapHeader * const bmhdP, ColorMap * const cmap, long const viewportmodes); static void -ham_to_ppm(FILE * const ifp, +ham_to_ppm(FILE * const ifP, long const chunksize, - BitMapHeader * const bmhd, + BitMapHeader * const bmhdP, ColorMap * const cmap, long const viewportmodes) { @@ -1008,9 +1065,9 @@ ham_to_ppm(FILE * const ifp, rawtype *rawrow; unsigned char hamlut[256]; - cols = bmhd->w; - rows = bmhd->h; - hambits = bmhd->nPlanes - 2; + cols = bmhdP->w; + rows = bmhdP->h; + hambits = bmhdP->nPlanes - 2; hammask = (1 << hambits) - 1; hamshift = 8 - hambits; hammask2 = (1 << hamshift) - 1; @@ -1019,15 +1076,16 @@ ham_to_ppm(FILE * const ifp, int const assumed_viewportmodes = viewportmodes & ~(vmHAM); pm_message("%d-plane HAM?? - interpreting image as a normal ILBM", - bmhd->nPlanes); - std_to_ppm(ifp, chunksize, bmhd, cmap, assumed_viewportmodes); + bmhdP->nPlanes); + std_to_ppm(ifP, chunksize, bmhdP, cmap, assumed_viewportmodes); return; } else { unsigned long remainingChunksize; + pixel * transpColorP; pm_message("input is a %sHAM%d file", HAS_MULTIPALETTE(cmap) ? "multipalette " : "", - bmhd->nPlanes); + bmhdP->nPlanes); if( HAS_COLORLUT(cmap) || HAS_MONOLUT(cmap) ) { pm_message("warning - color lookup tables ignored in HAM"); @@ -1046,10 +1104,7 @@ ham_to_ppm(FILE * const ifp, cmap->monolut = hamlut; } - if( transpName ) { - MALLOCVAR_NOFAIL(transpColor); - *transpColor = ppm_parsecolor(transpName, MAXCOLVAL); - } + transpColorP = transpColor(bmhdP, cmap, transpName, MAXCOLVAL); if( HAS_MULTIPALETTE(cmap) ) multi_init(cmap, viewportmodes); @@ -1066,15 +1121,15 @@ ham_to_ppm(FILE * const ifp, if( HAS_MULTIPALETTE(cmap) ) multi_update(cmap, row); - decode_row(ifp, &remainingChunksize, rawrow, bmhd->nPlanes, bmhd); - decode_mask(ifp, &remainingChunksize, rawrow, bmhd); + decode_row(ifP, &remainingChunksize, rawrow, bmhdP->nPlanes, bmhdP); + decode_mask(ifP, &remainingChunksize, rawrow, bmhdP); r = g = b = 0; for( col = 0; col < cols; col++ ) { int idx = rawrow[col] & hammask; - if( transpColor && maskrow && maskrow[col] == PBM_WHITE ) - pixelrow[col] = *transpColor; + if( transpColorP && maskrow && maskrow[col] == PBM_WHITE ) + pixelrow[col] = *transpColorP; else { switch((rawrow[col] >> hambits) & 0x03) { case HAMCODE_CMAP: @@ -1101,7 +1156,7 @@ ham_to_ppm(FILE * const ifp, } ppm_writeppmrow(stdout, pixelrow, cols, MAXCOLVAL, 0); } - chunk_end(ifp, ID_BODY, remainingChunksize); + chunk_end(ifP, ID_BODY, remainingChunksize); } } @@ -1110,27 +1165,28 @@ ham_to_ppm(FILE * const ifp, static void std_to_ppm(FILE * const ifP, long const chunksize, - BitMapHeader * const bmhd, + BitMapHeader * const bmhdP, ColorMap * const cmap, long const viewportmodes) { if (viewportmodes & vmHAM) { - ham_to_ppm(ifP, chunksize, bmhd, cmap, viewportmodes); + ham_to_ppm(ifP, chunksize, bmhdP, cmap, viewportmodes); } else { - unsigned int const cols = bmhd->w; - unsigned int const rows = bmhd->h; + unsigned int const cols = bmhdP->w; + unsigned int const rows = bmhdP->h; rawtype *rawrow; unsigned int row, col; pixval maxval; unsigned long remainingChunksize; + pixel * transpColorP; - pm_message("input is a %d-plane %s%sILBM", bmhd->nPlanes, + pm_message("input is a %d-plane %s%sILBM", bmhdP->nPlanes, HAS_MULTIPALETTE(cmap) ? "multipalette " : "", viewportmodes & vmEXTRA_HALFBRITE ? "EHB " : "" ); - if( bmhd->nPlanes > MAXPLANES ) + if( bmhdP->nPlanes > MAXPLANES ) pm_error("too many planes (max %d)", MAXPLANES); if( HAS_COLORMAP(cmap) ) { @@ -1140,15 +1196,12 @@ std_to_ppm(FILE * const ifP, } else { pm_message("no colormap - interpreting values as grayscale"); - maxval = lut_maxval(cmap, pm_bitstomaxval(bmhd->nPlanes)); + maxval = lut_maxval(cmap, pm_bitstomaxval(bmhdP->nPlanes)); if( maxval > PPM_OVERALLMAXVAL ) pm_error("nPlanes is too large"); } - if( transpName ) { - MALLOCVAR_NOFAIL(transpColor); - *transpColor = ppm_parsecolor(transpName, maxval); - } + transpColorP = transpColor(bmhdP, cmap, transpName, maxval); rawrow = alloc_rawrow(cols); @@ -1164,13 +1217,13 @@ std_to_ppm(FILE * const ifP, if( HAS_MULTIPALETTE(cmap) ) multi_update(cmap, row); - decode_row(ifP, &remainingChunksize, rawrow, bmhd->nPlanes, bmhd); - decode_mask(ifP, &remainingChunksize, rawrow, bmhd); + decode_row(ifP, &remainingChunksize, rawrow, bmhdP->nPlanes, bmhdP); + decode_mask(ifP, &remainingChunksize, rawrow, bmhdP); for( col = 0; col < cols; col++ ) { pixval r, g, b; - if( transpColor && maskrow && maskrow[col] == PBM_WHITE ) - pixelrow[col] = *transpColor; + if( transpColorP && maskrow && maskrow[col] == PBM_WHITE ) + pixelrow[col] = *transpColorP; else { get_color(cmap, rawrow[col], &r, &g, &b); PPM_ASSIGN(pixelrow[col], r, g, b); @@ -1198,6 +1251,7 @@ deep_to_ppm(FILE * const ifP, rawtype *Rrow, *Grow, *Brow; pixval maxval; unsigned long remainingChunksize; + pixel * transpColorP; pm_message("input is a deep (%d-bit) ILBM", bmhdP->nPlanes); if( planespercolor > MAXPLANES ) @@ -1214,11 +1268,8 @@ deep_to_ppm(FILE * const ifP, if( maxval > PPM_OVERALLMAXVAL ) pm_error("nPlanes is too large"); - if( transpName ) { - MALLOCVAR_NOFAIL(transpColor); - *transpColor = ppm_parsecolor(transpName, maxval); - } - + transpColorP = transpColor(bmhdP, cmap, transpName, maxval); + Rrow = alloc_rawrow(cols); Grow = alloc_rawrow(cols); Brow = alloc_rawrow(cols); @@ -1234,8 +1285,8 @@ deep_to_ppm(FILE * const ifP, decode_mask(ifP, &remainingChunksize, NULL, bmhdP); for( col = 0; col < cols; col++ ) { - if( transpColor && maskrow && maskrow[col] == PBM_WHITE ) - pixelrow[col] = *transpColor; + if( transpColorP && maskrow && maskrow[col] == PBM_WHITE ) + pixelrow[col] = *transpColorP; else PPM_ASSIGN(pixelrow[col], lookup_red(cmap, Rrow[col]), lookup_green(cmap, Grow[col]), @@ -1266,6 +1317,7 @@ dcol_to_ppm(FILE * const ifP, pixval maxval, redmaxval, greenmaxval, bluemaxval; pixval *redtable, *greentable, *bluetable; unsigned long remainingChunksize; + pixel * transpColorP; pm_message("input is a %d:%d:%d direct color ILBM", redplanes, greenplanes, blueplanes); @@ -1316,10 +1368,7 @@ dcol_to_ppm(FILE * const ifP, for (i = 0; i <= bluemaxval; ++i) bluetable[i] = ROUNDDIV(i * maxval, bluemaxval); } - if( transpName ) { - MALLOCVAR_NOFAIL(transpColor); - *transpColor = ppm_parsecolor(transpName, maxval); - } + transpColorP = transpColor(bmhdP, cmap, transpName, maxval); Rrow = alloc_rawrow(cols); Grow = alloc_rawrow(cols); @@ -1336,8 +1385,8 @@ dcol_to_ppm(FILE * const ifP, decode_mask(ifP, &remainingChunksize, NULL, bmhdP); for( col = 0; col < cols; col++ ) { - if( transpColor && maskrow && maskrow[col] == PBM_WHITE ) - pixelrow[col] = *transpColor; + if( transpColorP && maskrow && maskrow[col] == PBM_WHITE ) + pixelrow[col] = *transpColorP; else PPM_ASSIGN( pixelrow[col], redtable[Rrow[col]], greentable[Grow[col]], @@ -1372,6 +1421,7 @@ ipbm_to_ppm(FILE * const ifP, int col, row; pixval maxval; unsigned long remainingChunksize; + pixel * transpColorP; pm_message("input is a %sPBM ", HAS_MULTIPALETTE(cmap) ? "multipalette " : ""); @@ -1390,10 +1440,7 @@ ipbm_to_ppm(FILE * const ifP, maxval = lut_maxval(cmap, pm_bitstomaxval(bmhdP->nPlanes)); } - if( transpName ) { - MALLOCVAR_NOFAIL(transpColor); - *transpColor = ppm_parsecolor(transpName, maxval); - } + transpColorP = transpColor(bmhdP, cmap, transpName, maxval); if( HAS_MULTIPALETTE(cmap) ) multi_init(cmap, viewportmodes); @@ -1412,8 +1459,8 @@ ipbm_to_ppm(FILE * const ifP, for( col = 0; col < cols; col++ ) { pixval r, g, b; - if( transpColor && maskrow && maskrow[col] == PBM_WHITE ) - pixelrow[col] = *transpColor; + if( transpColorP && maskrow && maskrow[col] == PBM_WHITE ) + pixelrow[col] = *transpColorP; else { get_color(cmap, ilbmrow[col], &r, &g, &b); PPM_ASSIGN(pixelrow[col], r, g, b); @@ -1436,48 +1483,54 @@ rgbn_to_ppm(FILE * const ifP, unsigned int const rows = bmhdP->h; unsigned int const cols = bmhdP->w; - int row, col, count, genlock, tries; - pixval r, g, b, maxval; + unsigned int row; + unsigned int count; + pixval maxval; unsigned long remainingChunksize; + pixel * transpColorP; pm_message("input is a %d-bit RGB image", (typeid == ID_RGB8 ? 8 : 4)); - if( bmhdP->compression != 4 ) + if (bmhdP->compression != 4) pm_error("invalid compression mode for %s: %d (must be 4)", ID2string(typeid), bmhdP->compression); - - switch( typeid ) { - case ID_RGBN: - if( bmhdP->nPlanes != 13 ) - pm_error("invalid number of planes for %s: %d (must be 13)", - ID2string(typeid), bmhdP->nPlanes); - maxval = lut_maxval(cmap, 15); - break; - case ID_RGB8: - if( bmhdP->nPlanes != 25 ) - pm_error("invalid number of planes for %s: %d (must be 25)", - ID2string(typeid), bmhdP->nPlanes); - maxval = 255; - break; - default: - pm_error("rgbn_to_ppm(): invalid IFF ID %s - can't happen", - ID2string(typeid)); + + switch (typeid) { + case ID_RGBN: + if (bmhdP->nPlanes != 13) + pm_error("invalid number of planes for %s: %d (must be 13)", + ID2string(typeid), bmhdP->nPlanes); + maxval = lut_maxval(cmap, 15); + break; + case ID_RGB8: + if (bmhdP->nPlanes != 25) + pm_error("invalid number of planes for %s: %d (must be 25)", + ID2string(typeid), bmhdP->nPlanes); + maxval = 255; + break; + default: + pm_error("rgbn_to_ppm(): invalid IFF ID %s - can't happen", + ID2string(typeid)); } - if( transpName ) { - MALLOCVAR_NOFAIL(transpColor); - *transpColor = ppm_parsecolor(transpName, maxval); - } + transpColorP = transpColor(bmhdP, cmap, transpName, maxval); ppm_writeppminit(stdout, cols, rows, maxval, 0); - remainingChunksize = chunksize; /* initial value */ - count = 0; - for( row = 0; row < rows; row++ ) { - for( col = 0; col < cols; col++ ) { + for (row = 0, count = 0, remainingChunksize = chunksize; + row < rows; + ++row) { + + unsigned int col; + + for (col = 0; col < cols; ++col) { + unsigned int tries; + unsigned int genlock; + pixval r, g, b; + tries = 0; - while( !count ) { - if( typeid == ID_RGB8 ) { + while (count == 0) { + if (typeid == ID_RGB8) { r = lookup_red(cmap, get_byte(ifP, ID_BODY, &remainingChunksize)); g = lookup_green(cmap, get_byte(ifP, ID_BODY, @@ -1487,47 +1540,46 @@ rgbn_to_ppm(FILE * const ifP, count = get_byte(ifP, ID_BODY, &remainingChunksize); genlock = count & 0x80; count &= 0x7f; - } - else { - int word; - word = get_big_short(ifP, ID_BODY, &remainingChunksize); + } else { + unsigned int const word = + get_big_short(ifP, ID_BODY, &remainingChunksize); r = lookup_red(cmap, (word & 0xf000) >> 12); g = lookup_green(cmap, (word & 0x0f00) >> 8); b = lookup_blue(cmap, (word & 0x00f0) >> 4); genlock = word & 0x0008; count = word & 0x0007; } - if( !count ) { + if (!count) { count = get_byte(ifP, ID_BODY, &remainingChunksize); - if( !count ) + if (count == 0) count = get_big_short(ifP, ID_BODY, &remainingChunksize); - if( !count ) - ++tries; + if (count == 0) + ++tries; } } - if( tries ) { - pm_message("warning - repeat count 0 at col %d row %d: " - "skipped %d RGB entr%s", + if (tries > 0) { + pm_message("warning - repeat count 0 at col %u row %u: " + "skipped %u RGB entr%s", col, row, tries, (tries == 1 ? "y" : "ies")); } - if( maskfile ) { + if (maskfile) { /* genlock bit set -> transparent */ - if( genlock ) + if (genlock) maskrow[col] = PBM_WHITE; else maskrow[col] = PBM_BLACK; } - if( transpColor && maskrow && maskrow[col] == PBM_WHITE ) - pixelrow[col] = *transpColor; + if (transpColorP && maskrow && maskrow[col] == PBM_WHITE) + pixelrow[col] = *transpColorP; else PPM_ASSIGN(pixelrow[col], r, g, b); --count; } ppm_writeppmrow(stdout, pixelrow, cols, maxval, 0); - if( maskfile ) { + if (maskfile) { pbm_writepbmrow(maskfile, maskrow, cols, 0); - wrotemask = 1; + wrotemask = true; } } chunk_end(ifP, ID_BODY, remainingChunksize); @@ -1916,13 +1968,13 @@ PCHG_ConvertBig(PCHGHeader * const PCHG, static void -read_pchg(FILE * const ifp, +read_pchg(FILE * const ifP, IFF_ID const iffid, long const chunksize, ColorMap * const cmap) { if( cmap->mp_type >= MP_TYPE_PCHG ) { - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); } else { PCHGHeader PCHG; unsigned char *data; @@ -1936,15 +1988,15 @@ read_pchg(FILE * const ifp, remainingChunksize = chunksize; /* initial value */ - PCHG.Compression = get_big_short(ifp, iffid, &remainingChunksize); - PCHG.Flags = get_big_short(ifp, iffid, &remainingChunksize); - PCHG.StartLine = get_big_short(ifp, iffid, &remainingChunksize); - PCHG.LineCount = get_big_short(ifp, iffid, &remainingChunksize); - PCHG.ChangedLines= get_big_short(ifp, iffid, &remainingChunksize); - PCHG.MinReg = get_big_short(ifp, iffid, &remainingChunksize); - PCHG.MaxReg = get_big_short(ifp, iffid, &remainingChunksize); - PCHG.MaxChanges = get_big_short(ifp, iffid, &remainingChunksize); - PCHG.TotalChanges= get_big_long(ifp, iffid, &remainingChunksize); + PCHG.Compression = get_big_short(ifP, iffid, &remainingChunksize); + PCHG.Flags = get_big_short(ifP, iffid, &remainingChunksize); + PCHG.StartLine = get_big_short(ifP, iffid, &remainingChunksize); + PCHG.LineCount = get_big_short(ifP, iffid, &remainingChunksize); + PCHG.ChangedLines= get_big_short(ifP, iffid, &remainingChunksize); + PCHG.MinReg = get_big_short(ifP, iffid, &remainingChunksize); + PCHG.MaxReg = get_big_short(ifP, iffid, &remainingChunksize); + PCHG.MaxChanges = get_big_short(ifP, iffid, &remainingChunksize); + PCHG.TotalChanges= get_big_long(ifP, iffid, &remainingChunksize); #ifdef DEBUG pm_message("PCHG StartLine : %d", PCHG.StartLine); @@ -1959,17 +2011,17 @@ read_pchg(FILE * const ifp, long treesize, compsize; CompHdr.CompInfoSize = - get_big_long(ifp, iffid, &remainingChunksize); + get_big_long(ifP, iffid, &remainingChunksize); CompHdr.OriginalDataSize = - get_big_long(ifp, iffid, &remainingChunksize); + get_big_long(ifP, iffid, &remainingChunksize); treesize = CompHdr.CompInfoSize; MALLOCARRAY_NOFAIL(comptree, treesize); - read_bytes(ifp, treesize, comptree, iffid, &remainingChunksize); + read_bytes(ifP, treesize, comptree, iffid, &remainingChunksize); compsize = remainingChunksize; MALLOCARRAY_NOFAIL(compdata, compsize); - read_bytes(ifp, compsize, compdata, iffid, &remainingChunksize); + read_bytes(ifP, compsize, compdata, iffid, &remainingChunksize); datasize = CompHdr.OriginalDataSize; MALLOCARRAY_NOFAIL(data, datasize); @@ -1984,7 +2036,7 @@ read_pchg(FILE * const ifp, #endif datasize = remainingChunksize; MALLOCARRAY_NOFAIL(data, datasize); - read_bytes(ifp, datasize, data, iffid, &remainingChunksize); + read_bytes(ifP, datasize, data, iffid, &remainingChunksize); } if( PCHG.Flags & PCHGF_USE_ALPHA ) @@ -2023,7 +2075,7 @@ read_pchg(FILE * const ifp, ID2string(iffid)); } free(data); - chunk_end(ifp, iffid, remainingChunksize); + chunk_end(ifP, iffid, remainingChunksize); } } @@ -2048,7 +2100,7 @@ ignored_iffid(IFF_ID const iffid, static void -process_body( FILE * const ifp, +process_body( FILE * const ifP, long const chunksize, BitMapHeader * const bmhdP, ColorMap * const cmap, @@ -2058,19 +2110,19 @@ process_body( FILE * const ifp, DirectColor * const dcol, int * const viewportmodesP) { - if( bmhdP == NULL ) + if (bmhdP == NULL) pm_error("%s chunk without %s chunk", ID2string(ID_BODY), ID2string(ID_BMHD)); prepareCmap(bmhdP, cmap); pixelrow = ppm_allocrow(bmhdP->w); - if( maskfile ) { + if (maskfile) { maskrow = pbm_allocrow(bmhdP->w); pbm_writepbminit(maskfile, bmhdP->w, bmhdP->h, 0); } - if( typeid == ID_ILBM ) { + if (typeid == ID_ILBM) { int isdeep; MALLOCARRAY_NOFAIL(ilbmrow, RowBytes(bmhdP->w)); @@ -2084,27 +2136,27 @@ process_body( FILE * const ifp, } else isdeep = isdeepopt; - if( isdeep > 0 ) - deep_to_ppm(ifp, chunksize, bmhdP, cmap); - else if( dcol ) - dcol_to_ppm(ifp, chunksize, bmhdP, cmap, dcol); - else if( bmhdP->nPlanes > 8 ) { - if( bmhdP->nPlanes <= 16 && HAS_COLORMAP(cmap) ) - std_to_ppm(ifp, chunksize, bmhdP, cmap, *viewportmodesP); - else if( isdeep >= 0 && (bmhdP->nPlanes % 3 == 0) ) - deep_to_ppm(ifp, chunksize, bmhdP, cmap); - else if( bmhdP->nPlanes <= 16 ) + if (isdeep > 0) + deep_to_ppm(ifP, chunksize, bmhdP, cmap); + else if (dcol) + dcol_to_ppm(ifP, chunksize, bmhdP, cmap, dcol); + else if (bmhdP->nPlanes > 8) { + if (bmhdP->nPlanes <= 16 && HAS_COLORMAP(cmap)) + std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP); + else if (isdeep >= 0 && (bmhdP->nPlanes % 3 == 0)) + deep_to_ppm(ifP, chunksize, bmhdP, cmap); + else if (bmhdP->nPlanes <= 16) /* will be interpreted as grayscale */ - std_to_ppm(ifp, chunksize, bmhdP, cmap, *viewportmodesP); + std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP); else pm_error("don't know how to interpret %d-plane image", bmhdP->nPlanes); } else - std_to_ppm(ifp, chunksize, bmhdP, cmap, *viewportmodesP); + std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP); } else if( typeid == ID_PBM ) - ipbm_to_ppm(ifp, chunksize, bmhdP, cmap, *viewportmodesP); + ipbm_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP); else /* RGBN or RGB8 */ - rgbn_to_ppm(ifp, chunksize, bmhdP, cmap); + rgbn_to_ppm(ifP, chunksize, bmhdP, cmap); } @@ -2376,6 +2428,8 @@ main(int argc, char *argv[]) { if( argn != argc ) pm_usage(usage); + wrotemask = false; /* initial value */ + /* Read in the ILBM file. */ firstIffid = get_big_long(ifP, ID_FORM, NULL); diff --git a/converter/ppm/pc1toppm.c b/converter/ppm/pc1toppm.c index 5ba247e9..ec6678a4 100644 --- a/converter/ppm/pc1toppm.c +++ b/converter/ppm/pc1toppm.c @@ -170,7 +170,7 @@ writePpm(FILE * const ofP, is represented by 4 shorts (16 bit integers). The first is for Plane 0, the second for Plane 1, etc. Each short contains the bits for that plane for each of the 16 columns, - arranged from most signficant bit to least in increasing column + arranged from most significant bit to least in increasing column number. */ unsigned int col0ScreenIndex = cols/16*planes * row; diff --git a/converter/ppm/pcxtoppm.c b/converter/ppm/pcxtoppm.c index 25a81531..e252ba22 100644 --- a/converter/ppm/pcxtoppm.c +++ b/converter/ppm/pcxtoppm.c @@ -84,7 +84,7 @@ parseCommandLine ( int argc, char ** argv, was passed to us as the argv array. We also trash *argv. -----------------------------------------------------------------------------*/ optEntry *option_def = malloc( 100*sizeof( optEntry ) ); - /* Instructions to optParseOptions3 on how to parse our options. + /* Instructions to pm_optParseOptions3 on how to parse our options. */ optStruct3 opt; @@ -100,7 +100,7 @@ parseCommandLine ( int argc, char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3( &argc, argv, opt, sizeof(opt), 0 ); + pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0 ); /* Uses and sets argc, argv, and some of *cmdline_p and others. */ if (argc-1 < 1) @@ -129,9 +129,9 @@ struct pcxHeader { short Planes; short BitsPerPixel; short BytesPerLine; - /* Number of decompressed bytes each plane of each row of the image - takes. Due to padding (this is always an even number), there may - be garbage on the right end that isn't part of the image. + /* Number of decompressed bytes each plane of each row of the image + takes. Because of padding (this is always an even number), there + may be garbage on the right end that isn't part of the image. */ short PaletteInfo; short HorizontalResolution; @@ -532,14 +532,14 @@ pcx_256col_to_ppm(FILE * const ifP, } else cols = headerCols; - image = (unsigned char **)pm_allocarray(BytesPerLine, rows, - sizeof(unsigned char)); + MALLOCARRAY2(image, rows, BytesPerLine); + for (row = 0; row < rows; ++row) GetPCXRow(ifP, image[row], BytesPerLine); /* * 256 color images have their color map at the end of the file - * preceeded by a magic byte + * preceded by a magic byte */ colormapSignature = GetByte(ifP); if (colormapSignature != PCX_256_COLORS) diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c index 9a7d8e7c..828d5270 100644 --- a/converter/ppm/picttoppm.c +++ b/converter/ppm/picttoppm.c @@ -40,10 +40,10 @@ /* * Typical byte, 2 byte and 4 byte integers. */ -typedef unsigned char byte; -typedef char signed_byte; -typedef unsigned short word; -typedef unsigned long longword; +typedef unsigned char Byte; +typedef char SignedByte; +typedef unsigned short Word; +typedef unsigned long Longword; /* @@ -51,47 +51,47 @@ typedef unsigned long longword; */ struct Rect { - word top; - word left; - word bottom; - word right; + Word top; + Word left; + Word bottom; + Word right; }; struct pixMap { struct Rect Bounds; - word version; - word packType; - longword packSize; - longword hRes; - longword vRes; - word pixelType; - word pixelSize; - word cmpCount; - word cmpSize; - longword planeBytes; - longword pmTable; - longword pmReserved; + Word version; + Word packType; + Longword packSize; + Longword hRes; + Longword vRes; + Word pixelType; + Word pixelSize; + Word cmpCount; + Word cmpSize; + Longword planeBytes; + Longword pmTable; + Longword pmReserved; }; struct RGBColor { - word red; - word grn; - word blu; + Word red; + Word grn; + Word blu; }; struct Point { - word x; - word y; + Word x; + Word y; }; struct Pattern { - byte pix[64]; + Byte pix[64]; }; struct rgbPlanes { - word * red; - word * grn; - word * blu; + Word * red; + Word * grn; + Word * blu; }; struct canvas { @@ -102,8 +102,8 @@ typedef void (*transfer_func) (struct RGBColor* src, struct RGBColor* dst); static const char * stage; static struct Rect picFrame; -static word rowlen; -static word collen; +static Word rowlen; +static Word collen; static int verbose; static int fullres; static int recognize_comment; @@ -121,23 +121,23 @@ static struct Rect clip_rect; static struct Rect cur_rect; static struct Point current; static struct Pattern pen_pat; -static word pen_width; -static word pen_height; -static word pen_mode; +static Word pen_width; +static Word pen_height; +static Word pen_mode; static transfer_func pen_trf; -static word text_font; -static byte text_face; -static word text_mode; +static Word text_font; +static Byte text_face; +static Word text_mode; static transfer_func text_trf; -static word text_size; +static Word text_size; static struct font* tfont; /* state for magic printer comments */ static int ps_text; -static byte ps_just; -static byte ps_flip; -static word ps_rotation; -static byte ps_linespace; +static Byte ps_just; +static Byte ps_flip; +static Word ps_rotation; +static Byte ps_linespace; static int ps_cent_x; static int ps_cent_y; static int ps_cent_set; @@ -277,6 +277,10 @@ typedef void (drawFn)(struct canvas *, blitList *, int); struct opdef { const char* name; int len; + /* If non-negative, this is the length of the argument of the + instruction. If negative, it has special meaning; WORD_LEN + is the only value negative value. + */ drawFn * impl; const char* description; }; @@ -291,11 +295,11 @@ struct opdef { */ /* for reserved opcodes of known length */ -#define res(length) \ +#define RESERVED_OP(length) \ { "reserved", (length), NULL, "reserved for Apple use" } /* for reserved opcodes of length determined by a function */ -#define resf(skipfunction) \ +#define RESERVED_OP_F(skipfunction) \ { "reserved", NA, (skipfunction), "reserved for Apple use" } /* seems like RGB colors are 6 bytes, but Apple says they're variable */ @@ -308,8 +312,8 @@ static int align = 0; -static byte -read_byte(void) { +static Byte +readByte(void) { int c; if ((c = fgetc(ifp)) == EOF) @@ -321,52 +325,52 @@ read_byte(void) { -static word -read_word(void) { - byte b; +static Word +readWord(void) { - b = read_byte(); + Byte const hi = readByte(); + Byte const lo = readByte(); - return (b << 8) | read_byte(); + return (hi << 8) | (lo << 0); } -static void read_point(struct Point * const p) { - p->y = read_word(); - p->x = read_word(); +static void readPoint(struct Point * const p) { + p->y = readWord(); + p->x = readWord(); } -static longword -read_long(void) { - word i; +static Longword +readLong(void) { + Word const hi = readWord(); + Word const lo = readWord(); - i = read_word(); - return (i << 16) | read_word(); + return (hi << 16) | (lo << 0); } -static signed_byte -read_signed_byte(void) { - return (signed_byte)read_byte(); +static SignedByte +readSignedByte(void) { + return (SignedByte)readByte(); } static void -read_short_point(struct Point * const p) { - p->x = read_signed_byte(); - p->y = read_signed_byte(); +readShortPoint(struct Point * const p) { + p->x = readSignedByte(); + p->y = readSignedByte(); } static void skip(int const byteCount) { - static byte buf[1024]; + static Byte buf[1024]; int n; align += byteCount; @@ -461,7 +465,7 @@ const_name(const struct const_name * const table, static void -picComment(word const type, +picComment(Word const type, int const length) { unsigned int remainingLength; @@ -470,10 +474,10 @@ picComment(word const type, case 150: if (verbose) pm_message("TextBegin"); if (length >= 6) { - ps_just = read_byte(); - ps_flip = read_byte(); - ps_rotation = read_word(); - ps_linespace = read_byte(); + ps_just = readByte(); + ps_flip = readByte(); + ps_rotation = readWord(); + ps_linespace = readByte(); remainingLength = length - 5; if (recognize_comment) ps_text = 1; @@ -506,11 +510,11 @@ picComment(word const type, if (length < 8) remainingLength = length; else { - ps_cent_y = read_word(); + ps_cent_y = readWord(); if (ps_cent_y > 32767) ps_cent_y -= 65536; skip(2); /* ignore fractional part */ - ps_cent_x = read_word(); + ps_cent_x = readWord(); if (ps_cent_x > 32767) ps_cent_x -= 65536; skip(2); /* ignore fractional part */ @@ -621,7 +625,7 @@ ShortComment(struct canvas * const canvasP, blitList * const blitListP, int const version) { - picComment(read_word(), 0); + picComment(readWord(), 0); } @@ -633,10 +637,10 @@ LongComment(struct canvas * const canvasP, blitList * const blitListP, int const version) { - word type; + Word type; - type = read_word(); - picComment(type, read_word()); + type = readWord(); + picComment(type, readWord()); } @@ -649,7 +653,7 @@ skip_poly_or_region(struct canvas * const canvasP, int const version) { stage = "skipping polygon or region"; - skip(read_word() - 2); + skip(readWord() - 2); } @@ -788,12 +792,12 @@ dumpRect(const char * const label, static void -read_rect(struct Rect * const r) { +readRect(struct Rect * const r) { - r->top = read_word(); - r->left = read_word(); - r->bottom = read_word(); - r->right = read_word(); + r->top = readWord(); + r->left = readWord(); + r->bottom = readWord(); + r->right = readWord(); if (r->top > r->bottom || r->right < r->left) dumpRect("Invalid rectangle", *r); @@ -1196,7 +1200,7 @@ doDiffSize(struct Rect const clipsrc, unsigned int const dstadd = dstwid - xsize; - FILE * pnmscalePipeP; + FILE * pamscalePipeP; const char * command; FILE * scaled; int cols, rows, format; @@ -1205,9 +1209,9 @@ doDiffSize(struct Rect const clipsrc, pixel * rowp; FILE * tempFileP; const char * tempFilename; - word * reddst; - word * grndst; - word * bludst; + Word * reddst; + Word * grndst; + Word * bludst; reddst = dst.red; /* initial value */ grndst = dst.grn; /* initial value */ @@ -1217,19 +1221,19 @@ doDiffSize(struct Rect const clipsrc, pm_close(tempFileP); - asprintfN(&command, "pnmscale -xsize %d -ysize %d > %s", - rectwidth(&clipdst), rectheight(&clipdst), tempFilename); + pm_asprintf(&command, "pamscale -xsize %d -ysize %d > %s", + rectwidth(&clipdst), rectheight(&clipdst), tempFilename); pm_message("running command '%s'", command); - pnmscalePipeP = popen(command, "w"); - if (pnmscalePipeP == NULL) + pamscalePipeP = popen(command, "w"); + if (pamscalePipeP == NULL) pm_error("cannot execute command '%s' popen() errno = %s (%d)", command, strerror(errno), errno); - strfree(command); + pm_strfree(command); - fprintf(pnmscalePipeP, "P6\n%d %d\n%d\n", + fprintf(pamscalePipeP, "P6\n%d %d\n%d\n", rectwidth(&clipsrc), rectheight(&clipsrc), PPM_MAXMAXVAL); switch (pixSize) { @@ -1241,9 +1245,9 @@ doDiffSize(struct Rect const clipsrc, for (colNumber = 0; colNumber < xsize; ++colNumber) { unsigned int const colorIndex = row[colNumber]; struct RGBColor * const ct = &color_map[colorIndex]; - fputc(redepth(ct->red, 65535L), pnmscalePipeP); - fputc(redepth(ct->grn, 65535L), pnmscalePipeP); - fputc(redepth(ct->blu, 65535L), pnmscalePipeP); + fputc(redepth(ct->red, 65535L), pamscalePipeP); + fputc(redepth(ct->grn, 65535L), pamscalePipeP); + fputc(redepth(ct->blu, 65535L), pamscalePipeP); } } } @@ -1255,9 +1259,9 @@ doDiffSize(struct Rect const clipsrc, unsigned int colNumber; for (colNumber = 0; colNumber < xsize; ++colNumber) { struct RGBColor const color = decode16(&row[colNumber * 2]); - fputc(redepth(color.red, 32), pnmscalePipeP); - fputc(redepth(color.grn, 32), pnmscalePipeP); - fputc(redepth(color.blu, 32), pnmscalePipeP); + fputc(redepth(color.red, 32), pamscalePipeP); + fputc(redepth(color.grn, 32), pamscalePipeP); + fputc(redepth(color.blu, 32), pamscalePipeP); } } } @@ -1274,17 +1278,17 @@ doDiffSize(struct Rect const clipsrc, unsigned int colNumber; for (colNumber = 0; colNumber < xsize; ++colNumber) { - fputc(redepth(redPlane[colNumber], 256), pnmscalePipeP); - fputc(redepth(grnPlane[colNumber], 256), pnmscalePipeP); - fputc(redepth(bluPlane[colNumber], 256), pnmscalePipeP); + fputc(redepth(redPlane[colNumber], 256), pamscalePipeP); + fputc(redepth(grnPlane[colNumber], 256), pamscalePipeP); + fputc(redepth(bluPlane[colNumber], 256), pamscalePipeP); } } } break; } - if (pclose(pnmscalePipeP)) - pm_error("pnmscale failed. pclose() returned Errno %s (%d)", + if (pclose(pamscalePipeP)) + pm_error("pamscale failed. pclose() returned Errno %s (%d)", strerror(errno), errno); ppm_readppminit(scaled = pm_openr(tempFilename), &cols, &rows, @@ -1331,7 +1335,7 @@ doDiffSize(struct Rect const clipsrc, pm_close(scaled); ppm_freerow(row); - strfree(tempFilename); + pm_strfree(tempFilename); unlink(tempFilename); } @@ -1707,9 +1711,9 @@ allocPlanes(unsigned int const width, pm_error("not enough memory to hold picture"); /* initialize background to white */ - memset(planes.red, 255, planelen * sizeof(word)); - memset(planes.grn, 255, planelen * sizeof(word)); - memset(planes.blu, 255, planelen * sizeof(word)); + memset(planes.red, 255, planelen * sizeof(Word)); + memset(planes.grn, 255, planelen * sizeof(Word)); + memset(planes.blu, 255, planelen * sizeof(Word)); *planesP = planes; } @@ -1727,7 +1731,7 @@ freePlanes(struct rgbPlanes const planes) { static unsigned char -compact(word const input) { +compact(Word const input) { return (input >> 8) & 0xff; } @@ -1913,41 +1917,49 @@ outputPpm(FILE * const ofP, * All data in version 2 is 2-byte word aligned. Odd size data * is padded with a null. */ -static word +static Word get_op(int const version) { if ((align & 1) && version == 2) { stage = "aligning for opcode"; - read_byte(); + readByte(); } stage = "reading opcode"; if (version == 1) - return read_byte(); + return readByte(); else - return read_word(); + return readWord(); } -static drawFn Clip; +static drawFn ClipRgn; static void -Clip(struct canvas * const canvasP, - blitList * const blitListP, - int const version) { +ClipRgn(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + + Word const len = readWord(); + /* Length in bytes of the parameter (including this word) */ - word len; + if (len == 10) { /* null rgn */ + /* Parameter is 2 bytes of length, 8 bytes of rectangle corners */ - len = read_word(); + /* In March 2011, I saw a supposed PICT file (reported to work with + Apple pictureViewer) with what looked like signed numbers for the + rectangle: (-32767,-32767), (32767, 32767). This code has always + assumed all words in a PICT are unsigned. But even when I changed + it to accept this clip rectangle, this program found the image to + have an invalid raster. + */ - if (len == 0x000a) { /* null rgn */ - read_rect(&clip_rect); + readRect(&clip_rect); /* XXX should clip this by picFrame */ if (verbose) dumpRect("clipping to", clip_rect); - } - else + } else skip(len - 2); } @@ -1960,31 +1972,31 @@ OpColor(struct canvas * const canvasP, blitList * const blitListP, int const version) { - op_color.red = read_word(); - op_color.grn = read_word(); - op_color.blu = read_word(); + op_color.red = readWord(); + op_color.grn = readWord(); + op_color.blu = readWord(); } static void -read_pixmap(struct pixMap * const p) { +readPixmap(struct pixMap * const p) { stage = "getting pixMap header"; - read_rect(&p->Bounds); - p->version = read_word(); - p->packType = read_word(); - p->packSize = read_long(); - p->hRes = read_long(); - p->vRes = read_long(); - p->pixelType = read_word(); - p->pixelSize = read_word(); - p->cmpCount = read_word(); - p->cmpSize = read_word(); - p->planeBytes = read_long(); - p->pmTable = read_long(); - p->pmReserved = read_long(); + readRect(&p->Bounds); + p->version = readWord(); + p->packType = readWord(); + p->packSize = readLong(); + p->hRes = readLong(); + p->vRes = readLong(); + p->pixelType = readWord(); + p->pixelSize = readWord(); + p->cmpCount = readWord(); + p->cmpSize = readWord(); + p->planeBytes = readLong(); + p->pmTable = readLong(); + p->pmReserved = readLong(); if (verbose) { pm_message("pixelType: %d", p->pixelType); @@ -2007,19 +2019,19 @@ read_pixmap(struct pixMap * const p) { static struct RGBColor* -read_color_table(void) { - longword ctSeed; - word ctFlags; - word ctSize; - word val; +readColorTable(void) { + Longword ctSeed; + Word ctFlags; + Word ctSize; + Word val; int i; struct RGBColor* color_table; stage = "getting color table info"; - ctSeed = read_long(); - ctFlags = read_word(); - ctSize = read_word(); + ctSeed = readLong(); + ctFlags = readWord(); + ctSize = readWord(); if (verbose) { pm_message("ctSeed: %ld", ctSeed); @@ -2034,7 +2046,7 @@ read_color_table(void) { pm_error("no memory for color table"); for (i = 0; i <= ctSize; i++) { - val = read_word(); + val = readWord(); /* The indices in a device color table are bogus and usually == 0. * so I assume we allocate up the list of colors in order. */ @@ -2042,9 +2054,9 @@ read_color_table(void) { val = i; if (val > ctSize) pm_error("pixel value greater than color table size"); - color_table[val].red = read_word(); - color_table[val].grn = read_word(); - color_table[val].blu = read_word(); + color_table[val].red = readWord(); + color_table[val].grn = readWord(); + color_table[val].blu = readWord(); if (verbose > 1) pm_message("Color %3u: [%u,%u,%u]", val, @@ -2531,7 +2543,7 @@ interpretCompressedLine(unsigned char * const linebuf, So with 200 being the cutoff, it's actually impossible to represent some 16 bpp images with 200 pixels per row. - We have not been able to find an offical spec for PICT. + We have not been able to find an official spec for PICT. Some day, we may have to make a user option for this. */ @@ -2573,9 +2585,9 @@ unpackCompressedBits(FILE * const ifP, unsigned int linelen; if (llsize == 2) - linelen = read_word(); + linelen = readWord(); else - linelen = read_byte(); + linelen = readByte(); reportValidateCompressedLineLen(row, linelen, raster.rowSize); @@ -2598,7 +2610,7 @@ unpackCompressedBits(FILE * const ifP, static void unpackbits(FILE * const ifP, struct Rect * const boundsP, - word const rowBytesArg, + Word const rowBytesArg, int const bitsPerPixel, struct raster * const rasterP) { @@ -2633,7 +2645,7 @@ unpackbits(FILE * const ifP, static void -interpretRowBytesWord(word const rowBytesWord, +interpretRowBytesWord(Word const rowBytesWord, bool * const pixMapP, unsigned int * const rowBytesP) { @@ -2651,13 +2663,13 @@ interpretRowBytesWord(word const rowBytesWord, * a pattern in the fabled complete version. */ static void -read_pattern(void) { +readPattern(void) { - word PatType; + Word PatType; stage = "Reading a pattern"; - PatType = read_word(); + PatType = readWord(); switch (PatType) { case 2: @@ -2665,7 +2677,7 @@ read_pattern(void) { skip(5); /* RGB for pattern */ break; case 1: { - word rowBytesWord; + Word rowBytesWord; bool pixMap; unsigned int rowBytes; struct pixMap p; @@ -2673,16 +2685,16 @@ read_pattern(void) { struct RGBColor * ct; skip(8); /* old pattern data */ - rowBytesWord = read_word(); + rowBytesWord = readWord(); interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes); - read_pixmap(&p); - ct = read_color_table(); + readPixmap(&p); + ct = readColorTable(); unpackbits(ifp, &p.Bounds, rowBytes, p.pixelSize, &raster); freeRaster(raster); free(ct); } break; default: - pm_error("unknown pattern type in read_pattern"); + pm_error("unknown pattern type in readPattern"); } } @@ -2697,7 +2709,7 @@ BkPixPat(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_pattern(); + readPattern(); } @@ -2709,7 +2721,7 @@ PnPixPat(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_pattern(); + readPattern(); } @@ -2721,13 +2733,13 @@ FillPixPat(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_pattern(); + readPattern(); } static void -read_8x8_pattern(struct Pattern * const pat) { +read8x8Pattern(struct Pattern * const pat) { unsigned char buf[8]; unsigned char * exp; unsigned int len; @@ -2756,7 +2768,7 @@ BkPat(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_8x8_pattern(&bkpat); + read8x8Pattern(&bkpat); } @@ -2768,7 +2780,7 @@ PnPat(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_8x8_pattern(&pen_pat); + read8x8Pattern(&pen_pat); } @@ -2780,7 +2792,7 @@ FillPat(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_8x8_pattern(&fillpat); + read8x8Pattern(&fillpat); } @@ -2792,8 +2804,8 @@ PnSize(struct canvas * const canvasP, blitList * const blitListP, int const version) { - pen_height = read_word(); - pen_width = read_word(); + pen_height = readWord(); + pen_width = readWord(); if (verbose) pm_message("pen size %d x %d", pen_width, pen_height); } @@ -2807,7 +2819,7 @@ PnMode(struct canvas * const canvasP, blitList * const blitListP, int const version) { - pen_mode = read_word(); + pen_mode = readWord(); if (pen_mode >= 8 && pen_mode < 15) pen_mode -= 8; @@ -2821,10 +2833,10 @@ PnMode(struct canvas * const canvasP, static void -read_rgb(struct RGBColor * const rgb) { - rgb->red = read_word(); - rgb->grn = read_word(); - rgb->blu = read_word(); +readRgb(struct RGBColor * const rgb) { + rgb->red = readWord(); + rgb->grn = readWord(); + rgb->blu = readWord(); } @@ -2836,7 +2848,7 @@ RGBFgCol(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_rgb(&foreground); + readRgb(&foreground); if (verbose) pm_message("foreground now [%d,%d,%d]", foreground.red, foreground.grn, foreground.blu); @@ -2851,7 +2863,7 @@ RGBBkCol(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_rgb(&background); + readRgb(&background); if (verbose) pm_message("background now [%d,%d,%d]", background.red, background.grn, background.blu); @@ -2869,7 +2881,7 @@ draw_pixel(struct canvas * const canvasP, transfer_func trf) { if (x < clip_rect.left || x >= clip_rect.right || - y < clip_rect.top || y >= clip_rect.bottom) { + y < clip_rect.top || y >= clip_rect.bottom) { } else { unsigned int const i = PIXEL_INDEX(x, y); @@ -3011,8 +3023,8 @@ Line(struct canvas * const canvasP, int const version) { struct Point p1; - read_point(&p1); - read_point(¤t); + readPoint(&p1); + readPoint(¤t); if (verbose) pm_message("(%d,%d) to (%d, %d)", p1.x,p1.y,current.x,current.y); @@ -3029,7 +3041,7 @@ LineFrom(struct canvas * const canvasP, int const version) { struct Point p1; - read_point(&p1); + readPoint(&p1); if (verbose) pm_message("(%d,%d) to (%d, %d)", current.x, current.y, p1.x, p1.y); @@ -3050,8 +3062,8 @@ ShortLine(struct canvas * const canvasP, int const version) { struct Point p1; - read_point(&p1); - read_short_point(¤t); + readPoint(&p1); + readShortPoint(¤t); if (verbose) pm_message("(%d,%d) delta (%d, %d)", p1.x, p1.y, current.x, current.y); current.x += p1.x; @@ -3071,7 +3083,7 @@ ShortLineFrom(struct canvas * const canvasP, int const version) { struct Point p1; - read_short_point(&p1); + readShortPoint(&p1); if (verbose) pm_message("(%d,%d) delta (%d, %d)", current.x,current.y,p1.x,p1.y); @@ -3108,7 +3120,7 @@ paintRect(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_rect(&cur_rect); + readRect(&cur_rect); if (!blitListP) do_paintRect(canvasP, cur_rect); } @@ -3159,7 +3171,7 @@ frameRect(struct canvas * const canvasP, blitList * const blitListP, int const version) { - read_rect(&cur_rect); + readRect(&cur_rect); if (!blitListP) do_frameRect(canvasP, cur_rect); } @@ -3179,7 +3191,7 @@ frameSameRect(struct canvas * const canvasP, -/* a stupid shell sort - I'm so embarassed */ +/* a stupid shell sort - I'm so embarrassed */ static void poly_sort(int const sort_index, struct Point points[]) { @@ -3326,11 +3338,11 @@ paintPoly(struct canvas * const canvasP, struct Rect bb; struct Point pts[100]; - int i, np = (read_word() - 10) >> 2; + int i, np = (readWord() - 10) >> 2; - read_rect(&bb); + readRect(&bb); for (i=0; i<np; ++i) - read_point(&pts[i]); + readPoint(&pts[i]); /* scan convert poly ... */ if (!blitListP) @@ -3346,7 +3358,7 @@ PnLocHFrac(struct canvas * const canvasP, blitList * const blitListP, int const version) { - word frac = read_word(); + Word frac = readWord(); if (verbose) pm_message("PnLocHFrac = %d", frac); @@ -3361,7 +3373,7 @@ TxMode(struct canvas * const canvasP, blitList * const blitListP, int const version) { - text_mode = read_word(); + text_mode = readWord(); if (text_mode >= 8 && text_mode < 15) text_mode -= 8; @@ -3382,7 +3394,7 @@ TxFont(struct canvas * const canvasP, blitList * const blitListP, int const version) { - text_font = read_word(); + text_font = readWord(); if (verbose) pm_message("text font %s", const_name(font_name, text_font)); } @@ -3396,7 +3408,7 @@ TxFace(struct canvas * const canvasP, blitList * const blitListP, int const version) { - text_face = read_byte(); + text_face = readByte(); if (verbose) pm_message("text face %d", text_face); } @@ -3410,7 +3422,7 @@ TxSize(struct canvas * const canvasP, blitList * const blitListP, int const version) { - text_size = read_word(); + text_size = readWord(); if (verbose) pm_message("text size %d", text_size); } @@ -3420,7 +3432,7 @@ TxSize(struct canvas * const canvasP, static void skip_text(blitList * const blitListP) { - skip(read_byte()); + skip(readByte()); blitListP->unblittableText = true; } @@ -3504,11 +3516,11 @@ rotate(int * const x, static void do_ps_text(struct canvas * const canvasP, - word const tx, - word const ty) { + Word const tx, + Word const ty) { int len, width, i, w, h, x, y, rx, ry, o; - byte str[256], ch; + Byte str[256], ch; struct glyph* glyph; current.x = tx; @@ -3520,12 +3532,12 @@ do_ps_text(struct canvas * const canvasP, ps_cent_set = 1; } - len = read_byte(); + len = readByte(); /* XXX this width calculation is not completely correct */ width = 0; for (i = 0; i < len; i++) { - ch = str[i] = read_byte(); + ch = str[i] = readByte(); if (tfont->glyph[ch]) width += tfont->glyph[ch]->xadd; } @@ -3574,8 +3586,8 @@ do_ps_text(struct canvas * const canvasP, static void do_text(struct canvas * const canvasP, blitList * const blitListP, - word const startx, - word const starty) { + Word const startx, + Word const starty) { if (blitListP) skip_text(blitListP); @@ -3587,12 +3599,12 @@ do_text(struct canvas * const canvasP, do_ps_text(canvasP, startx, starty); else { int len; - word x, y; + Word x, y; x = startx; y = starty; - for (len = read_byte(); len > 0; --len) { - struct glyph* const glyph = tfont->glyph[read_byte()]; + for (len = readByte(); len > 0; --len) { + struct glyph* const glyph = tfont->glyph[readByte()]; if (glyph) { int dy; int h; @@ -3628,7 +3640,7 @@ LongText(struct canvas * const canvasP, struct Point p; - read_point(&p); + readPoint(&p); do_text(canvasP, blitListP, p.x, p.y); } @@ -3642,7 +3654,7 @@ DHText(struct canvas * const canvasP, blitList * const blitListP, int const version) { - current.x += read_byte(); + current.x += readByte(); do_text(canvasP, blitListP, current.x, current.y); } @@ -3656,7 +3668,7 @@ DVText(struct canvas * const canvasP, blitList * const blitListP, int const version) { - current.y += read_byte(); + current.y += readByte(); do_text(canvasP, blitListP, current.x, current.y); } @@ -3669,10 +3681,10 @@ static void DHDVText(struct canvas * const canvasP, blitList * const blitListP, int const version) { - byte dh, dv; + Byte dh, dv; - dh = read_byte(); - dv = read_byte(); + dh = readByte(); + dv = readByte(); if (verbose) pm_message("dh, dv = %d, %d", dh, dv); @@ -3686,7 +3698,7 @@ DHDVText(struct canvas * const canvasP, /* - * This could use read_pixmap, but I'm too lazy to hack read_pixmap. + * This could use readPixmap, but I'm too lazy to hack readPixmap. */ static void @@ -3699,36 +3711,36 @@ directBits(struct canvas * const canvasP, struct Rect srcRect; struct Rect dstRect; struct raster raster; - word mode; + Word mode; unsigned int rectWidth; /* skip fake len, and fake EOF */ skip(4); /* Ptr baseAddr == 0x000000ff */ - read_word(); /* version */ - read_rect(&p.Bounds); + readWord(); /* version */ + readRect(&p.Bounds); rectWidth = p.Bounds.right - p.Bounds.left; - p.packType = read_word(); - p.packSize = read_long(); - p.hRes = read_long(); - p.vRes = read_long(); - p.pixelType = read_word(); - p.pixelSize = read_word(); - p.pixelSize = read_word(); /* XXX twice??? */ - p.cmpCount = read_word(); - p.cmpSize = read_word(); - p.planeBytes = read_long(); - p.pmTable = read_long(); - p.pmReserved = read_long(); - - read_rect(&srcRect); + p.packType = readWord(); + p.packSize = readLong(); + p.hRes = readLong(); + p.vRes = readLong(); + p.pixelType = readWord(); + p.pixelSize = readWord(); + p.pixelSize = readWord(); /* XXX twice??? */ + p.cmpCount = readWord(); + p.cmpSize = readWord(); + p.planeBytes = readLong(); + p.pmTable = readLong(); + p.pmReserved = readLong(); + + readRect(&srcRect); if (verbose) dumpRect("source rectangle:", srcRect); - read_rect(&dstRect); + readRect(&dstRect); if (verbose) dumpRect("destination rectangle:", dstRect); - mode = read_word(); + mode = readWord(); if (verbose) pm_message("transfer mode = %s", const_name(transfer_name, mode)); @@ -3776,38 +3788,38 @@ static void do_pixmap(struct canvas * const canvasP, blitList * const blitListP, int const version, - word const rowBytes, + Word const rowBytes, int const is_region) { /*---------------------------------------------------------------------------- Do a paletted image. -----------------------------------------------------------------------------*/ - word mode; + Word mode; struct pixMap p; struct raster raster; struct RGBColor * color_table; struct Rect srcRect; struct Rect dstRect; - read_pixmap(&p); + readPixmap(&p); if (verbose) pm_message("%u x %u paletted image", p.Bounds.right - p.Bounds.left, p.Bounds.bottom - p.Bounds.top); - color_table = read_color_table(); + color_table = readColorTable(); - read_rect(&srcRect); + readRect(&srcRect); if (verbose) dumpRect("source rectangle:", srcRect); - read_rect(&dstRect); + readRect(&dstRect); if (verbose) dumpRect("destination rectangle:", dstRect); - mode = read_word(); + mode = readWord(); if (verbose) pm_message("transfer mode = %s", const_name(transfer_name, mode)); @@ -3843,7 +3855,7 @@ do_bitmap(FILE * const ifP, struct Rect Bounds; struct Rect srcRect; struct Rect dstRect; - word mode; + Word mode; struct raster raster; /* This raster contains padding on the right to make a multiple of 16 pixels per row. @@ -3851,10 +3863,10 @@ do_bitmap(FILE * const ifP, static struct RGBColor color_table[] = { {65535L, 65535L, 65535L}, {0, 0, 0} }; - read_rect(&Bounds); - read_rect(&srcRect); - read_rect(&dstRect); - mode = read_word(); + readRect(&Bounds); + readRect(&srcRect); + readRect(&dstRect); + mode = readWord(); if (verbose) pm_message("transfer mode = %s", const_name(transfer_name, mode)); @@ -3880,12 +3892,12 @@ BitsRect(struct canvas * const canvasP, blitList * const blitListP, int const version) { - word rowBytesWord; + Word rowBytesWord; bool pixMap; unsigned int rowBytes; stage = "Reading rowBytes word for bitsrect"; - rowBytesWord = read_word(); + rowBytesWord = readWord(); interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes); @@ -3904,12 +3916,12 @@ BitsRegion(struct canvas * const canvasP, blitList * const blitListP, int const version) { - word rowBytesWord; + Word rowBytesWord; bool pixMap; unsigned int rowBytes; stage = "Reading rowBytes for bitsregion"; - rowBytesWord = read_word(); + rowBytesWord = readWord(); interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes); @@ -3927,7 +3939,7 @@ BitsRegion(struct canvas * const canvasP, */ static struct opdef const optable[] = { /* 0x00 */ { "NOP", 0, NULL, "nop" }, -/* 0x01 */ { "Clip", NA, Clip, "clip" }, +/* 0x01 */ { "ClipRgn", NA, ClipRgn, "clip region" }, /* 0x02 */ { "BkPat", 8, BkPat, "background pattern" }, /* 0x03 */ { "TxFont", 2, TxFont, "text font (word)" }, /* 0x04 */ { "TxFace", 1, TxFace, "text face (byte)" }, @@ -3949,9 +3961,9 @@ static struct opdef const optable[] = { /* 0x14 */ { "FillPixPat", NA, FillPixPat, "color fill pattern" }, /* 0x15 */ { "PnLocHFrac", 2, PnLocHFrac, "fractional pen position" }, /* 0x16 */ { "ChExtra", 2, NULL, "extra for each character" }, -/* 0x17 */ res(0), -/* 0x18 */ res(0), -/* 0x19 */ res(0), +/* 0x17 */ RESERVED_OP(0), +/* 0x18 */ RESERVED_OP(0), +/* 0x19 */ RESERVED_OP(0), /* 0x1a */ { "RGBFgCol", RGB_LEN, RGBFgCol, "RGB foreColor" }, /* 0x1b */ { "RGBBkCol", RGB_LEN, RGBBkCol, "RGB backColor" }, /* 0x1c */ { "HiliteMode", 0, NULL, "hilite mode flag" }, @@ -3963,134 +3975,134 @@ static struct opdef const optable[] = { /* 0x22 */ { "ShortLine", 6, ShortLine, "pnLoc (point, dh, dv (-128 .. 127))" }, /* 0x23 */ { "ShortLineFrom", 2, ShortLineFrom, "dh, dv (-128 .. 127)" }, -/* 0x24 */ res(WORD_LEN), -/* 0x25 */ res(WORD_LEN), -/* 0x26 */ res(WORD_LEN), -/* 0x27 */ res(WORD_LEN), +/* 0x24 */ RESERVED_OP(WORD_LEN), +/* 0x25 */ RESERVED_OP(WORD_LEN), +/* 0x26 */ RESERVED_OP(WORD_LEN), +/* 0x27 */ RESERVED_OP(WORD_LEN), /* 0x28 */ { "LongText", NA, LongText, "txLoc (point), count (0..255), text" }, /* 0x29 */ { "DHText", NA, DHText, "dh (0..255), count (0..255), text" }, /* 0x2a */ { "DVText", NA, DVText, "dv (0..255), count (0..255), text" }, /* 0x2b */ { "DHDVText", NA, DHDVText, "dh, dv (0..255), count (0..255), text" }, -/* 0x2c */ res(WORD_LEN), -/* 0x2d */ res(WORD_LEN), -/* 0x2e */ res(WORD_LEN), -/* 0x2f */ res(WORD_LEN), +/* 0x2c */ RESERVED_OP(WORD_LEN), +/* 0x2d */ RESERVED_OP(WORD_LEN), +/* 0x2e */ RESERVED_OP(WORD_LEN), +/* 0x2f */ RESERVED_OP(WORD_LEN), /* 0x30 */ { "frameRect", 8, frameRect, "rect" }, /* 0x31 */ { "paintRect", 8, paintRect, "rect" }, /* 0x32 */ { "eraseRect", 8, NULL, "rect" }, /* 0x33 */ { "invertRect", 8, NULL, "rect" }, /* 0x34 */ { "fillRect", 8, NULL, "rect" }, -/* 0x35 */ res(8), -/* 0x36 */ res(8), -/* 0x37 */ res(8), +/* 0x35 */ RESERVED_OP(8), +/* 0x36 */ RESERVED_OP(8), +/* 0x37 */ RESERVED_OP(8), /* 0x38 */ { "frameSameRect", 0, frameSameRect, "rect" }, /* 0x39 */ { "paintSameRect", 0, paintSameRect, "rect" }, /* 0x3a */ { "eraseSameRect", 0, NULL, "rect" }, /* 0x3b */ { "invertSameRect", 0, NULL, "rect" }, /* 0x3c */ { "fillSameRect", 0, NULL, "rect" }, -/* 0x3d */ res(0), -/* 0x3e */ res(0), -/* 0x3f */ res(0), +/* 0x3d */ RESERVED_OP(0), +/* 0x3e */ RESERVED_OP(0), +/* 0x3f */ RESERVED_OP(0), /* 0x40 */ { "frameRRect", 8, NULL, "rect" }, /* 0x41 */ { "paintRRect", 8, NULL, "rect" }, /* 0x42 */ { "eraseRRect", 8, NULL, "rect" }, /* 0x43 */ { "invertRRect", 8, NULL, "rect" }, /* 0x44 */ { "fillRRrect", 8, NULL, "rect" }, -/* 0x45 */ res(8), -/* 0x46 */ res(8), -/* 0x47 */ res(8), +/* 0x45 */ RESERVED_OP(8), +/* 0x46 */ RESERVED_OP(8), +/* 0x47 */ RESERVED_OP(8), /* 0x48 */ { "frameSameRRect", 0, NULL, "rect" }, /* 0x49 */ { "paintSameRRect", 0, NULL, "rect" }, /* 0x4a */ { "eraseSameRRect", 0, NULL, "rect" }, /* 0x4b */ { "invertSameRRect", 0, NULL, "rect" }, /* 0x4c */ { "fillSameRRect", 0, NULL, "rect" }, -/* 0x4d */ res(0), -/* 0x4e */ res(0), -/* 0x4f */ res(0), +/* 0x4d */ RESERVED_OP(0), +/* 0x4e */ RESERVED_OP(0), +/* 0x4f */ RESERVED_OP(0), /* 0x50 */ { "frameOval", 8, NULL, "rect" }, /* 0x51 */ { "paintOval", 8, NULL, "rect" }, /* 0x52 */ { "eraseOval", 8, NULL, "rect" }, /* 0x53 */ { "invertOval", 8, NULL, "rect" }, /* 0x54 */ { "fillOval", 8, NULL, "rect" }, -/* 0x55 */ res(8), -/* 0x56 */ res(8), -/* 0x57 */ res(8), +/* 0x55 */ RESERVED_OP(8), +/* 0x56 */ RESERVED_OP(8), +/* 0x57 */ RESERVED_OP(8), /* 0x58 */ { "frameSameOval", 0, NULL, "rect" }, /* 0x59 */ { "paintSameOval", 0, NULL, "rect" }, /* 0x5a */ { "eraseSameOval", 0, NULL, "rect" }, /* 0x5b */ { "invertSameOval", 0, NULL, "rect" }, /* 0x5c */ { "fillSameOval", 0, NULL, "rect" }, -/* 0x5d */ res(0), -/* 0x5e */ res(0), -/* 0x5f */ res(0), +/* 0x5d */ RESERVED_OP(0), +/* 0x5e */ RESERVED_OP(0), +/* 0x5f */ RESERVED_OP(0), /* 0x60 */ { "frameArc", 12, NULL, "rect, startAngle, arcAngle" }, /* 0x61 */ { "paintArc", 12, NULL, "rect, startAngle, arcAngle" }, /* 0x62 */ { "eraseArc", 12, NULL, "rect, startAngle, arcAngle" }, /* 0x63 */ { "invertArc", 12, NULL, "rect, startAngle, arcAngle" }, /* 0x64 */ { "fillArc", 12, NULL, "rect, startAngle, arcAngle" }, -/* 0x65 */ res(12), -/* 0x66 */ res(12), -/* 0x67 */ res(12), +/* 0x65 */ RESERVED_OP(12), +/* 0x66 */ RESERVED_OP(12), +/* 0x67 */ RESERVED_OP(12), /* 0x68 */ { "frameSameArc", 4, NULL, "rect, startAngle, arcAngle" }, /* 0x69 */ { "paintSameArc", 4, NULL, "rect, startAngle, arcAngle" }, /* 0x6a */ { "eraseSameArc", 4, NULL, "rect, startAngle, arcAngle" }, /* 0x6b */ { "invertSameArc", 4, NULL, "rect, startAngle, arcAngle" }, /* 0x6c */ { "fillSameArc", 4, NULL, "rect, startAngle, arcAngle" }, -/* 0x6d */ res(4), -/* 0x6e */ res(4), -/* 0x6f */ res(4), +/* 0x6d */ RESERVED_OP(4), +/* 0x6e */ RESERVED_OP(4), +/* 0x6f */ RESERVED_OP(4), /* 0x70 */ { "framePoly", NA, skip_poly_or_region, "poly" }, /* 0x71 */ { "paintPoly", NA, paintPoly, "poly" }, /* 0x72 */ { "erasePoly", NA, skip_poly_or_region, "poly" }, /* 0x73 */ { "invertPoly", NA, skip_poly_or_region, "poly" }, /* 0x74 */ { "fillPoly", NA, skip_poly_or_region, "poly" }, -/* 0x75 */ resf(skip_poly_or_region), -/* 0x76 */ resf(skip_poly_or_region), -/* 0x77 */ resf(skip_poly_or_region), +/* 0x75 */ RESERVED_OP_F(skip_poly_or_region), +/* 0x76 */ RESERVED_OP_F(skip_poly_or_region), +/* 0x77 */ RESERVED_OP_F(skip_poly_or_region), /* 0x78 */ { "frameSamePoly", 0, NULL, "poly (NYI)" }, /* 0x79 */ { "paintSamePoly", 0, NULL, "poly (NYI)" }, /* 0x7a */ { "eraseSamePoly", 0, NULL, "poly (NYI)" }, /* 0x7b */ { "invertSamePoly", 0, NULL, "poly (NYI)" }, /* 0x7c */ { "fillSamePoly", 0, NULL, "poly (NYI)" }, -/* 0x7d */ res(0), -/* 0x7e */ res(0), -/* 0x7f */ res(0), +/* 0x7d */ RESERVED_OP(0), +/* 0x7e */ RESERVED_OP(0), +/* 0x7f */ RESERVED_OP(0), /* 0x80 */ { "frameRgn", NA, skip_poly_or_region, "region" }, /* 0x81 */ { "paintRgn", NA, skip_poly_or_region, "region" }, /* 0x82 */ { "eraseRgn", NA, skip_poly_or_region, "region" }, /* 0x83 */ { "invertRgn", NA, skip_poly_or_region, "region" }, /* 0x84 */ { "fillRgn", NA, skip_poly_or_region, "region" }, -/* 0x85 */ resf(skip_poly_or_region), -/* 0x86 */ resf(skip_poly_or_region), -/* 0x87 */ resf(skip_poly_or_region), +/* 0x85 */ RESERVED_OP_F(skip_poly_or_region), +/* 0x86 */ RESERVED_OP_F(skip_poly_or_region), +/* 0x87 */ RESERVED_OP_F(skip_poly_or_region), /* 0x88 */ { "frameSameRgn", 0, NULL, "region (NYI)" }, /* 0x89 */ { "paintSameRgn", 0, NULL, "region (NYI)" }, /* 0x8a */ { "eraseSameRgn", 0, NULL, "region (NYI)" }, /* 0x8b */ { "invertSameRgn", 0, NULL, "region (NYI)" }, /* 0x8c */ { "fillSameRgn", 0, NULL, "region (NYI)" }, -/* 0x8d */ res(0), -/* 0x8e */ res(0), -/* 0x8f */ res(0), +/* 0x8d */ RESERVED_OP(0), +/* 0x8e */ RESERVED_OP(0), +/* 0x8f */ RESERVED_OP(0), /* 0x90 */ { "BitsRect", NA, BitsRect, "copybits, rect clipped" }, /* 0x91 */ { "BitsRgn", NA, BitsRegion, "copybits, rgn clipped" }, -/* 0x92 */ res(WORD_LEN), -/* 0x93 */ res(WORD_LEN), -/* 0x94 */ res(WORD_LEN), -/* 0x95 */ res(WORD_LEN), -/* 0x96 */ res(WORD_LEN), -/* 0x97 */ res(WORD_LEN), +/* 0x92 */ RESERVED_OP(WORD_LEN), +/* 0x93 */ RESERVED_OP(WORD_LEN), +/* 0x94 */ RESERVED_OP(WORD_LEN), +/* 0x95 */ RESERVED_OP(WORD_LEN), +/* 0x96 */ RESERVED_OP(WORD_LEN), +/* 0x97 */ RESERVED_OP(WORD_LEN), /* 0x98 */ { "PackBitsRect", NA, BitsRect, "packed copybits, rect clipped" }, /* 0x99 */ { "PackBitsRgn", NA, BitsRegion, "packed copybits, rgn clipped" }, /* 0x9a */ { "DirectBitsRect", NA, DirectBitsRect, "PixMap, srcRect, dstRect, int copymode, PixData" }, /* 0x9b */ { "DirectBitsRgn", NA, DirectBitsRgn, "PixMap, srcRect, dstRect, int copymode, maskRgn, PixData" }, -/* 0x9c */ res(WORD_LEN), -/* 0x9d */ res(WORD_LEN), -/* 0x9e */ res(WORD_LEN), -/* 0x9f */ res(WORD_LEN), +/* 0x9c */ RESERVED_OP(WORD_LEN), +/* 0x9d */ RESERVED_OP(WORD_LEN), +/* 0x9e */ RESERVED_OP(WORD_LEN), +/* 0x9f */ RESERVED_OP(WORD_LEN), /* 0xa0 */ { "ShortComment", 2, ShortComment, "kind (word)" }, /* 0xa1 */ { "LongComment", NA, LongComment, "kind (word), size (word), data" } @@ -4099,7 +4111,7 @@ static struct opdef const optable[] = { static void -processOpcode(word const opcode, +processOpcode(Word const opcode, struct canvas * const canvasP, blitList * const blitListP, unsigned int const version) { @@ -4118,13 +4130,14 @@ processOpcode(word const opcode, else if (optable[opcode].len >= 0) skip(optable[opcode].len); else { + /* It's a special length code */ switch (optable[opcode].len) { case WORD_LEN: { - word const len = read_word(); + Word const len = readWord(); skip(len); - } break; + } break; default: - pm_error("can't do length %u", optable[opcode].len); + pm_error("can't do length %d", optable[opcode].len); } } } else if (opcode == 0xc00) { @@ -4136,7 +4149,7 @@ processOpcode(word const opcode, stage = "skipping reserved"; if (verbose) pm_message("%s 0x%x", stage, opcode); - skip(read_word()); + skip(readWord()); } else if (opcode >= 0xb0 && opcode <= 0xcf) { /* just a reserved opcode, no data */ if (verbose) @@ -4145,21 +4158,21 @@ processOpcode(word const opcode, stage = "skipping reserved"; if (verbose) pm_message("%s 0x%x", stage, opcode); - skip(read_long()); + skip(readLong()); } else if (opcode >= 0x100 && opcode <= 0x7fff) { stage = "skipping reserved"; if (verbose) pm_message("%s 0x%x", stage, opcode); skip((opcode >> 7) & 255); } else if (opcode >= 0x8000 && opcode <= 0x80ff) { - /* just a reserved opcode */ + /* just a reserved opcode, no data */ if (verbose) pm_message("reserved 0x%x", opcode); } else if (opcode >= 0x8100) { stage = "skipping reserved"; if (verbose) pm_message("%s 0x%x", stage, opcode); - skip(read_long()); + skip(readLong()); } else pm_error("This program does not understand opcode 0x%04x", opcode); } @@ -4167,13 +4180,13 @@ processOpcode(word const opcode, static void -interpret_pict(FILE * const ofP) { +interpretPict(FILE * const ofP) { - byte ch; - word picSize; - word opcode; + Byte ch; + Word picSize; + Word opcode; unsigned int version; - int i; + unsigned int i; struct canvas canvas; blitList blitList; @@ -4188,13 +4201,13 @@ interpret_pict(FILE * const ofP) { text_trf = transfer(text_mode); stage = "Reading picture size"; - picSize = read_word(); + picSize = readWord(); if (verbose) pm_message("picture size = %u (0x%x)", picSize, picSize); stage = "reading picture frame"; - read_rect(&picFrame); + readRect(&picFrame); if (verbose) { dumpRect("Picture frame:", picFrame); @@ -4212,18 +4225,18 @@ interpret_pict(FILE * const ofP) { clip_rect = picFrame; } - while ((ch = read_byte()) == 0) + while ((ch = readByte()) == 0) ; if (ch != 0x11) pm_error("No version number"); - version = read_byte(); + version = readByte(); switch (version) { case 1: break; case 2: { - unsigned char const subcode = read_byte(); + unsigned char const subcode = readByte(); if (subcode != 0xff) pm_error("The only Version 2 PICT images this program " "undertands are subcode 0xff. This image has " @@ -4322,7 +4335,7 @@ main(int argc, char * argv[]) { skip(512); } - interpret_pict(stdout); + interpretPict(stdout); pm_close(stdout); diff --git a/converter/ppm/ppmtoacad.c b/converter/ppm/ppmtoacad.c index 4f927f02..b5ee4d65 100644 --- a/converter/ppm/ppmtoacad.c +++ b/converter/ppm/ppmtoacad.c @@ -20,10 +20,9 @@ */ #include <stdio.h> -#include "ppm.h" -#define TRUE 1 -#define FALSE 0 +#include "pm_c_util.h" +#include "ppm.h" #define EOS '\0' diff --git a/converter/ppm/ppmtoapplevol.c b/converter/ppm/ppmtoapplevol.c new file mode 100644 index 00000000..e1c7f2dc --- /dev/null +++ b/converter/ppm/ppmtoapplevol.c @@ -0,0 +1,95 @@ +/* ppmtoapplevol.c - read a portable pixmap and produce an Apple volume label + * + * Copyright 2011 Red Hat <mjg@redhat.com> + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "as is" without express or + * implied warranty. + */ + +#include "pm.h" +#include "ppm.h" + + + +static unsigned char const map[] = { + 0x00, 0xf6, 0xf7, 0x2a, 0xf8, 0xf9, 0x55, 0xfa, + 0xfb, 0x80, 0xfc, 0xfd, 0xab, 0xfe, 0xff, 0xd6 +}; + + + +static void +writeHeader(unsigned int const cols, + FILE * const ofP) { + + unsigned char header[5]; + + header[0] = 0x01; + header[1] = 0x00; + header[2] = cols; + header[3] = 0x00; + header[4] = 0x0c; + + fwrite(header, sizeof(header), 1, ofP); +} + + + +int +main (int argc, const char * argv[]) { + + const char * inputFilename; + FILE * ifP; + int rows, cols; + pixval maxval; + int format; + pixel * pixelrow; + unsigned int row; + + pm_proginit(&argc, argv); + + if (argc-1 > 1) + pm_error("Too many arguments: %u. There is at most one argument: " + "the input file name", argc-1); + + if (argc-1 >= 1) + inputFilename = argv[1]; + else + inputFilename = "-"; + + ifP = pm_openr(inputFilename); + + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); + + if (rows != 12) + pm_error("Input image must be 12 rows tall. Yours is %u", rows); + + writeHeader(cols, stdout); + + pixelrow = ppm_allocrow(cols); + + for (row = 0; row < rows; row++) { + unsigned int col; + + ppm_readppmrow(stdin, pixelrow, cols, maxval, format); + + for (col = 0; col < cols; ++col) { + unsigned int const maxval15Value = + ((unsigned int)PPM_GETR(pixelrow[col]) * 15 + maxval/2) / + maxval; + unsigned char const appleValue = + (unsigned char)map[15 - maxval15Value]; + fwrite(&appleValue, sizeof(appleValue), 1, stdout); + } + } + + ppm_freerow(pixelrow); + + pm_close(ifP); + + return 0; +} diff --git a/converter/ppm/ppmtoarbtxt.c b/converter/ppm/ppmtoarbtxt.c index df859c84..fc8927ce 100644 --- a/converter/ppm/ppmtoarbtxt.c +++ b/converter/ppm/ppmtoarbtxt.c @@ -1,4 +1,4 @@ -/* ppmtoarbtxt.c - convert portable pixmap to cleartext +/* ppmtoarbtxt.c - convert PPM to a custom text-based format ** ** Renamed from ppmtotxt.c by Bryan Henderson in January 2003. ** @@ -12,51 +12,151 @@ ** implied warranty. */ +#include <assert.h> #include <string.h> +#ifdef __GLIBC__ + #include <printf.h> /* Necessary for parse_printf_format() */ +#endif -#include "ppm.h" +#include "pm_c_util.h" #include "mallocvar.h" #include "nstring.h" +#include "shhopt.h" +#include "ppm.h" + +/* HAVE_PARSE_PRINTF_FORMAT means the system library has + parse_printf_format(), declared in <printf.h>. This essentially means + systems with GNU libc. +*/ + +#ifndef HAVE_PARSE_PRINTF_FORMAT + #ifdef PA_FLAG_MASK /* Defined in printf.h */ + #define HAVE_PARSE_PRINTF_FORMAT 1 + #else + #define HAVE_PARSE_PRINTF_FORMAT 0 + #endif +#endif + + + +struct CmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileName; + const char * bodySklFileName; + const char * hd; + const char * tl; + unsigned int debug; +}; + + + +static void +parseCommandLine(int argc, const char ** argv, + struct CmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that many of the strings that this function returns in the + *cmdline_p structure are actually in the supplied argv array. And + sometimes, one of these strings is actually just a suffix of an entry + in argv! +-----------------------------------------------------------------------------*/ + optEntry * option_def; + /* Instructions to OptParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int hdSpec, tlSpec; + + unsigned int option_def_index; + + MALLOCARRAY(option_def, 100); + + option_def_index = 0; /* incremented by OPTENTRY */ + OPTENT3(0, "hd", OPT_STRING, &cmdlineP->hd, + &hdSpec, 0); + OPTENT3(0, "tl", OPT_STRING, &cmdlineP->tl, + &tlSpec, 0); + OPTENT3(0, "debug", OPT_FLAG, NULL, + &cmdlineP->debug, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + free(option_def); + + if (!hdSpec) + cmdlineP->hd = NULL; + + if (!tlSpec) + cmdlineP->tl = NULL; + + if (argc-1 < 1) + pm_error("You must specify the body skeleton file name as an " + "argument"); + else { + cmdlineP->bodySklFileName = strdup(argv[1]); + + if (argc-1 < 2) + cmdlineP->inputFileName = strdup("-"); /* he wants stdin */ + else { + cmdlineP->inputFileName = strdup(argv[2]); + if (argc-1 > 2) + pm_error("Too many arguments. The only possible arguments " + "are the body skeleton file name and input image " + "file name"); + } + } +} + + + typedef enum { /* The types of object we handle */ BDATA, IRED, IGREEN, IBLUE, ILUM, FRED, FGREEN, FBLUE, FLUM, WIDTH, HEIGHT, POSX, POSY -} SKL_OBJ_TYP; +} SkeletonObjectType; typedef enum { OBJTYP_ICOLOR, OBJTYP_FCOLOR, OBJTYP_INT, OBJTYP_BDATA -} SKL_OBJ_CLASS; +} SkeletonObjectClass; /* Maximum size for a format string ("%d" etc.) */ +/* Add one to this size for the terminating '\0'. */ #define MAXFORMAT 16 +typedef union { /* The data we keep for each object */ -typedef union - { - struct BNDAT { char *bdat; /* Binary data (text with newlines etc.) */ - int ndat; - } bin_data; - - struct ICDAT { char icformat[MAXFORMAT]; /* Integer colors */ - int icolmin, icolmax; - } icol_data; - - struct FCDAT { char fcformat[MAXFORMAT]; /* Float colors */ - double fcolmin, fcolmax; - } fcol_data; - - struct IDAT { char iformat[MAXFORMAT]; /* Integer data */ - } i_data; - } SKL_OBJ_DATA; + struct Bndat { + char * bdat; /* Binary data (text with newlines etc.) */ + unsigned int ndat; + } binData; + + struct Icdat { + char icformat[MAXFORMAT+1]; /* Integer colors */ + unsigned int icolmin, icolmax; + } icolData; + + struct Fcdat { + char fcformat[MAXFORMAT+1]; /* Float colors */ + double fcolmin, fcolmax; + } fcolData; + + struct Idat { + char iformat[MAXFORMAT+1]; /* Integer data */ + } iData; +} SkeletonObjectData; /* Each object has a type and some data */ -typedef struct - { - SKL_OBJ_TYP otyp; - SKL_OBJ_DATA odata; - } SKL_OBJ; +typedef struct { + SkeletonObjectType objType; + SkeletonObjectData odata; +} SkeletonObject; + #define MAX_SKL_HEAD_OBJ 64 @@ -66,199 +166,168 @@ typedef struct #define MAX_OBJ_BUF 80 -static void write_txt (fout, nobj, obj, width, height, x, y, red, green, blue) -FILE *fout; -int nobj; -SKL_OBJ *obj[]; -int width, height, x, y; -double red, green, blue; - -{register int count; - -#define WRITE_BNDAT(fd,theobj) \ - {struct BNDAT *bdata = &((theobj)->odata.bin_data); \ - fwrite (bdata->bdat,bdata->ndat,1,fd); } - -#define WRITE_ICOL(fd,theobj,thecol) \ - {struct ICDAT *icdata = &((theobj)->odata.icol_data); \ - fprintf (fd,icdata->icformat,(int)(icdata->icolmin \ - + (icdata->icolmax - icdata->icolmin)*(thecol))); } - -#define WRITE_FCOL(fd,theobj,thecol) \ - {struct FCDAT *fcdata = &((theobj)->odata.fcol_data); \ - fprintf (fd,fcdata->fcformat,(double)(fcdata->fcolmin \ - + (fcdata->fcolmax - fcdata->fcolmin)*(thecol))); } - -#define WRITE_IDAT(fd,theobj,thedat) \ - {struct IDAT *idata = &((theobj)->odata.i_data); \ - fprintf (fd,idata->iformat,thedat); } - - for (count = 0; count < nobj; count++) - { - switch (obj[count]->otyp) - { - case BDATA: - WRITE_BNDAT (fout,obj[count]); - break; - case IRED: - WRITE_ICOL (fout,obj[count],red); - break; - case IGREEN: - WRITE_ICOL (fout,obj[count],green); - break; - case IBLUE: - WRITE_ICOL (fout,obj[count],blue); - break; - case ILUM: - WRITE_ICOL (fout,obj[count],0.299*red+0.587*green+0.114*blue); - break; - case FRED: - WRITE_FCOL (fout,obj[count],red); - break; - case FGREEN: - WRITE_FCOL (fout,obj[count],green); - break; - case FBLUE: - WRITE_FCOL (fout,obj[count],blue); - break; - case FLUM: - WRITE_FCOL (fout,obj[count],0.299*red+0.587*green+0.114*blue); - break; - case WIDTH: - WRITE_IDAT (fout,obj[count],width); - break; - case HEIGHT: - WRITE_IDAT (fout,obj[count],height); - break; - case POSX: - WRITE_IDAT (fout,obj[count],x); - break; - case POSY: - WRITE_IDAT (fout,obj[count],y); - break; - } - } -} +static void +dumpSkeleton(SkeletonObject ** const skeletonPList, + unsigned int const nSkeleton) { -static SKL_OBJ * -save_bin_data(int const ndat, - char * const bdat) { + unsigned int i; - /* Save binary data in Object */ + pm_message("%u objects", nSkeleton); - SKL_OBJ *obj; + for (i = 0; i < nSkeleton; ++i) { + SkeletonObject * const skeletonP = skeletonPList[i]; - obj = (SKL_OBJ *)malloc (sizeof (SKL_OBJ) + ndat); - if (obj != NULL) - { - obj->otyp = BDATA; - obj->odata.bin_data.ndat = ndat; - obj->odata.bin_data.bdat = ((char *)(obj))+sizeof (SKL_OBJ); - memcpy (obj->odata.bin_data.bdat,bdat,ndat); + pm_message(" Object: Type %u", skeletonP->objType); } - return (obj); } -static SKL_OBJ * -save_icol_data(SKL_OBJ_TYP const ctyp, - const char * const format, - int const icolmin, - int const icolmax) { -/* Save integer color data in Object */ - - SKL_OBJ * objP; +static void +dumpAllSkeleton(SkeletonObject ** const bodySkeletonPList, + unsigned int const bodyNskl, + SkeletonObject ** const headSkeletonPList, + unsigned int const headNskl, + SkeletonObject ** const tailSkeletonPList, + unsigned int const tailNskl) { + + pm_message("Body skeleton:"); + dumpSkeleton(bodySkeletonPList, bodyNskl); + + pm_message("Head skeleton:"); + dumpSkeleton(headSkeletonPList, headNskl); + + pm_message("Tail skeleton:"); + dumpSkeleton(tailSkeletonPList, tailNskl); +} - MALLOCVAR(objP); - if (objP) { - objP->otyp = ctyp; - strcpy(objP->odata.icol_data.icformat, format); - objP->odata.icol_data.icolmin = icolmin; - objP->odata.icol_data.icolmax = icolmax; - } - return objP; -} +static void +writeBndat(FILE * const ofP, + SkeletonObject * const objectP) { + struct Bndat * const bdataP = &objectP->odata.binData; -static SKL_OBJ * -save_fcol_data(SKL_OBJ_TYP const ctyp, - const char * const format, - double const fcolmin, - double const fcolmax) { -/* Save float color data in Object */ + fwrite(bdataP->bdat, bdataP->ndat, 1, ofP); +} - SKL_OBJ * objP; - MALLOCVAR(objP); - if (objP) { - objP->otyp = ctyp; - strcpy(objP->odata.fcol_data.fcformat, format); - objP->odata.fcol_data.fcolmin = fcolmin; - objP->odata.fcol_data.fcolmax = fcolmax; - } - return objP; -} +static void +writeIcol(FILE * const ofP, + SkeletonObject * const objectP, + double const value) { + /* Unlike Netpbm, the output format does not have an upper limit for + maxval. Here we allow all values representable by unsigned int. + */ + struct Icdat * const icdataP = &objectP->odata.icolData; + unsigned int const outValue = + ROUNDU( icdataP->icolmin + + ((double)icdataP->icolmax - icdataP->icolmin) * value); -static SKL_OBJ * -save_i_data(SKL_OBJ_TYP const ctyp, - const char * const format) { + fprintf(ofP, icdataP->icformat, outValue); +} -/* Save universal data in Object */ - SKL_OBJ * objP; - MALLOCVAR(objP); - if (objP) { - objP->otyp = ctyp; - strcpy(objP->odata.i_data.iformat, format); - } - return objP; +static void +writeFcol(FILE * const ofP, + SkeletonObject * const objectP, + double const value) { + + struct Fcdat * const fcdataP = &objectP->odata.fcolData; + + fprintf(ofP, fcdataP->fcformat, + (double) + (fcdataP->fcolmin + + (fcdataP->fcolmax - fcdataP->fcolmin) * value)); } -static char const escape = '#'; +static void +writeIdat(FILE * const ofP, + SkeletonObject * const objectP, + unsigned int const value) { + + struct Idat * const idataP = &objectP->odata.iData; + + fprintf(ofP, idataP->iformat, value); +} -static SKL_OBJ_TYP -interpretObjType(const char * const typstr) { +static void +writeText(FILE * const ofP, + unsigned int const nObj, + SkeletonObject ** const obj, + unsigned int const width, + unsigned int const height, + unsigned int const x, + unsigned int const y, + double const red, + double const green, + double const blue) { + + unsigned int i; - SKL_OBJ_TYP otyp; - - /* Check for integer colors */ - if (streq(typstr, "ired") ) otyp = IRED; - else if (streq(typstr, "igreen")) otyp = IGREEN; - else if (streq(typstr, "iblue") ) otyp = IBLUE; - else if (streq(typstr, "ilum") ) otyp = ILUM; - /* Check for real colors */ - else if (streq(typstr, "fred") ) otyp = FRED; - else if (streq(typstr, "fgreen")) otyp = FGREEN; - else if (streq(typstr, "fblue") ) otyp = FBLUE; - else if (streq(typstr, "flum") ) otyp = FLUM; - /* Check for integer data */ - else if (streq(typstr, "width") ) otyp = WIDTH; - else if (streq(typstr, "height")) otyp = HEIGHT; - else if (streq(typstr, "posx") ) otyp = POSX; - else if (streq(typstr, "posy") ) otyp = POSY; - else otyp = BDATA; - - return otyp; + for (i = 0; i < nObj; ++i) { + switch (obj[i]->objType) { + case BDATA: + writeBndat(ofP, obj[i]); + break; + case IRED: + writeIcol(ofP, obj[i], red); + break; + case IGREEN: + writeIcol(ofP, obj[i], green); + break; + case IBLUE: + writeIcol(ofP, obj[i], blue); + break; + case ILUM: + writeIcol(ofP, obj[i], + PPM_LUMINR*red + PPM_LUMING*green + PPM_LUMINB*blue); + break; + case FRED: + writeFcol(ofP, obj[i], red); + break; + case FGREEN: + writeFcol(ofP, obj[i], green); + break; + case FBLUE: + writeFcol(ofP, obj[i], blue); + break; + case FLUM: + writeFcol(ofP, obj[i], + PPM_LUMINR*red + PPM_LUMING*green + PPM_LUMINB*blue); + break; + case WIDTH: + writeIdat(ofP, obj[i], width); + break; + case HEIGHT: + writeIdat(ofP, obj[i], height); + break; + case POSX: + writeIdat(ofP, obj[i], x); + break; + case POSY: + writeIdat(ofP, obj[i], y); + break; + } + } } -static SKL_OBJ_CLASS -objClass(SKL_OBJ_TYP const otyp) { +static SkeletonObjectClass +objClass(SkeletonObjectType const objType) { - switch (otyp) { + switch (objType) { case IRED: case IGREEN: case IBLUE: @@ -283,298 +352,873 @@ objClass(SKL_OBJ_TYP const otyp) { } +/*---------------------------------------------------------------------------- + Format string validation + + We validate format strings (such as "%f" "%03d") found in the skeleton files + for convenience, even though behavior is documented as undefined when the + user supplies a bogus format string. Certain strings, most notably those + with "%n", are especially risky; they pose a security threat. + + On systems with Glibc, we check with parse_printf_format(). On other + systems we conduct a cursory scan of the characters in the format string, + looking for characters that trigger non-numeric conversions, etc. + + Documentation for parse_printf_format() is usually available in texinfo + format on GNU/Linux systems. As of Dec. 2014 there is no official man page. + + Online documentation is available from: + https:// + www.gnu.org/software/libc/manual/html_node/Parsing-a-Template-String.html +-----------------------------------------------------------------------------*/ +#if HAVE_PARSE_PRINTF_FORMAT static void -addImpostorReplacementSeq(char * const line, - unsigned int const startCursor, - const char * const seqContents, - unsigned int const seqContentsLen, - unsigned int * const newCursorP) { +validateParsePrintfFlag(int const printfConversion, + SkeletonObjectType const ctyp, + const char ** const errorP) { /*---------------------------------------------------------------------------- - Add to line line[], at position 'startCursor', text that looks like a - replacement sequence but doesn't have the proper contents (the - stuff between the parentheses) to be one. For example, + Assuming 'printfConversion' is the value reported by parse_printf_format() + as the type of argument a format string requires, + return an explanation of how it is incompatible with 'ctyp' as + *errorP -- return null string if it is compatible. +-----------------------------------------------------------------------------*/ + /* We first check for "%n", then the type modifiers, and finally the + actual conversion type (char, int, float, double, string or pointer.) + */ + switch (printfConversion & PA_FLAG_MASK) { + case PA_FLAG_PTR: /* This means %n */ + pm_asprintf(errorP, "Contains a %%n conversion specifier"); + break; + + case PA_FLAG_SHORT: + case PA_FLAG_LONG: + case PA_FLAG_LONG_LONG: + /* We omit PA_FLAG_LONG_DOUBLE because it is a synonym for + PA_FLAG_LONG_LONG: listing both causes compilation errors. + */ + pm_asprintf(errorP, "Invalid type modifier"); + break; + + default: + switch (printfConversion & ~PA_FLAG_MASK) { + case PA_CHAR: + pm_message("Warning: char type conversion."); + case PA_INT: + if(objClass(ctyp) == OBJTYP_ICOLOR || + objClass(ctyp) == OBJTYP_INT ) + *errorP = NULL; + else + pm_asprintf(errorP, "Conversion specifier requires a " + "character or integer argument, but it is in " + "a replacement sequence for a different type"); + break; + case PA_DOUBLE: + if(objClass(ctyp) == OBJTYP_FCOLOR) + *errorP = NULL; + else + pm_asprintf(errorP, "Conversion specifier requires a " + "double precision floating point argument, " + "but it is in " + "a replacement sequence for a different type"); + break; + case PA_FLOAT: + case PA_STRING: /* %s */ + case PA_POINTER: /* %p */ + default: + pm_asprintf(errorP, "Conversion specifier requires an argument of " + "a type that this program never provides for " + "any replacement sequence"); + } + } +} +#endif - "#(fread x)" - seqContents[] is the contents; 'seqContentsLen' its length. - Return as *newCursorP where the line[] cursor ends up after adding - the sequence. +#if HAVE_PARSE_PRINTF_FORMAT +static void +validateFormatWithPpf(const char * const format, + SkeletonObjectType const ctyp, + const char ** const errorP) { +/*---------------------------------------------------------------------------- + Validate format string 'format' for use with a skeleton of type 'ctyp', + using the system parse_printf_format() function. + + Return as *errorP an explanation of how it is invalid, or a null string + if it is valid. -----------------------------------------------------------------------------*/ - unsigned int cursor; - unsigned int i; + /* We request parse_printf_format() to report the details of the first + 8 conversions. 8 because the maximum length of format is 16 means it + can have up to 8 conversions: "%d%d%d%d%d%d%d%d". + + Actually this is more than necessary: we are concerned with only the + first conversion and whether there it is the only one. + */ - cursor = startCursor; + int printfConversion[MAXFORMAT/2] = {0, 0, 0, 0, 0, 0, 0, 0}; - line[cursor++] = escape; - line[cursor++] = '('; + size_t const n = + parse_printf_format(format, MAXFORMAT/2, printfConversion); + + switch (n) { + case 0: + pm_asprintf(errorP, "No transformation found"); + break; + + case 1: + validateParsePrintfFlag(printfConversion[0], ctyp, errorP); + break; + + default: + pm_asprintf(errorP, "Has %lu extra transformation%s ", + (unsigned long)n-1, n-1 > 1 ? "s" : ""); + break; + } +} +#endif - for (i = 0; i < seqContentsLen; ++i) - line[cursor++] = seqContents[i]; - line[cursor++] = ')'; - *newCursorP = cursor; +static void +validateFormatOne(char const typeSpecifier, + bool const isLastInString, + SkeletonObjectType const ctyp, + bool * const validatedP, + const char ** const errorP) { + + switch (typeSpecifier) { + /* Valid character encountered. Skip. */ + /* ' ' (space) is listed here, but should never occur for + we use sscanf() to parse the fields. + */ + case ' ': case '-': case '+': case '\'': case '#': case '.': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + break; + + case 'c': case 'C': + pm_message("Warning: char type conversion: %%%c.", typeSpecifier); + case 'i': case 'd': case 'u': case 'o': case 'x': case 'X': + if (!isLastInString) + pm_asprintf(errorP, "Extra characters at end"); + else if(objClass(ctyp) != OBJTYP_ICOLOR && + objClass(ctyp) != OBJTYP_INT ) + pm_asprintf(errorP, "Conversion type mismatch"); + else + *validatedP = true; + break; + + case 'f': case 'F': case 'g': case 'G': case 'a': case 'A': + if (!isLastInString) + pm_asprintf(errorP, "Extra characters at end"); + else if(objClass(ctyp) != OBJTYP_FCOLOR) + pm_asprintf(errorP, "Conversion type mismatch"); + else + *validatedP = true; + break; + + case '\0': + pm_asprintf(errorP, "No conversion specified"); + break; + case '%': + pm_asprintf(errorP, "No more than one %% is allowed"); + break; + case '$': + case '*': + pm_asprintf(errorP, "%c is not allowed", typeSpecifier); + break; + case 'h': case 'l': case 'L': case 'q': case 'j': case 'Z': case 't': + pm_asprintf(errorP, "Modifier %c is not allowed in format", + typeSpecifier); + break; + case 's': case 'S': case 'm': case 'p': case 'n': + pm_asprintf(errorP, "Invalid conversion type"); + break; + default: + pm_asprintf(errorP, "Abnormal character"); + break; + } } -static int -read_skeleton(const char * const filename, - unsigned int const maxskl, - unsigned int * const nsklP, - SKL_OBJ ** const skl) { +static void +validateFormatGen(const char * const format, + SkeletonObjectType const ctyp, + const char ** const errorP) { /*---------------------------------------------------------------------------- - Read skeleton file + Validate format string 'format' for use with a skeleton of type 'ctyp', + without using the system parse_printf_format() function. + + The string must begin with "%" and end with the translation type character + ("%d", "%x", "%f", etc.) + + We check only for invalid characters. Invalid constructs, such as + "%00.00.00d" will pass this test. + + Return as *errorP an explanation of how it is invalid, or a null string + if it is valid. -----------------------------------------------------------------------------*/ - FILE * sklfile; - unsigned int slen; - unsigned int objlen; - int chr; - SKL_OBJ_TYP otyp; - char line[MAX_LINE_BUF+MAX_OBJ_BUF+16]; - char objstr[MAX_OBJ_BUF],typstr[MAX_OBJ_BUF]; - unsigned int nskl; - -#define SAVE_BIN(slen,line) \ - { if (slen > 0 && (skl[nskl] = save_bin_data(slen,line)) != NULL) ++nskl; \ - slen = 0; } - - sklfile = pm_openr(filename); - - /* Parse skeleton file */ - nskl = 0; /* initial value */ - - slen = 0; - while ((chr = getc (sklfile)) != EOF) { /* Up to end of skeleton file */ - if (nskl >= maxskl) - return -1; - - if (slen+1 >= MAX_LINE_BUF) { - /* Buffer finished. Save as binary object */ - SAVE_BIN(slen,line); + if (format[0] != '%') + pm_asprintf(errorP, "Does not start with %%"); + else { + unsigned int i; + bool validated; + + for (i = 1, validated = false, *errorP = NULL; + !validated && !*errorP; + ++i) { + + validateFormatOne(format[i], format[i+1] == '\0', ctyp, + &validated, errorP); } + } +} - if (chr != escape) { - /* Not a replacement sequence; just a literal character */ - line[slen++] = chr; - continue; - } - chr = getc(sklfile); - if (chr == EOF) { - /* Not a valid replacement sequence */ - line[slen++] = escape; - break; - } - if (chr != '(') { - /* Not a valid replacement sequence */ - line[slen++] = escape; - line[slen++] = chr; - continue; + +static void +validateFormat(const char * const format, + SkeletonObjectType const ctyp) { + + const char * error; + + if (strlen(format) > MAXFORMAT) + pm_asprintf(&error, "Too long"); + else { +#if HAVE_PARSE_PRINTF_FORMAT + if (true) + validateFormatWithPpf(format, ctyp, &error); + else /* Silence compiler warning about unused function */ + validateFormatGen(format, ctyp, &error); +#else + validateFormatGen(format, ctyp, &error); +#endif + } + + if (error) + pm_error("Invalid format string '%s'. %s", format, error); +} + + + +static SkeletonObject * +newBinDataObj(unsigned int const nDat, + const char * const bdat) { +/*---------------------------------------------------------------------------- + Create a binary data object. +-----------------------------------------------------------------------------*/ + SkeletonObject * objectP; + + objectP = malloc(sizeof(*objectP) + nDat); + + if (!objectP) + pm_error("Failed to allocate memory for binary data object " + "with %u bytes", nDat); + + objectP->objType = BDATA; + objectP->odata.binData.ndat = nDat; + objectP->odata.binData.bdat = ((char *)objectP) + sizeof(SkeletonObject); + memcpy(objectP->odata.binData.bdat, bdat, nDat); + + return objectP; +} + + + +static SkeletonObject * +newIcolDataObj(SkeletonObjectType const ctyp, + const char * const format, + unsigned int const icolmin, + unsigned int const icolmax) { +/*---------------------------------------------------------------------------- + Create integer color data object. +-----------------------------------------------------------------------------*/ + SkeletonObject * objectP; + + MALLOCVAR(objectP); + + if (!objectP) + pm_error("Failed to allocate memory for an integer color data " + "object"); + + objectP->objType = ctyp; + validateFormat(format, ctyp); + strcpy(objectP->odata.icolData.icformat, format); + objectP->odata.icolData.icolmin = icolmin; + objectP->odata.icolData.icolmax = icolmax; + + return objectP; +} + + + +static SkeletonObject * +newFcolDataObj(SkeletonObjectType const ctyp, + const char * const format, + double const fcolmin, + double const fcolmax) { +/*---------------------------------------------------------------------------- + Create float color data object. +-----------------------------------------------------------------------------*/ + SkeletonObject * objectP; + + MALLOCVAR(objectP); + + if (!objectP) + pm_error("Failed to allocate memory for a float color data object"); + + objectP->objType = ctyp; + validateFormat(format, ctyp); + strcpy(objectP->odata.fcolData.fcformat, format); + objectP->odata.fcolData.fcolmin = fcolmin; + objectP->odata.fcolData.fcolmax = fcolmax; + + return objectP; +} + + + +static SkeletonObject * +newIdataObj(SkeletonObjectType const ctyp, + const char * const format) { +/*---------------------------------------------------------------------------- + Create universal data object. +-----------------------------------------------------------------------------*/ + SkeletonObject * objectP; + + MALLOCVAR(objectP); + + if (!objectP) + pm_error("Failed to allocate memory for a universal data object"); + + objectP->objType = ctyp; + validateFormat(format, ctyp); + strcpy(objectP->odata.iData.iformat, format); + + return objectP; +} + + + +static char const escape = '#'; + + + +static SkeletonObjectType +interpretObjType(const char * const typstr) { + + SkeletonObjectType objType; + + /* handle integer colors */ + if (streq(typstr, "ired") ) objType = IRED; + else if (streq(typstr, "igreen")) objType = IGREEN; + else if (streq(typstr, "iblue") ) objType = IBLUE; + else if (streq(typstr, "ilum") ) objType = ILUM; + /* handle real colors */ + else if (streq(typstr, "fred") ) objType = FRED; + else if (streq(typstr, "fgreen")) objType = FGREEN; + else if (streq(typstr, "fblue") ) objType = FBLUE; + else if (streq(typstr, "flum") ) objType = FLUM; + /* handle integer data */ + else if (streq(typstr, "width") ) objType = WIDTH; + else if (streq(typstr, "height")) objType = HEIGHT; + else if (streq(typstr, "posx") ) objType = POSX; + else if (streq(typstr, "posy") ) objType = POSY; + else objType = BDATA; + + return objType; +} + + + +static SkeletonObject * +newIcSkelFromReplString(const char * const objstr, + SkeletonObjectType const objType) { + + SkeletonObject * retval; + unsigned int icolmin, icolmax; + char formstr[MAX_OBJ_BUF]; + unsigned int nOdata; + + nOdata = sscanf(objstr, "%*s%s%u%u", formstr, &icolmin, &icolmax); + + if (nOdata == 3) + retval = newIcolDataObj(objType, formstr, icolmin, icolmax); + else if (nOdata == EOF) { + /* No arguments specified. Use defaults */ + retval = newIcolDataObj(objType, "%u", 0, 255); + } else + retval = NULL; + + return retval; +} + + + +static SkeletonObject * +newFcSkelFromReplString(const char * const objstr, + SkeletonObjectType const objType) { + + SkeletonObject * retval; + double fcolmin, fcolmax; + char formstr[MAX_OBJ_BUF]; + unsigned int nOdata; + + nOdata = sscanf(objstr, "%*s%s%lf%lf", formstr, + &fcolmin, &fcolmax); + + if (nOdata == 3) + retval = newFcolDataObj(objType, formstr, fcolmin, fcolmax); + else if (nOdata == EOF) { + /* No arguments specified. Use defaults */ + retval = newFcolDataObj(objType, "%f", 0.0, 1.0); + } else + retval = NULL; + + return retval; +} + + + +static SkeletonObject * +newISkelFromReplString(const char * const objstr, + SkeletonObjectType const objType) { + + SkeletonObject * retval; + char formstr[MAX_OBJ_BUF]; + unsigned int const nOdata = sscanf(objstr, "%*s%s", formstr); + + if (nOdata == 1) + retval = newIdataObj(objType, formstr); + else if (nOdata == EOF) { + /* No arguments specified. Use defaults */ + retval = newIdataObj(objType, "%u"); + } else + retval = NULL; + + return retval; +} + + + +static SkeletonObject * +newSkeletonFromReplString(const char * const objstr) { +/*---------------------------------------------------------------------------- + Create a skeleton from the replacement string 'objstr' (the stuff + between the parentheses in #(...) ). + + Return NULL if it isn't a valid replacement string. +-----------------------------------------------------------------------------*/ + /* We use sscanf() to parse the contents of objstr, giving it a format + template with the largest number of fields possible plus one extra to + pick up and check for the existence of invalid trailing characters. We + read and discard fields beyond the first, if any. The appropriate + new**SkelFromReplString() function determines their contents with a + separate call to sscanf(). + */ + + SkeletonObject * retval; + char typstr[MAX_OBJ_BUF]; + SkeletonObjectType objType; + int conversionCt; + char s1[MAX_OBJ_BUF]; /* Dry read. */ + char s2[MAX_OBJ_BUF]; /* Extra tailing characters. */ + float f1, f2; /* Dry read. */ + + typstr[0] = '\0'; /* initial value */ + + conversionCt = sscanf(objstr, "%s%s%f%f%s", typstr, s1, &f1, &f2, s2); + switch (conversionCt) { + case 1: case 2: case 4: + objType = interpretObjType(typstr); + break; + default: + objType = BDATA; + } + + switch (objClass(objType)) { + case OBJTYP_ICOLOR: + retval = newIcSkelFromReplString(objstr, objType); + break; + case OBJTYP_FCOLOR: + retval = newFcSkelFromReplString(objstr, objType); + break; + case OBJTYP_INT: + retval = newISkelFromReplString(objstr, objType); + break; + case OBJTYP_BDATA: + retval = NULL; + } + return retval; +} + + + +static void +readThroughCloseParen(FILE * const ifP, + char * const objstr, + size_t const objstrSize, + bool * const unclosedP) { +/*---------------------------------------------------------------------------- + Read *ifP up through close parenthesis ( ')' ) into 'objstr', which + is of size 'objstrSize'. Make it a NUL-terminated string. + + Return *unclosedP true iff we run out of file or run out of objstr + before we see a close parenthesis. In this case, return the rest of + the file, or as much as fits, in 'objstr', not NUL-terminated. +-----------------------------------------------------------------------------*/ + unsigned int i; + bool eof; + bool gotEscSeq; + + for (i= 0, eof = false, gotEscSeq = false; + i < objstrSize - 1 && !gotEscSeq && !eof; + ++i) { + + int rc; + + rc = getc(ifP); + if (rc == EOF) + eof = true; + else { + char const chr = rc; + if (chr == ')') { + gotEscSeq = true; + objstr[i] = '\0'; + } else + objstr[i] = chr; } - /* Read replacement string up through ')'. Put contents of - parentheses in objstr[]. + } + *unclosedP = !gotEscSeq; +} + + + +typedef struct { + unsigned int capacity; + SkeletonObject ** skeletonPList; + unsigned int nSkeleton; +} SkeletonBuffer; + + + +static void +SkeletonBuffer_init(SkeletonBuffer * const bufferP, + unsigned int const capacity, + SkeletonObject ** const skeletonPList) { + + bufferP->capacity = capacity; + bufferP->skeletonPList = skeletonPList; + bufferP->nSkeleton = 0; +} + + + +static void +SkeletonBuffer_add(SkeletonBuffer * const bufferP, + SkeletonObject * const skeletonP) { + + if (bufferP->nSkeleton >= bufferP->capacity) + pm_error("Too many skeletons. Max = %u", bufferP->capacity); + + bufferP->skeletonPList[bufferP->nSkeleton++] = skeletonP; +} + + + +typedef struct { + + char data[MAX_LINE_BUF + MAX_OBJ_BUF + 16]; + + unsigned int length; + + SkeletonBuffer * skeletonBufferP; + /* The buffer to which we flush. Flushing means turning all the + characters currently in our buffer into a binary skeleton object + here. */ - for (objlen = 0; objlen < sizeof(objstr)-1; ++objlen) { - chr = getc(sklfile); - if (chr == EOF) break; - if (chr == ')') break; - objstr[objlen] = chr; - } - objstr[objlen] = '\0'; - - if (chr != ')') { - /* Not valid replacement sequence */ - unsigned int i; - line[slen++] = escape; - line[slen++] = chr; - for (i = 0; i < objlen; ++i) - line[slen++] = objstr[i]; - if (chr == EOF) - break; - continue; - } - typstr[0] = '\0'; /* Get typ of data */ - sscanf(objstr, "%s", typstr); - - otyp = interpretObjType(typstr); - - switch (objClass(otyp)) { - case OBJTYP_ICOLOR: { - int icolmin, icolmax; - char formstr[MAX_OBJ_BUF]; - int n_odata; - - n_odata = sscanf(objstr, "%*s%s%d%d", formstr, &icolmin, &icolmax); - - if (n_odata == 3) { - SAVE_BIN(slen, line); - skl[nskl] = save_icol_data(otyp, formstr, icolmin, icolmax); - if (skl[nskl] != NULL) - ++nskl; - } else if (n_odata == EOF) { - /* No arguments specified. Use defaults */ - SAVE_BIN(slen, line); - skl[nskl] = save_icol_data(otyp, "%d", 0, 255); - if (skl[nskl] != NULL) - ++nskl; - } else - addImpostorReplacementSeq(line, slen, objstr, objlen, &slen); - } break; - case OBJTYP_FCOLOR: { - double fcolmin, fcolmax; - char formstr[MAX_OBJ_BUF]; - int n_odata; - - n_odata = sscanf(objstr, "%*s%s%lf%lf", formstr, - &fcolmin, &fcolmax); - - if (n_odata == 3) { - SAVE_BIN(slen, line); - skl[nskl] = save_fcol_data(otyp, formstr, fcolmin, fcolmax); - if (skl[nskl] != NULL) - ++nskl; - } else if (n_odata == EOF) { - /* No arguments specified. Use defaults */ - SAVE_BIN(slen, line); - skl[nskl] = save_fcol_data(otyp, "%f", 0.0, 1.0); - if (skl[nskl] != NULL) - ++nskl; - } else - addImpostorReplacementSeq(line, slen, objstr, objlen, &slen); - } break; - - case OBJTYP_INT: { - char formstr[MAX_OBJ_BUF]; - int const n_odata = sscanf(objstr, "%*s%s", formstr); - - if (n_odata == 1) { - SAVE_BIN(slen, line); - skl[nskl] = save_i_data(otyp, formstr); - if (skl[nskl] != NULL) - ++nskl; - } else if (n_odata == EOF) { - /* No arguments specified. Use defaults */ - SAVE_BIN(slen, line); - skl[nskl] = save_i_data(otyp, "%d"); - if (skl[nskl] != NULL) - ++nskl; - } else - addImpostorReplacementSeq(line, slen, objstr, objlen, &slen); - } break; - case OBJTYP_BDATA: - addImpostorReplacementSeq(line, slen, objstr, objlen, &slen); +} Buffer; + + + +static void +Buffer_init(Buffer * const bufferP, + SkeletonBuffer * const skeletonBufferP) { + + bufferP->skeletonBufferP = skeletonBufferP; + bufferP->length = 0; +} + + + +static void +Buffer_flush(Buffer * const bufferP) { +/*---------------------------------------------------------------------------- + Flush the buffer out to a binary skeleton object. +-----------------------------------------------------------------------------*/ + SkeletonBuffer_add(bufferP->skeletonBufferP, + newBinDataObj(bufferP->length, bufferP->data)); + + bufferP->length = 0; +} + + + +static void +Buffer_add(Buffer * const bufferP, + char const newChar) { + + if (bufferP->length >= MAX_LINE_BUF) + Buffer_flush(bufferP); + + assert(bufferP->length < MAX_LINE_BUF); + + bufferP->data[bufferP->length++] = newChar; +} + + + +static void +Buffer_dropFinalNewline(Buffer * const bufferP) { +/*---------------------------------------------------------------------------- + If the last thing in the buffer is a newline, remove it. +-----------------------------------------------------------------------------*/ + if (bufferP->length >= 1 && bufferP->data[bufferP->length-1] == '\n') { + /* Drop finishing newline character */ + --bufferP->length; + } +} + + + +static void +addImpostorReplacementSeq(Buffer * const bufferP, + const char * const seqContents) { +/*---------------------------------------------------------------------------- + Add to buffer *bufferP something that looks like a replacement sequence but + doesn't have the proper contents (the stuff between the parentheses) to be + one. For example, + + "#(fread x)" + + seqContents[] is the contents, NUL-terminated. +-----------------------------------------------------------------------------*/ + const char * p; + + Buffer_add(bufferP, escape); + Buffer_add(bufferP, '('); + + for (p = &seqContents[0]; *p; ++p) + Buffer_add(bufferP, *p); + + Buffer_add(bufferP, ')'); +} + + + +static void +readSkeletonFile(const char * const filename, + unsigned int const maxskl, + const char ** const errorP, + unsigned int * const nSkeletonP, + SkeletonObject ** const skeletonPList) { +/*---------------------------------------------------------------------------- +-----------------------------------------------------------------------------*/ + FILE * sklfileP; + SkeletonBuffer skeletonBuffer; + /* A buffer for accumulating skeleton objects */ + Buffer buffer; + /* A buffer for accumulating binary (literal; unsubstituted) data, on + its way to becoming a binary skeleton object. + */ + bool eof; + const char * error; + + SkeletonBuffer_init(&skeletonBuffer, maxskl, skeletonPList); + + Buffer_init(&buffer, &skeletonBuffer); + + sklfileP = pm_openr(filename); + + for (eof = false, error = NULL; !eof && !error; ) { + + int rc; + + rc = getc(sklfileP); + + if (rc == EOF) + eof = true; + else { + char const chr = rc; + + if (chr != escape) { + /* Not a replacement sequence; just a literal character */ + Buffer_add(&buffer, chr); + } else { + int rc; + rc = getc(sklfileP); + if (rc == EOF) { + /* Not a replacement sequence, just an escape caharacter + at the end of the file. + */ + Buffer_add(&buffer, escape); + eof = true; + } else { + char const chr = rc; + + if (chr != '(') { + /* Not a replacement sequence, just a lone escape + character + */ + Buffer_add(&buffer, escape); + Buffer_add(&buffer, chr); + } else { + char objstr[MAX_OBJ_BUF]; + bool unclosed; + readThroughCloseParen(sklfileP, + objstr, sizeof(objstr), + &unclosed); + if (unclosed) + pm_asprintf(&error, "Unclosed parentheses " + "in #() escape sequence"); + else { + SkeletonObject * const skeletonP = + newSkeletonFromReplString(objstr); + + if (skeletonP) { + Buffer_flush(&buffer); + SkeletonBuffer_add(&skeletonBuffer, skeletonP); + } else + addImpostorReplacementSeq(&buffer, objstr); + } + } + } + } } - } /* EOF of skeleton file */ + } - if (slen >= 1 && line[slen-1] == '\n') - /* Drop finishing newline character */ - --slen; + if (!error) { + Buffer_dropFinalNewline(&buffer); + Buffer_flush(&buffer); + } + *errorP = error; + *nSkeletonP = skeletonBuffer.nSkeleton; - SAVE_BIN(slen, line); /* Save whatever is left */ + fclose(sklfileP); +} - *nsklP = nskl; - fclose(sklfile); - return 0; + +static void +convertIt(FILE * const ifP, + FILE * const ofP, + SkeletonObject ** const bodySkeletonPList, + unsigned int const bodyNskl, + SkeletonObject ** const headSkeletonPList, + unsigned int const headNskl, + SkeletonObject ** const tailSkeletonPList, + unsigned int const tailNskl) { + + pixel * pixelrow; + pixval maxval; + double dmaxval; + int rows, cols; + int format; + unsigned int row; + + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); + + pixelrow = ppm_allocrow(cols); + + dmaxval = (double)maxval; + + /* Write header */ + writeText(ofP, headNskl, headSkeletonPList, + cols, rows , 0, 0, 0.0, 0.0, 0.0); + + /* Write raster */ + for (row = 0; row < rows; ++row) { + unsigned int col; + + ppm_readppmrow(ifP, pixelrow, cols, maxval, format); + + for (col = 0; col < cols; ++col) { + pixel const thisPixel = pixelrow[col]; + + writeText(ofP, bodyNskl, bodySkeletonPList, + cols, rows, col, row, + PPM_GETR(thisPixel)/dmaxval, + PPM_GETG(thisPixel)/dmaxval, + PPM_GETB(thisPixel)/dmaxval); + } + } + + /* Write trailer */ + writeText(ofP, tailNskl, tailSkeletonPList, + cols, rows, 0, 0, 0.0, 0.0, 0.0); } -int main( argc, argv ) -int argc; -char* argv[]; - -{register int col; - register pixel* xP; - pixel* pixelrow; - pixval maxval,red,green,blue; - double dmaxval; - int argn, rows, cols, format, row; - unsigned int head_nskl,body_nskl,tail_nskl; - SKL_OBJ *head_skl[MAX_SKL_HEAD_OBJ]; - SKL_OBJ *body_skl[MAX_SKL_BODY_OBJ]; - SKL_OBJ *tail_skl[MAX_SKL_TAIL_OBJ]; - FILE *ifp; - const char *usage = "bodyskl [ -hd headskl ] [ -tl tailskl ] [pnmfile]"; - - ppm_init( &argc, argv ); - - argn = 1; - if (argn == argc) - pm_usage( usage ); - /* Read body skeleton file */ - if (read_skeleton (argv[argn],sizeof (body_skl)/sizeof (SKL_OBJ *), - &body_nskl,body_skl) < 0) - pm_usage ( usage ); - ++argn; - - head_nskl = tail_nskl = 0; - - while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') - { - if ( pm_keymatch ( argv[argn], "-hd", 1) && argn+1 < argc ) - { - argn++; /* Read header skeleton */ - if (read_skeleton (argv[argn],sizeof (head_skl)/sizeof (SKL_OBJ *), - &head_nskl,head_skl) < 0) - pm_usage ( usage ); - } - else if ( pm_keymatch ( argv[argn], "-tl", 1) && argn+1 < argc ) - { - argn++; /* Read tail skeleton */ - if (read_skeleton (argv[argn],sizeof (tail_skl)/sizeof (SKL_OBJ *), - &tail_nskl,tail_skl) < 0) - pm_usage ( usage ); - } - else - { - pm_usage ( usage ); - } - argn++; - } - - if ( argn != argc ) - { - ifp = pm_openr( argv[argn] ); - ++argn; - } - else - { - ifp = stdin; - } - - if ( argn != argc ) - pm_usage( usage ); - - ppm_readppminit( ifp, &cols, &rows, &maxval, &format ); - pixelrow = ppm_allocrow( cols ); - dmaxval = (double)maxval; - - if (head_nskl > 0) /* Write header */ - write_txt (stdout,head_nskl,head_skl,cols,rows,0,0,0.0,0.0,0.0); - - for ( row = 0; row < rows; ++row ) - { - ppm_readppmrow( ifp, pixelrow, cols, maxval, format ); - - for ( col = 0, xP = pixelrow; col < cols; ++col, ++xP ) - { - red = PPM_GETR( *xP ); - green = PPM_GETG( *xP ); - blue = PPM_GETB( *xP ); - write_txt (stdout,body_nskl,body_skl,cols,rows,col,row, - red/dmaxval,green/dmaxval,blue/dmaxval); - } - } - - if (tail_nskl > 0) /* Write trailer */ - write_txt (stdout,tail_nskl,tail_skl,cols,rows,0,0,0.0,0.0,0.0); - - pm_close( ifp ); - - exit( 0 ); +int +main(int argc, + const char ** argv) { + + struct CmdlineInfo cmdline; + + unsigned int headNskl, bodyNskl, tailNskl; + SkeletonObject * headSkeletonPList[MAX_SKL_HEAD_OBJ]; + SkeletonObject * bodySkeletonPList[MAX_SKL_BODY_OBJ]; + SkeletonObject * tailSkeletonPList[MAX_SKL_TAIL_OBJ]; + FILE * ifP; + const char * error; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFileName); + + readSkeletonFile(cmdline.bodySklFileName, ARRAY_SIZE(bodySkeletonPList), + &error, &bodyNskl, bodySkeletonPList); + if (error) + pm_error("Invalid body skeleton file '%s'. %s", + cmdline.bodySklFileName, error); + + if (cmdline.hd) { + readSkeletonFile(cmdline.hd, ARRAY_SIZE(headSkeletonPList), + &error, &headNskl, headSkeletonPList); + if (error) + pm_error("Invalid head skeleton file '%s'. %s", + cmdline.hd, error); + } else + headNskl = 0; + + if (cmdline.tl) { + readSkeletonFile(cmdline.tl, ARRAY_SIZE(tailSkeletonPList), + &error, &tailNskl, tailSkeletonPList); + if (error) + pm_error("Invalid tail skeleton file '%s'. %s", + cmdline.tl, error); + } else + tailNskl = 0; + + if (cmdline.debug) + dumpAllSkeleton(bodySkeletonPList, bodyNskl, + headSkeletonPList, headNskl, + tailSkeletonPList, tailNskl); + + convertIt(ifP, stdout, + bodySkeletonPList, bodyNskl, + headSkeletonPList, headNskl, + tailSkeletonPList, tailNskl); + + pm_close(ifP); + + return 0; } + + diff --git a/converter/ppm/ppmtoascii.c b/converter/ppm/ppmtoascii.c new file mode 100644 index 00000000..6b0b04d7 --- /dev/null +++ b/converter/ppm/ppmtoascii.c @@ -0,0 +1,236 @@ +/*============================================================================= + ppmtoascii +=============================================================================== + + Convert a PPM image to ASCII with ANSI color graphics terminal controls + + Based on pbmtoascii. + Copyright (C) 1988, 1992 by Jef Poskanzer. + Copyright (C) 2010 by Frank Ch. Eigler. + + 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. +=============================================================================*/ + +#include "pm_c_util.h" +#include "mallocvar.h" +#include "shhopt.h" +#include "ppm.h" +#include "pm_gamma.h" + +/* We use the same algorithm for converting many pixels into a character + as Pbmtoascii. See pbmtoascii.c for a full explanation. +*/ + + +#define SQQ '\'' +#define BSQ '\\' + +/* Bit-map for 1x2 mode: +** 1 +** 2 +*/ +static char const carr1x2[4] = { +/* 0 1 2 3 */ + ' ', '"', 'o', 'M' }; + +/* Bit-map for 2x4 mode (hex): +** 1 2 +** 4 8 +** 10 20 +** 40 80 +** The idea here is first to preserve geometry, then to show density. +*/ +#define D08 'M' +#define D07 'H' +#define D06 '&' +#define D05 '$' +#define D04 '?' +static char const carr2x4[256] = { +/*0 1 2 3 4 5 6 7 8 9 A B C D E F */ +' ',SQQ, '`','"', '-',SQQ, SQQ,SQQ, '-','`', '`','`', '-','^','^','"',/*00-0F*/ +'.',':', ':',':', '|','|', '/',D04, '/','>', '/','>', '~','+','/','*',/*10-1F*/ +'.',':', ':',':', BSQ,BSQ, '<','<', '|',BSQ, '|',D04, '~',BSQ,'+','*',/*20-2F*/ +'-',':', ':',':', '~',D04, '<','<', '~','>', D04,'>', '=','b','d','#',/*30-3F*/ +'.',':', ':',':', ':','!', '/',D04, ':',':', '/',D04, ':',D04,D04,'P',/*40-4F*/ +',','i', '/',D04, '|','|', '|','T', '/',D04, '/','7', 'r','}','/','P',/*50-5F*/ +',',':', ';',D04, '>',D04, 'S','S', '/',')', '|','7', '>',D05,D05,D06,/*60-6F*/ +'v',D04, D04,D05, '+','}', D05,'F', '/',D05, '/',D06, 'p','D',D06,D07,/*70-7F*/ +'.',':', ':',':', ':',BSQ, ':',D04, ':',BSQ, '!',D04, ':',D04,D04,D05,/*80-8F*/ +BSQ,BSQ, ':',D04, BSQ,'|', '(',D05, '<','%', D04,'Z', '<',D05,D05,D06,/*90-9F*/ +',',BSQ, 'i',D04, BSQ,BSQ, D04,BSQ, '|','|', '|','T', D04,BSQ,'4','9',/*A0-AF*/ +'v',D04, D04,D05, BSQ,BSQ, D05,D06, '+',D05, '{',D06, 'q',D06,D06,D07,/*B0-BF*/ +'_',':', ':',D04, ':',D04, D04,D05, ':',D04, D04,D05, ':',D05,D05,D06,/*C0-CF*/ +BSQ,D04, D04,D05, D04,'L', D05,'[', '<','Z', '/','Z', 'c','k',D06,'R',/*D0-DF*/ +',',D04, D04,D05, '>',BSQ, 'S','S', D04,D05, 'J',']', '>',D06,'1','9',/*E0-EF*/ +'o','b', 'd',D06, 'b','b', D06,'6', 'd',D06, 'd',D07, '#',D07,D07,D08 /*F0-FF*/ +}; + + + +static const char* rgb2x2x2fg[2][2][2] = { + {{"\x1b[30m", /* 000 black */ + "\x1b[34m"}, /* 001 blue */ + {"\x1b[32m", /* 010 green */ + "\x1b[36m"}}, /* 011 cyan */ + {{"\x1b[31m", /* 100 red */ + "\x1b[35m"}, /* 101 magenta */ + {"\x1b[33m", /* 110 yellow */ + "\x1b[37m"}}, /* 111 white */ +}; + + + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileName; /* Name of input file */ + unsigned int cellWidth; + unsigned int cellHeight; + const char * carr; +}; + + + +static void +parseCommandLine(int argc, const char **argv, + struct cmdlineInfo * const cmdlineP) { + + optEntry * option_def; + /* Instructions to OptParseOptions3 on how to parse our options */ + optStruct3 opt; + + unsigned int option_def_index; + unsigned int dim1x2Spec, dim2x4Spec; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENTRY */ + OPTENT3(0, "1x2", OPT_FLAG, NULL, &dim1x2Spec, 0); + OPTENT3(0, "2x4", OPT_FLAG, NULL, &dim2x4Spec, 0); + + opt.opt_table = option_def; + opt.short_allowed = false; /* We have no short (old-fashioned) options */ + opt.allowNegNum = false; /* We have no parms that are negative numbers */ + + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (dim1x2Spec && dim2x4Spec) + pm_error("You cannot specify both -1x2 and -2x4"); + else if (dim2x4Spec) { + cmdlineP->cellWidth = 2; + cmdlineP->cellHeight = 4; + cmdlineP->carr = carr2x4; + } else { + cmdlineP->cellWidth = 1; + cmdlineP->cellHeight = 2; + cmdlineP->carr = carr1x2; + } + + if (argc-1 < 1) + cmdlineP->inputFileName = "-"; + else { + cmdlineP->inputFileName = argv[1]; + + if (argc-1 > 1) + pm_error("Too many arguments: %u. The only possible argument " + "is the input file name", argc-1); + } +} + + + +static void +ppmtoascii(pixel * const * const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + struct cmdlineInfo const cmdline, + FILE * const ofP) { + + unsigned int const cellHeight = cmdline.cellHeight; + unsigned int const cellWidth = cmdline.cellWidth; + const char * const carr = cmdline.carr; + unsigned int row; + + fprintf(ofP, "\x1b[0m"); /* Clear initial ansi attributes */ + /* TODO: set background to black */ + + for (row = 0; row < rows; row += cellHeight) { + unsigned int col; + for (col = 0; col < cols; col += cellWidth) { + unsigned int const sumthresh = cellWidth * cellHeight * 1.0 / 2; + + float sumr, sumg, sumb; + /* sum of intensity within cell so far, by component */ + unsigned int b; + const char * colorstr; + unsigned int subrow; + + sumr = sumg = sumb = 0; /* initial value */ + b = 0; /* initial value */ + + for (subrow = 0; subrow < cellHeight; ++subrow) { + unsigned int subcol; + for (subcol = 0; subcol < cellWidth; ++subcol) { + pixel color; + pixval value; + + if (row + subrow < rows && col + subcol < cols) + color = pixels[row + subrow][col + subcol]; + else + color = ppm_whitepixel (maxval); + + sumr += pm_ungamma709((float)PPM_GETR(color)/maxval); + sumg += pm_ungamma709((float)PPM_GETG(color)/maxval); + sumb += pm_ungamma709((float)PPM_GETB(color)/maxval); + + value = ppm_colorvalue(color); + b <<= 1; + if (value > maxval/2) + b |= 1; + } + } + colorstr = rgb2x2x2fg + [sumr >= sumthresh] + [sumg >= sumthresh] + [sumb >= sumthresh]; + fprintf(ofP, "%s%c", colorstr, carr[b]); + } + fprintf(ofP, "\n"); + } + fprintf(ofP, "\x1b[0m"); /* Clear final ansi attributes */ +} + + + +int +main(int argc, const char ** argv) { + + struct cmdlineInfo cmdline; + FILE * ifP; + + pixval maxval; + pixel ** pixels; + int rows, cols; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFileName); + + pixels = ppm_readppm(ifP, &cols, &rows, &maxval); + + pm_close(ifP); + + ppmtoascii(pixels, cols, rows, maxval, cmdline, stdout); + + return 0; +} diff --git a/converter/ppm/ppmtobmp.c b/converter/ppm/ppmtobmp.c index c295f70c..6d65d744 100644 --- a/converter/ppm/ppmtobmp.c +++ b/converter/ppm/ppmtobmp.c @@ -20,6 +20,7 @@ #include <string.h> #include "pm_c_util.h" +#include "nstring.h" #include "mallocvar.h" #include "shhopt.h" #include "bmp.h" @@ -63,11 +64,11 @@ freeColorMap(const colorMap * const colorMapP) { -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - char *input_filename; + const char * inputFilename; int class; /* C_WIN or C_OS2 */ unsigned int bppSpec; unsigned int bpp; @@ -77,7 +78,7 @@ struct cmdlineInfo { static void parseCommandLine(int argc, const char ** argv, - struct cmdlineInfo * const cmdlineP) { + struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that many of the strings that this function returns in the *cmdline_p structure are actually in the supplied argv array. And @@ -107,7 +108,7 @@ parseCommandLine(int argc, const char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); if (windowsSpec && os2Spec) pm_error("Can't specify both -windows and -os2 options."); @@ -131,13 +132,22 @@ parseCommandLine(int argc, const char ** argv, cmdlineP->mapfile = NULL; if (argc - 1 == 0) - cmdlineP->input_filename = strdup("-"); /* he wants stdin */ + cmdlineP->inputFilename = pm_strdup("-"); /* he wants stdin */ else if (argc - 1 == 1) - cmdlineP->input_filename = strdup(argv[1]); + cmdlineP->inputFilename = pm_strdup(argv[1]); else pm_error("Too many arguments. The only argument accepted " "is the input file specificaton"); + free(option_def); +} + + + +static void +freeCommandLine(struct CmdlineInfo const cmdline) { + + pm_strfree(cmdline.inputFilename); } @@ -177,20 +187,18 @@ PutLong(FILE * const fp, long const v) { * BMP writing */ -static int +static unsigned int BMPwritefileheader(FILE * const fp, - int const class, - unsigned long const bitcount, - unsigned long const x, - unsigned long const y) { + unsigned int const cbSize, + unsigned int const offBits) { /*---------------------------------------------------------------------------- - Return the number of bytes written, or -1 on error. + Return the number of bytes written. -----------------------------------------------------------------------------*/ PutByte(fp, 'B'); PutByte(fp, 'M'); /* cbSize */ - PutLong(fp, BMPlenfile(class, bitcount, -1, x, y)); + PutLong(fp, cbSize); /* xHotSpot */ PutShort(fp, 0); @@ -199,7 +207,7 @@ BMPwritefileheader(FILE * const fp, PutShort(fp, 0); /* offBits */ - PutLong(fp, BMPoffbits(class, bitcount, -1)); + PutLong(fp, offBits); return 14; } @@ -213,9 +221,9 @@ BMPwriteinfoheader(FILE * const fp, unsigned long const x, unsigned long const y) { /*---------------------------------------------------------------------------- - Return the number of bytes written, or -1 on error. + Return the number of bytes written. ----------------------------------------------------------------------------*/ - long cbFix; + unsigned int cbFix; switch (class) { case C_WIN: { @@ -266,7 +274,7 @@ BMPwriteRgb(FILE * const fp, pixval const G, pixval const B) { /*---------------------------------------------------------------------------- - Return the number of bytes written, or -1 on error. + Return the number of bytes written. -----------------------------------------------------------------------------*/ switch (class) { case C_WIN: @@ -282,8 +290,8 @@ BMPwriteRgb(FILE * const fp, return 3; default: pm_error(er_internal, "BMPwriteRgb"); + return -1; /* avoid compiler warning. */ } - return -1; } @@ -294,7 +302,7 @@ BMPwriteColormap(FILE * const ifP, int const bpp, const colorMap * const colorMapP) { /*---------------------------------------------------------------------------- - Return the number of bytes written, or -1 on error. + Return the number of bytes written. -----------------------------------------------------------------------------*/ unsigned int const ncolors = (1 << bpp); @@ -445,7 +453,7 @@ BMPwritebits(FILE * const fp, pixval const maxval, colorhash_table const cht) { /*---------------------------------------------------------------------------- - Return the number of bytes written, or -1 on error. + Return the number of bytes written. -----------------------------------------------------------------------------*/ unsigned int nbyte; int row; @@ -490,6 +498,9 @@ bmpEncode(FILE * const ifP, /*---------------------------------------------------------------------------- Write a BMP file of the given class. -----------------------------------------------------------------------------*/ + unsigned int const cbSize = BMPlenfile(class, bpp, 0, x, y); + unsigned int const offbits = BMPoffbits(class, bpp, 0); + unsigned long nbyte; if (colortype == PALETTE) @@ -498,19 +509,17 @@ bmpEncode(FILE * const ifP, pm_message("Writing %u bits per pixel truecolor (no palette)", bpp); nbyte = 0; /* initial value */ - nbyte += BMPwritefileheader(ifP, class, bpp, x, y); + nbyte += BMPwritefileheader(ifP, cbSize, offbits); nbyte += BMPwriteinfoheader(ifP, class, bpp, x, y); if (colortype == PALETTE) nbyte += BMPwriteColormap(ifP, class, bpp, colorMapP); - if (nbyte != (BMPlenfileheader(class) - + BMPleninfoheader(class) - + BMPlencolormap(class, bpp, 0))) + if (nbyte != offbits) pm_error(er_internal, "BmpEncode 1"); nbyte += BMPwritebits(ifP, x, y, colortype, bpp, pixels, maxval, colorMapP->cht); - if (nbyte != BMPlenfile(class, bpp, -1, x, y)) + if (nbyte != cbSize) pm_error(er_internal, "BmpEncode 2"); } @@ -544,6 +553,8 @@ bmpEncodePbm(FILE * const ifP, Only PBM input uses this routine. Color images represented by 1 bpp via color palette use the general bmpEncode(). */ + unsigned int const cbSize = BMPlenfile(class, 1, 0, cols, rows); + unsigned int const offbits = BMPoffbits(class, 1, 0); unsigned int const adjustedCols = (cols + 31) / 32 * 32; unsigned int const packedBytes = adjustedCols / 8; @@ -555,18 +566,16 @@ bmpEncodePbm(FILE * const ifP, pm_message("Writing 1 bit per pixel with a black-white palette"); nbyte = 0; /* initial value */ - nbyte += BMPwritefileheader(ifP, class, 1, cols, rows); + nbyte += BMPwritefileheader(ifP, cbSize, offbits); nbyte += BMPwriteinfoheader(ifP, class, 1, cols, rows); makeBilevelColorMap(&bilevelColorMap); nbyte += BMPwriteColormap(ifP, class, 1, &bilevelColorMap); - if (nbyte != (BMPlenfileheader(class) - + BMPleninfoheader(class) - + BMPlencolormap(class, 1, 0))) - pm_error(er_internal, "bmpEncodePBM 1"); - + if (nbyte != offbits) + pm_error(er_internal, "bmpEncodePbm 1"); + for (row = 0; row < rows; ++row){ size_t bytesWritten; @@ -581,7 +590,7 @@ bmpEncodePbm(FILE * const ifP, nbyte += bytesWritten; } - if (nbyte != BMPlenfile(class, 1, -1, cols, rows)) + if (nbyte != cbSize) pm_error(er_internal, "bmpEncodePbm 2"); } @@ -822,7 +831,6 @@ doPbm(FILE * const ifP, 32 bit borders and that in BMP the bottom row comes first in order. */ - int const CHARBITS = (sizeof(unsigned char)*8); int const colChars = pbm_packed_bytes(cols); int const adjustedCols = (cols+31) /32 * 32; int const packedBytes = adjustedCols /8; @@ -854,11 +862,8 @@ doPbm(FILE * const ifP, some BMP viewers may get confused with that. */ - if (cols % 8 >0) { - /* adjust final partial byte */ - thisRow[colChars-1] >>= CHARBITS - cols % CHARBITS; - thisRow[colChars-1] <<= CHARBITS - cols % CHARBITS; - } + /* Clean off remainder of fractional last character */ + pbm_cleanrowend_packed(thisRow, cols); } bmpEncodePbm(ofP, class, cols, rows, bitrow); @@ -908,6 +913,8 @@ doPgmPpm(FILE * const ifP, cols, rows, (const pixel**)pixels, maxval, &colorMap); freeColorMap(&colorMap); + + ppm_freearray(pixels, rows); } @@ -916,7 +923,7 @@ int main(int argc, const char ** argv) { - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; FILE * ifP; int rows; int cols; @@ -927,7 +934,7 @@ main(int argc, parseCommandLine(argc, argv, &cmdline); - ifP = pm_openr(cmdline.input_filename); + ifP = pm_openr(cmdline.inputFilename); ppm_readppminit(ifP, &cols, &rows, &maxval, &ppmFormat); @@ -938,6 +945,8 @@ main(int argc, cmdline.class, cmdline.bppSpec, cmdline.bpp, cmdline.mapfile, stdout); + freeCommandLine(cmdline); + pm_close(ifP); pm_close(stdout); diff --git a/converter/ppm/ppmtogif.c b/converter/ppm/ppmtogif.c index 93feaa95..fa7d1dbe 100644 --- a/converter/ppm/ppmtogif.c +++ b/converter/ppm/ppmtogif.c @@ -68,7 +68,7 @@ handleLatex2htmlHack(void) { This program used to put out a "usage" message when it saw an option it didn't understand. Latex2html's configure program does a ppmtogif -h (-h was never a valid option) to elicit that message and - then parses the message to see if it included the strings + then parses the message to see if it includes the strings "-interlace" and "-transparent". That way it knows if the 'ppmtogif' program it found has those options or not. I don't think any 'ppmtogif' you're likely to find today lacks those options, but @@ -91,7 +91,7 @@ handleLatex2htmlHack(void) { static void -parseCommandLine(int argc, char ** argv, +parseCommandLine(int argc, const char ** argv, struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Parse the program arguments (given by argc and argv) into a form @@ -146,7 +146,7 @@ parseCommandLine(int argc, char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (latex2htmlhack) @@ -183,8 +183,8 @@ openPnmremapStream(const char * const inputFileName, assert(inputFileName != NULL); assert(mapFileName != NULL); - asprintfN(&pnmremapCommand, "pnmremap -mapfile='%s' %s", - mapFileName, inputFileName); + pm_asprintf(&pnmremapCommand, "pnmremap -mapfile='%s' %s", + mapFileName, inputFileName); if (verbose) pm_message("Preprocessing Pamtogif input with shell command '%s'", @@ -198,7 +198,7 @@ openPnmremapStream(const char * const inputFileName, else *pnmremapPipeP = pnmremapPipe; - strfree(pnmremapCommand); + pm_strfree(pnmremapCommand); } @@ -221,39 +221,39 @@ pamtogifCommand(const char * const arg0, struct stat statbuf; - asprintfN(&progName, "%s/%s", arg0DirName, pamtogifName); + pm_asprintf(&progName, "%s/%s", arg0DirName, pamtogifName); if (stat(progName, &statbuf) == 0) commandVerb = progName; else commandVerb = strdup(pamtogifName); - strfree(arg0DirName); + pm_strfree(arg0DirName); } else commandVerb = strdup(pamtogifName); if (cmdline.transparent) - asprintfN(&transparentOpt, "-transparent=%s", cmdline.transparent); + pm_asprintf(&transparentOpt, "-transparent=%s", cmdline.transparent); else transparentOpt = strdup(""); if (cmdline.comment) - asprintfN(&commentOpt, "-comment=%s", cmdline.comment); + pm_asprintf(&commentOpt, "-comment=%s", cmdline.comment); else commentOpt = strdup(""); - asprintfN(&retval, "%s - -alphacolor=%s %s %s %s %s %s %s", - commandVerb, - cmdline.alphacolor, - cmdline.interlace ? "-interlace" : "", - cmdline.sort ? "-sort" : "", - transparentOpt, - commentOpt, - cmdline.nolzw ? "-nolzw" : "", - cmdline.verbose ? "-verbose" : ""); + pm_asprintf(&retval, "%s - -alphacolor=%s %s %s %s %s %s %s", + commandVerb, + cmdline.alphacolor, + cmdline.interlace ? "-interlace" : "", + cmdline.sort ? "-sort" : "", + transparentOpt, + commentOpt, + cmdline.nolzw ? "-nolzw" : "", + cmdline.verbose ? "-verbose" : ""); - strfree(transparentOpt); - strfree(commentOpt); + pm_strfree(transparentOpt); + pm_strfree(commentOpt); return retval; } @@ -374,8 +374,8 @@ feedPamtogif(struct pam * const inPamP, int -main(int argc, - char * argv[]) { +main(int argc, + const char ** argv) { struct cmdlineInfo cmdline; FILE * ifP; @@ -384,7 +384,7 @@ main(int argc, FILE * pipeToPamtogif; int rc; - pnm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -413,7 +413,7 @@ main(int argc, if (rc != 0) pm_error("Pamtogif process failed. pclose() failed."); - strfree(command); + pm_strfree(command); pm_close(ifP); pm_close(stdout); diff --git a/converter/ppm/ppmtoicr.c b/converter/ppm/ppmtoicr.c index feca0c18..3c8be421 100644 --- a/converter/ppm/ppmtoicr.c +++ b/converter/ppm/ppmtoicr.c @@ -10,311 +10,255 @@ ** implied warranty. */ +#include <stdbool.h> +#include <assert.h> #include "ppm.h" -#define MAXCOLORS 256 -#define CLUTCOLORS 768 +#define MAXCOLORCT 256 +#define CLUTCOLORCT 768 -static int colorstobpp ARGS(( int colors )); -static int GetPixel ARGS(( int x, int y )); -static int rleit ARGS(( char* buf, char* bufto, int len )); -static pixel** pixels; -static colorhash_table cht; -static char* testimage; -int -main(argc, argv) -int argc; -char* argv[]; -{ - FILE* ifp; - int argn, rows, cols, colors, i, j, BitsPerPixel, newxsize; - pixval maxval; - colorhist_vector chv; - char rgb[CLUTCOLORS]; - const char* windowname; - char* thischar; - char* thisline; - char* space; - register unsigned char c; - register char* p; - int display, expand; - int rleflag, winflag; - const char* const usage = "[-windowname windowname] [-expand expand] [-display display] [-rle] [ppmfile]"; - - - ppm_init( &argc, argv ); - - argn = 1; - windowname = "untitled"; - winflag = 0; - expand = 1; - display = 0; - rleflag = 0; - - while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) - { - if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc ) - { - ++argn; - windowname = argv[argn]; - winflag = 1; - } - else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc ) - { - ++argn; - if ( sscanf( argv[argn], "%d",&expand ) != 1 ) - pm_usage( usage ); - } - else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc ) - { - ++argn; - if ( sscanf( argv[argn], "%d",&display ) != 1 ) - pm_usage( usage ); - } - else if ( pm_keymatch(argv[argn],"-rle",2) ) - rleflag = 1; - else if ( pm_keymatch(argv[argn],"-norle",2) ) - rleflag = 0; - else - pm_usage( usage ); - } - - if ( argn < argc ) - { - ifp = pm_openr( argv[argn] ); - if ( ! winflag ) - windowname = argv[argn]; - ++argn; - } - else - ifp = stdin; - - if ( argn != argc ) - pm_usage( usage ); - - pixels = ppm_readppm( ifp, &cols, &rows, &maxval ); - - pm_close( ifp ); - - for (i = 0; i < CLUTCOLORS; i++) - rgb[i] = 0; - - /* Figure out the colormap. */ - pm_message("computing colormap..." ); - chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors); - if (chv == (colorhist_vector) 0) - pm_error( "too many colors - try doing a 'pnmquant %d'", MAXCOLORS ); - pm_message("%d colors found", colors ); - - /* Turn the ppm colormap into an ICR colormap. */ - if (maxval > 255) - pm_message( - "maxval is not 255 - automatically rescaling colors" ); - for (i = 0; i < colors; i++) - { - j = (3 * i); - if (maxval == 255) - { - rgb[j] = PPM_GETR(chv[i].color) ; - j++; - rgb[j] = PPM_GETG(chv[i].color) ; - j++; - rgb[j] = PPM_GETB(chv[i].color) ; - } - else - { - rgb[j] = (int) PPM_GETR(chv[i].color) * 255 / maxval; - j++; - rgb[j] = (int) PPM_GETG(chv[i].color) * 255 / maxval; - j++; - rgb[j] = (int) PPM_GETB(chv[i].color) * 255 / maxval; - } - } - BitsPerPixel = colorstobpp(colors); - - /* And make a hash table for fast lookup. */ - cht = ppm_colorhisttocolorhash(chv, colors); - ppm_freecolorhist(chv); - - - /************** Create a new window using ICR protocol *********/ - /* Format is "ESC^W;left;top;width;height;display;windowname" */ - - pm_message("creating window %s ...", windowname ); - (void)printf("\033^W;%d;%d;%d;%d;%d;%s^",0,0,cols*expand,rows*expand,display,windowname); - fflush(stdout); - - - /****************** Download the colormap. ********************/ - pm_message("downloading colormap for %s ...", windowname ); - - (void)printf("\033^M;%d;%d;%d;%s^",0,MAXCOLORS,CLUTCOLORS,windowname); - thischar = rgb; - for (j=0; j<CLUTCOLORS; j++) { - c = *thischar++; - if (c > 31 && c < 123 ) { /* printable ASCII */ - putchar(c); - } - else { - putchar((c>>6)+123); /* non-printable, so encode it */ - putchar((c & 0x3f) + 32); - } - } - fflush(stdout); - - /**************** send out picture *************************/ - /* Protocol's RLE scheme is quicker but buggy */ - - if (rleflag) { - pm_message("sending run-length encoded picture data ..." ); - testimage = (char*) malloc(rows*cols); - p = testimage; - for (i=0; i<rows; i++) - for (j=0; j<cols; j++) - *p++ = GetPixel(j,i); - space = (char*) malloc(rows*3); - thisline = testimage; - for (i = 0; i < rows; i++) { - newxsize = rleit(thisline,space,cols); - thisline += cols; /* increment to next line */ - (void)printf("\033^R;%d;%d;%d;%d;%s^",0,i*expand,expand,newxsize,windowname); - thischar = space; - for (j=0; j< newxsize; j++) { - c= *thischar++; /*get byte to send */ - if (c>31 && c <123) { - putchar(c); - } - else { - putchar((c>>6) + 123); - putchar((c & 0x3f) + 32); - } - } - fflush(stdout); - } - free(space); - exit(0); - } - - /* Otherwise, send out uncompressed pixel data via the slow method */ - - else { - pm_message("sending picture data ..." ); - for (i = 0; i < rows; i++) { - (void)printf("\033^P;%d;%d;%d;%d;%s^",0,i*expand,expand,cols,windowname); - for (j = 0; j < cols; j++) { - c = GetPixel(j,i); - if (c > 31 && c < 123) { - putchar(c); - } - else { - putchar((c>>6)+123); - putchar((c & 0x3f) + 32); - } - } - } - fflush(stdout); - exit(0); - } - } +static void +makeIcrColormap(colorhist_vector const chv, + unsigned int const colorCt, + pixval const maxval, + char * const rgb) { + + unsigned int i; + + if (maxval > 255) + pm_message("Maxval is not 255 - automatically rescaling colors" ); + + for (i = 0; i < CLUTCOLORCT; ++i) + rgb[i] = 0; + + for (i = 0; i < colorCt; ++i) { + unsigned int j; + + j = (3 * i); + + if (maxval == 255) { + rgb[j++] = PPM_GETR(chv[i].color) ; + rgb[j++] = PPM_GETG(chv[i].color) ; + rgb[j++] = PPM_GETB(chv[i].color) ; + } else { + rgb[j++] = (unsigned int) PPM_GETR(chv[i].color) * 255 / maxval; + rgb[j++] = (unsigned int) PPM_GETG(chv[i].color) * 255 / maxval; + rgb[j++] = (unsigned int) PPM_GETB(chv[i].color) * 255 / maxval; + } + } +} + + static int -colorstobpp(colors) -int colors; - { - int bpp; - - if (colors <= 2) - bpp = 1; - else if (colors <= 4) - bpp = 2; - else if (colors <= 8) - bpp = 3; - else if (colors <= 16) - bpp = 4; - else if (colors <= 32) - bpp = 5; - else if (colors <= 64) - bpp = 6; - else if (colors <= 128) - bpp = 7; - else if (colors <= 256) - bpp = 8; - else - pm_error("can't happen" ); - return bpp; - } +bppFromColorCt(unsigned int const colorCt) { + + unsigned int bpp; + + if (colorCt <= 2) + bpp = 1; + else if (colorCt <= 4) + bpp = 2; + else if (colorCt <= 8) + bpp = 3; + else if (colorCt <= 16) + bpp = 4; + else if (colorCt <= 32) + bpp = 5; + else if (colorCt <= 64) + bpp = 6; + else if (colorCt <= 128) + bpp = 7; + else if (colorCt <= 256) + bpp = 8; + else + assert(false); + + return bpp; +} + + static int -GetPixel(x, y) -int x, y; - { - int color; +colorIndexAtPosition(unsigned int const x, + unsigned int const y, + pixel ** const pixels, + colorhash_table const cht) { - color = ppm_lookupcolor(cht, &pixels[y][x]); - return color; - } + int rc; + rc = ppm_lookupcolor(cht, &pixels[y][x]); -/* rleit compress with run length encoding as per NCSA's documentation */ + /* Every color in the image is in the palette */ + assert(rc >= 0); -static int -rleit(buf,bufto,len) - char* buf; - char* bufto; - int len; - { - register char* p; - register char* q; - register char* cfoll; - register char* clead; - char* begp; - int i; - - p = buf; - cfoll = bufto; - clead = cfoll + 1; - - begp = p; - while (len > 0 ) { /* encode until gone */ - - q = p + 1; - i = len-1; - while (*p == *q && i+120 > len && i) { - q++; - i--; - } - - if (q > p +2) { /* three in a row */ - if (p > begp) { - *cfoll = p - begp; - cfoll = clead; - } - *cfoll++ = 128 | (q-p); /*len of seq*/ - *cfoll++ = *p; /* char of seq */ - len -= q-p; /* subtract len of seq */ - p = q; - clead = cfoll+1; - begp = p; - } - else { - *clead++ = *p++; /* copy one char */ - len--; - if (p>begp + 120) { - *cfoll = p - begp; - cfoll = clead++; - begp = p; - } - } - } - -/* fillin last bytecount */ - - if (p>begp) - *cfoll = (p - begp); - else - clead--; - - return((int) (clead-bufto)); /*how many stored as encoded */ + return rc; } + + + +static void +downloadColormap(char const rgb[CLUTCOLORCT], + const char * const windowName) { + + unsigned int i; + + pm_message("Downloading colormap for %s ...", windowName); + + printf("\033^M;%d;%d;%d;%s^", + 0, MAXCOLORCT, CLUTCOLORCT, windowName); + + for (i = 0; i < CLUTCOLORCT; ++i) { + unsigned char const c = rgb[i]; + + if (c > 31 && c < 123) { + /* printable ASCII */ + putchar(c); + } else { + /* non-printable, so encode it */ + putchar((c >> 6) + 123); + putchar((c & 0x3f) + 32); + } + } + fflush(stdout); +} + + + +static void +sendOutPicture(pixel ** const pixels, + unsigned int const rows, + unsigned int const cols, + colorhash_table const cht, + int const expand, + const char * const windowName) { + + unsigned int row; + + pm_message("Sending picture data ..." ); + + for (row = 0; row < rows; ++row) { + unsigned int col; + printf("\033^P;%d;%d;%d;%d;%s^", + 0, row * expand, expand, cols, windowName); + for (col = 0; col < cols; ++col) { + unsigned char const c = + colorIndexAtPosition(col, row, pixels, cht); + if (c > 31 && c < 123) { + putchar(c); + } else { + putchar((c >> 6) + 123); + putchar((c & 0x3f) + 32); + } + } + } + fflush(stdout); +} + + + +int +main(int argc, const char ** const argv) { + + FILE * ifP; + int rows, cols; + int colorCt; + int argn; + unsigned int bitsPerPixel; + pixval maxval; + colorhist_vector chv; + char rgb[CLUTCOLORCT]; + const char * windowName; + int display, expand; + int winflag; + const char* const usage = "[-windowname windowname] [-expand expand] [-display display] [ppmfile]"; + pixel** pixels; + colorhash_table cht; + + pm_proginit(&argc, argv); + + argn = 1; + windowName = "untitled"; + winflag = 0; + expand = 1; + display = 0; + + while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) + { + if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc ) + { + ++argn; + windowName = argv[argn]; + winflag = 1; + } + else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc ) + { + ++argn; + if ( sscanf( argv[argn], "%d",&expand ) != 1 ) + pm_usage( usage ); + } + else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc ) + { + ++argn; + if ( sscanf( argv[argn], "%d",&display ) != 1 ) + pm_usage( usage ); + } + else + pm_usage( usage ); + } + + if ( argn < argc ) + { + ifP = pm_openr( argv[argn] ); + if ( ! winflag ) + windowName = argv[argn]; + ++argn; + } + else + ifP = stdin; + + if ( argn != argc ) + pm_usage( usage ); + + pixels = ppm_readppm(ifP, &cols, &rows, &maxval); + + pm_close(ifP); + + /* Figure out the colormap. */ + pm_message("Computing colormap..." ); + chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORCT, &colorCt); + if (!chv) + pm_error("Too many colors - try doing a 'pnmquant %u'", MAXCOLORCT); + pm_message("%u colors found", colorCt ); + + makeIcrColormap(chv, colorCt, maxval, rgb); + + bitsPerPixel = bppFromColorCt(colorCt); + + /* And make a hash table for fast lookup. */ + cht = ppm_colorhisttocolorhash(chv, colorCt); + + ppm_freecolorhist(chv); + + /************** Create a new window using ICR protocol *********/ + /* Format is "ESC^W;left;top;width;height;display;windowname" */ + + pm_message("Creating window %s ...", windowName); + + printf("\033^W;%d;%d;%d;%d;%d;%s^", + 0, 0, cols * expand, rows * expand, display, windowName); + fflush(stdout); + + /****************** Download the colormap. ********************/ + + downloadColormap(rgb, windowName); + + sendOutPicture(pixels, rows, cols, cht, expand, windowName); + + return 0; +} + + + diff --git a/converter/ppm/ppmtoilbm.c b/converter/ppm/ppmtoilbm.c index d296f498..595aa3f4 100644 --- a/converter/ppm/ppmtoilbm.c +++ b/converter/ppm/ppmtoilbm.c @@ -38,8 +38,11 @@ ** - added IFF text chunks ** ** Feb 2010: afu -** Added dimension check to prevent short int from overflowing. -** +** - added dimension check to prevent short int from overflowing. +** +** June 2015: afu +** - moved byterun1 (or Packbits) compression to lib/util/runlenth.c +** - fixed bug with HAM -nocompress ** ** TODO: ** - multipalette capability (PCHG chunk) for std and HAM @@ -64,6 +67,7 @@ ** implied warranty. */ +#include <assert.h> #include <string.h> #include "pm_c_util.h" @@ -71,6 +75,7 @@ #include "ppm.h" #include "ppmfloyd.h" #include "pbm.h" +#include "runlength.h" #include "ilbm.h" #include "lum.h" @@ -106,31 +111,6 @@ #define INT16MAX 32767 -static void put_big_short ARGS((short s)); -static void put_big_long ARGS((long l)); -#define put_byte(b) (void)(putc((unsigned char)(b), stdout)) -static void write_bytes ARGS((unsigned char *buffer, int bytes)); -static void ppm_to_ham ARGS((FILE *fp, int cols, int rows, int maxval, pixel *colormap, int colors, int cmapmaxval, int hamplanes)); -static void ppm_to_deep ARGS((FILE *fp, int cols, int rows, int maxval, int bitspercolor)); -static void ppm_to_dcol ARGS((FILE *fp, int cols, int rows, int maxval, DirectColor *dcol)); -static void ppm_to_rgb8 ARGS((FILE *fp, int cols, int rows, int maxval)); -static void ppm_to_rgbn ARGS((FILE *fp, int cols, int rows, int maxval)); -static void ppm_to_std ARGS((FILE *fp, int cols, int rows, int maxval, pixel *colormap, int colors, int cmapmaxval, int maxcolors, int nPlanes)); -static void ppm_to_cmap ARGS((pixel *colormap, int colors, int maxval)); -static void write_bmhd ARGS((int cols, int rows, int nPlanes)); -static void write_cmap ARGS((pixel *colormap, int colors, int maxval)); -static long encode_row ARGS((FILE *outfile, rawtype *rawrow, int cols, int nPlanes)); -static long encode_maskrow ARGS((FILE *outfile, rawtype *rawrow, int cols)); -static int compress_row ARGS((int bytes)); -static void store_bodyrow ARGS((unsigned char *row, int len)); -static int runbyte1 ARGS((int bytes)); -static pixel * next_pixrow ARGS((FILE *fp, int row)); -static int * make_val_table ARGS((int oldmaxval, int newmaxval)); -static void init_read ARGS((FILE *fp, int *colsP, int *rowsP, pixval *maxvalP, int *formatP, int readall)); -static void write_body_rows ARGS((void)); -static void write_camg ARGS((void)); -static int length_of_text_chunks ARGS((void)); -static void write_text_chunks ARGS((void)); #define PAD(n) (ODD(n) ? 1 : 0) /* pad to a word */ @@ -183,25 +163,394 @@ static short gen_camg = 0; /* write CAMG chunk */ #define WORSTCOMPR(bytes) ((bytes) + (bytes)/128 + 1) #define DO_COMPRESS (compmethod != cmpNone) +#define NEWDEPTH(pix, table) PPM_ASSIGN((pix), (table)[PPM_GETR(pix)], (table)[PPM_GETG(pix)], (table)[PPM_GETB(pix)]) -/***** parse options and figure out what kind of ILBM to write *****/ +#define putByte(b) (void)(putc((unsigned char)(b), stdout)) -static int get_int_val ARGS((char *string, char *option, int bot, int top)); -static int get_compr_method ARGS((char *string)); -static int get_mask_type ARGS((char *string)); -static int get_hammap_mode ARGS((char *string)); +/************ other utility functions ************/ + + + +static void +writeBytes(unsigned char * const buffer, + int const bytes) { + + if( fwrite(buffer, 1, bytes, stdout) != bytes ) + pm_error("write error"); +} + + + +static int * +makeValTable(int const oldmaxval, + int const newmaxval) { + + unsigned int i; + int * table; + + MALLOCARRAY_NOFAIL(table, oldmaxval + 1); + for (i = 0; i <= oldmaxval; ++i) + table[i] = ROUNDDIV(i * newmaxval, oldmaxval); + + return table; +} + + + +static int gFormat; +static int gCols; +static int gMaxval; + +static void +initRead(FILE * const fp, + int * const colsP, + int * const rowsP, + pixval * const maxvalP, + int * const formatP, + int const readall) { + + ppm_readppminit(fp, colsP, rowsP, maxvalP, formatP); + + if( *rowsP >INT16MAX || *colsP >INT16MAX ) + pm_error ("Input image is too large."); + + if( readall ) { + int row; + + pixels = ppm_allocarray(*colsP, *rowsP); + for( row = 0; row < *rowsP; row++ ) + ppm_readppmrow(fp, pixels[row], *colsP, *maxvalP, *formatP); + /* pixels = ppm_readppm(fp, colsP, rowsP, maxvalP); */ + } + else { + pixrow = ppm_allocrow(*colsP); + } + gCols = *colsP; + gMaxval = *maxvalP; + gFormat = *formatP; +} + + + +static pixel * +nextPixrow(FILE * const fp, + int const row) { + + if( pixels ) + pixrow = pixels[row]; + else { + ppm_readppmrow(fp, pixrow, gCols, gMaxval, gFormat); + } + if( maskrow ) { + int col; + + if( maskfile ) + pbm_readpbmrow(maskfile, maskrow, maskcols, maskformat); + else { + for( col = 0; col < gCols; col++ ) + maskrow[col] = PBM_BLACK; + } + if( transpColor ) { + for( col = 0; col < gCols; col++ ) + if( PPM_EQUAL(pixrow[col], *transpColor) ) + maskrow[col] = PBM_WHITE; + } + } + return pixrow; +} + + + +/************ ILBM functions ************/ + + + +static int +lengthOfTextChunks(void) { + + int len, n; + + len = 0; + if( anno_chunk ) { + n = strlen(anno_chunk); + len += 4 + 4 + n + PAD(n); /* ID chunksize text */ + } + if( auth_chunk ) { + n = strlen(auth_chunk); + len += 4 + 4 + n + PAD(n); /* ID chunksize text */ + } + if( name_chunk ) { + n = strlen(name_chunk); + len += 4 + 4 + n + PAD(n); /* ID chunksize text */ + } + if( copyr_chunk ) { + n = strlen(copyr_chunk); + len += 4 + 4 + n + PAD(n); /* ID chunksize text */ + } + if( text_chunk ) { + n = strlen(text_chunk); + len += 4 + 4 + n + PAD(n); /* ID chunksize text */ + } + return len; +} + + + +static void +writeTextChunks(void) { + + int n; + + if( anno_chunk ) { + n = strlen(anno_chunk); + pm_writebiglong(stdout, ID_ANNO); + pm_writebiglong(stdout, n); + writeBytes((unsigned char *)anno_chunk, n); + if( ODD(n) ) + putByte(0); + } + if( auth_chunk ) { + n = strlen(auth_chunk); + pm_writebiglong(stdout, ID_AUTH); + pm_writebiglong(stdout, n); + writeBytes((unsigned char *)auth_chunk, n); + if( ODD(n) ) + putByte(0); + } + if( copyr_chunk ) { + n = strlen(copyr_chunk); + pm_writebiglong(stdout, ID_copy); + pm_writebiglong(stdout, n); + writeBytes((unsigned char *)copyr_chunk, n); + if( ODD(n) ) + putByte(0); + } + if( name_chunk ) { + n = strlen(name_chunk); + pm_writebiglong(stdout, ID_NAME); + pm_writebiglong(stdout, n); + writeBytes((unsigned char *)name_chunk, n); + if( ODD(n) ) + putByte(0); + } + if( text_chunk ) { + n = strlen(text_chunk); + pm_writebiglong(stdout, ID_TEXT); + pm_writebiglong(stdout, n); + writeBytes((unsigned char *)text_chunk, n); + if( ODD(n) ) + putByte(0); + } +} + + +static void +writeCmap(pixel * const colormap, + int const colors, + int const maxval) { + + int cmapsize, i; + + cmapsize = 3 * colors; + + /* write colormap */ + pm_writebiglong(stdout, ID_CMAP); + pm_writebiglong(stdout, cmapsize); + if( maxval != MAXCOLVAL ) { + int *table; + pm_message("maxval is not %d - automatically rescaling colors", + MAXCOLVAL); + table = makeValTable(maxval, MAXCOLVAL); + for( i = 0; i < colors; i++ ) { + putByte(table[PPM_GETR(colormap[i])]); + putByte(table[PPM_GETG(colormap[i])]); + putByte(table[PPM_GETB(colormap[i])]); + } + free(table); + } + else { + for( i = 0; i < colors; i++ ) { + putByte(PPM_GETR(colormap[i])); + putByte(PPM_GETG(colormap[i])); + putByte(PPM_GETB(colormap[i])); + } + } + if( ODD(cmapsize) ) + putByte(0); +} + + + +static void +writeBmhd(int const cols, + int const rows, + int const nPlanes) { + + unsigned char xasp, yasp; + + xasp = 10; /* initial value */ + yasp = 10; /* initial value */ + + if( viewportmodes & vmLACE ) + xasp *= 2; + if( viewportmodes & vmHIRES ) + yasp *= 2; + + pm_writebiglong(stdout, ID_BMHD); + pm_writebiglong(stdout, BitMapHeaderSize); + + pm_writebigshort(stdout, cols); + pm_writebigshort(stdout, rows); + pm_writebigshort(stdout, 0); /* x-offset */ + pm_writebigshort(stdout, 0); /* y-offset */ + putByte(nPlanes); /* no of planes */ + putByte(maskmethod); /* masking */ + putByte(compmethod); /* compression */ + putByte(BMHD_FLAGS_CMAPOK); /* flags */ + if( maskmethod == mskHasTransparentColor ) + pm_writebigshort(stdout, transpIndex); + else + pm_writebigshort(stdout, 0); + putByte(xasp); /* x-aspect */ + putByte(yasp); /* y-aspect */ + pm_writebigshort(stdout, cols); /* pageWidth */ + pm_writebigshort(stdout, rows); /* pageHeight */ +} + -#define NEWDEPTH(pix, table) PPM_ASSIGN((pix), (table)[PPM_GETR(pix)], (table)[PPM_GETG(pix)], (table)[PPM_GETB(pix)]) +/************ compression ************/ static void -report_too_many_colors(int const ifmode, - int const maxplanes, - int const hamplanes, - DirectColor const dcol, - int const deepbits) { +storeBodyrow(unsigned char * const row, + int const len) { + + int idx; + + idx = cur_block->used; /* initial value */ + + if (idx >= ROWS_PER_BLOCK) { + MALLOCVAR_NOFAIL(cur_block->next); + cur_block = cur_block->next; + cur_block->used = idx = 0; + cur_block->next = NULL; + } + MALLOCARRAY_NOFAIL(cur_block->row[idx], len); + cur_block->len[idx] = len; + memcpy(cur_block->row[idx], row, len); + ++cur_block->used; +} + + + +static unsigned int +compressRow(unsigned int const bytes) { + + size_t compressedByteCt; + + switch (compmethod) { + case cmpByteRun1: + pm_rlenc_compressbyte( + coded_rowbuf, compr_rowbuf, PM_RLE_PACKBITS, bytes, + &compressedByteCt); + break; + default: + pm_error("compressRow(): unknown compression method %d", + compmethod); + } + storeBodyrow(compr_rowbuf, compressedByteCt); + + assert((unsigned)compressedByteCt == compressedByteCt); + + return (unsigned)compressedByteCt; +} + + + +static const unsigned char bitmask[] = {1, 2, 4, 8, 16, 32, 64, 128}; + + + +static long +encodeRow(FILE * const outfile, + /* if non-NULL, write uncompressed row to this file */ + rawtype * const rawrow, + int const cols, + int const nPlanes) { + + /* encode algorithm by Johan Widen (jw@jwdata.se) */ + + int plane, bytes; + long retbytes = 0; + + bytes = RowBytes(cols); + + /* Encode and write raw bytes in plane-interleaved form. */ + for( plane = 0; plane < nPlanes; plane++ ) { + register int col, cbit; + register rawtype *rp; + register unsigned char *cp; + int mask; + + mask = 1 << plane; + cbit = -1; + cp = coded_rowbuf-1; + rp = rawrow; + for( col = 0; col < cols; col++, cbit--, rp++ ) { + if( cbit < 0 ) { + cbit = 7; + *++cp = 0; + } + if( *rp & mask ) + *cp |= bitmask[cbit]; + } + if( outfile ) { + writeBytes(coded_rowbuf, bytes); + retbytes += bytes; + } + else + retbytes += compressRow(bytes); + } + return retbytes; +} + + + +static long +encodeMaskrow(FILE * const ofP, + rawtype * const rawrow, + int const cols) { + + int col; + + for( col = 0; col < cols; col++ ) { + if( maskrow[col] == PBM_BLACK ) + rawrow[col] = 1; + else + rawrow[col] = 0; + } + return encodeRow(ofP, rawrow, cols, 1); +} + + + +static void +writeCamg(void) { + pm_writebiglong(stdout, ID_CAMG); + pm_writebiglong(stdout, CAMGChunkSize); + pm_writebiglong(stdout, viewportmodes); +} + + + +static void +reportTooManyColors(int const ifmode, + int const maxplanes, + int const hamplanes, + DirectColor const dcol, + int const deepbits) { int const maxcolors = 1 << maxplanes; @@ -237,17 +586,19 @@ report_too_many_colors(int const ifmode, } + static int -get_int_val(string, option, bot, top) - char *string, *option; - int bot, top; -{ +getIntVal(const char * const string, + const char * const option, + int const bot, + int const top) { + int val; - if( sscanf(string, "%d", &val) != 1 ) + if (sscanf(string, "%d", &val) != 1 ) pm_error("option \"%s\" needs integer argument", option); - if( val < bot || val > top ) + if (val < bot || val > top) pm_error("option \"%s\" argument value out of range (%d..%d)", option, bot, top); @@ -255,10 +606,10 @@ get_int_val(string, option, bot, top) } + static int -get_compr_method(string) - char *string; -{ +getComprMethod(const char * const string) { + int retval; if( pm_keymatch(string, "none", 1) || pm_keymatch(string, "0", 1) ) retval = cmpNone; @@ -271,10 +622,10 @@ get_compr_method(string) } + static int -get_mask_type(string) - char *string; -{ +getMaskType(const char * const string) { + int retval; if( pm_keymatch(string, "none", 1) || pm_keymatch(string, "0", 1) ) @@ -297,10 +648,10 @@ get_mask_type(string) } + static int -get_hammap_mode(string) - char *string; -{ +getHammapMode(const char * const string) { + int retval; if( pm_keymatch(string, "grey", 1) || pm_keymatch(string, "gray", 1) ) @@ -320,14 +671,16 @@ get_hammap_mode(string) } + /************ colormap file ************/ + + static void -ppm_to_cmap(colorrow, colors, maxval) - pixel *colorrow; - int colors; - int maxval; -{ +ppmToCmap(pixel * const colorrow, + int const colors, + int const maxval) { + int formsize, cmapsize; cmapsize = colors * 3; @@ -336,27 +689,21 @@ ppm_to_cmap(colorrow, colors, maxval) 4 + /* ILBM */ 4 + 4 + BitMapHeaderSize + /* BMHD size header */ 4 + 4 + cmapsize + PAD(cmapsize) + /* CMAP size colormap */ - length_of_text_chunks(); + lengthOfTextChunks(); - put_big_long(ID_FORM); - put_big_long(formsize); - put_big_long(ID_ILBM); + pm_writebiglong(stdout, ID_FORM); + pm_writebiglong(stdout, formsize); + pm_writebiglong(stdout, ID_ILBM); - write_bmhd(0, 0, 0); - write_text_chunks(); - write_cmap(colorrow, colors, maxval); + writeBmhd(0, 0, 0); + writeTextChunks(); + writeCmap(colorrow, colors, maxval); } -/************ HAM ************/ -static long -do_ham_body ARGS((FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, - pixval hammaxval, int nPlanes, pixel *cmap, int colors)); +/************ HAM ************/ -static int hcmp (const void *va, const void *vb); -static pixel *compute_ham_cmap ARGS((int cols, int rows, int maxval, - int maxcolors, int *colorsP, int hbits)); typedef struct { @@ -365,20 +712,33 @@ typedef struct { } hentry; + +#ifndef LITERAL_FN_DEF_MATCH +static qsort_comparison_fn hcmp; +#endif + static int -hcmp(const void *va, const void *vb) -{ - return(((hentry *)vb)->count - ((hentry *)va)->count); - /* reverse sort, highest count first */ +hcmp(const void * const a, + const void * const b) { + + /* reverse sort, highest count first */ + + const hentry * const vaP = a; + const hentry * const vbP = b; + + return(vbP->count - vaP->count); } + static pixel * -compute_ham_cmap(cols, rows, maxval, maxcolors, colorsP, hbits) - int cols, rows, maxval, maxcolors; - int *colorsP; - int hbits; -{ +computeHamCmap(int const cols, + int const rows, + int const maxval, + int const maxcolors, + int * const colorsP, + int const hbits) { + int colors; hentry *hmap; pixel *cmap; @@ -405,7 +765,7 @@ compute_ham_cmap(cols, rows, maxval, maxcolors, colorsP, hbits) } } - htable = make_val_table(maxval, hmaxval); + htable = makeValTable(maxval, hmaxval); for( row = 0; row < rows; row++ ) { unsigned int col; for( col = 0; col < cols; ++col) { @@ -485,167 +845,38 @@ out: } -static void -ppm_to_ham(fp, cols, rows, maxval, colormap, colors, cmapmaxval, hamplanes) - FILE *fp; - int cols, rows, maxval; - pixel *colormap; - int colors, cmapmaxval, hamplanes; -{ - int hamcolors, nPlanes, i, hammaxval; - long oldsize, bodysize, formsize, cmapsize; - int *table = NULL; - - if( maskmethod == mskHasTransparentColor ) { - pm_message("masking method '%s' not usable with HAM - " - "using '%s' instead", - mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]); - maskmethod = mskHasMask; - } - - hamcolors = 1 << (hamplanes-2); - hammaxval = pm_bitstomaxval(hamplanes-2); - - if( colors == 0 ) { - /* no colormap, make our own */ - switch( hammapmode ) { - case HAMMODE_GRAY: - colors = hamcolors; - MALLOCARRAY_NOFAIL(colormap, colors); -#ifdef DEBUG - pm_message("generating grayscale colormap"); -#endif - table = make_val_table(hammaxval, MAXCOLVAL); - for( i = 0; i < colors; i++ ) - PPM_ASSIGN(colormap[i], table[i], table[i], table[i]); - free(table); - cmapmaxval = MAXCOLVAL; - break; - case HAMMODE_FIXED: { - int entries, val; - double step; -#ifdef DEBUG - pm_message("generating rgb colormap"); -#endif - /* generate a colormap of 7 "rays" in an RGB color cube: - r, g, b, r+g, r+b, g+b, r+g+b - we need one colormap entry for black, so the number of - entries per ray is (maxcolors-1)/7 */ +static void +writeBodyRows(void) { - entries = (hamcolors-1)/7; - colors = 7*entries+1; - MALLOCARRAY_NOFAIL(colormap, colors); - step = (double)MAXCOLVAL / (double)entries; + bodyblock *b; + int i; + long total = 0; - PPM_ASSIGN(colormap[0], 0, 0, 0); - for( i = 1; i <= entries; i++ ) { - val = (int)((double)i * step); - PPM_ASSIGN(colormap[ i], val, 0, 0); /* r */ - PPM_ASSIGN(colormap[ entries+i], 0, val, 0); /* g */ - PPM_ASSIGN(colormap[2*entries+i], 0, 0, val); /* b */ - PPM_ASSIGN(colormap[3*entries+i], val, val, 0); /* r+g */ - PPM_ASSIGN(colormap[4*entries+i], val, 0, val); /* r+b */ - PPM_ASSIGN(colormap[5*entries+i], 0, val, val); /* g+b */ - PPM_ASSIGN(colormap[6*entries+i], val, val, val); /*r+g+b*/ - } - cmapmaxval = MAXCOLVAL; - } - break; - case HAMMODE_RGB4: - colormap = compute_ham_cmap(cols, rows, maxval, hamcolors, - &colors, 4); - cmapmaxval = 15; - break; - case HAMMODE_RGB5: - colormap = compute_ham_cmap(cols, rows, maxval, - hamcolors, &colors, 5); - cmapmaxval = 31; - break; - default: - pm_error("ppm_to_ham(): unknown hammapmode - can't happen"); - } - } - else { - hammapmode = HAMMODE_MAPFILE; - if( colors > hamcolors ) { - pm_message("colormap too large - using first %d colors", - hamcolors); - colors = hamcolors; + for( b = &firstblock; b != NULL; b = b->next ) { + for( i = 0; i < b->used; i++ ) { + writeBytes(b->row[i], b->len[i]); + total += b->len[i]; } } - - if( cmapmaxval != maxval ) { - int i, *table; - pixel *newcmap; - - newcmap = ppm_allocrow(colors); - table = make_val_table(cmapmaxval, maxval); - for( i = 0; i < colors; i++ ) - PPM_ASSIGN(newcmap[i], - table[PPM_GETR(colormap[i])], - table[PPM_GETG(colormap[i])], - table[PPM_GETB(colormap[i])]); - free(table); - ppm_freerow(colormap); - colormap = newcmap; - } - if( sortcmap ) - ppm_sortcolorrow(colormap, colors, PPM_STDSORT); - - nPlanes = hamplanes; - cmapsize = colors * 3; - - bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols); - if( DO_COMPRESS ) { - bodysize = do_ham_body(fp, NULL, cols, rows, maxval, - hammaxval, nPlanes, colormap, colors); - /*bodysize = do_ham_body(fp, NULL, cols, - rows, maxval, hammaxval, nPlanes, colbits, nocolor);*/ - if( bodysize > oldsize ) - pm_message("warning - %s compression increases BODY size " - "by %ld%%", - cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize); - else - pm_message("BODY compression (%s): %ld%%", - cmpNAME[compmethod], 100*(oldsize-bodysize)/oldsize); - } - - - formsize = - 4 + /* ILBM */ - 4 + 4 + BitMapHeaderSize + /* BMHD size header */ - 4 + 4 + CAMGChunkSize + /* CAMG size viewportmodes */ - 4 + 4 + cmapsize + PAD(cmapsize) + /* CMAP size colormap */ - 4 + 4 + bodysize + PAD(bodysize) + /* BODY size data */ - length_of_text_chunks(); - - put_big_long(ID_FORM); - put_big_long(formsize); - put_big_long(ID_ILBM); - - write_bmhd(cols, rows, nPlanes); - write_text_chunks(); - write_camg(); /* HAM requires CAMG chunk */ - write_cmap(colormap, colors, maxval); - - /* write body */ - put_big_long(ID_BODY); - put_big_long(bodysize); - if( DO_COMPRESS ) - write_body_rows(); - else - do_ham_body(fp, stdout, cols, rows, maxval, hammaxval, - nPlanes, colormap, colors); + if( ODD(total) ) + putByte(0); } + static long -do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows, - pixval maxval, pixval hammaxval, int nPlanes, - pixel *colormap, int colors) -{ - register int col, row, i; +doHamBody(FILE * const ifP, + FILE * const ofP, + int const cols, + int const rows, + pixval const maxval, + pixval const hammaxval, + int const nPlanes, + pixel * const colormap, + int const colors) { + + int col, row, i; rawtype *raw_rowbuf; ppm_fs_info *fi = NULL; colorhash_table cht, cht2; @@ -665,7 +896,7 @@ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows, hamcode_green = HAMCODE_GREEN << colbits; hamcode_blue = HAMCODE_BLUE << colbits; - itoh = make_val_table(maxval, hammaxval); + itoh = makeValTable(maxval, hammaxval); if( floyd ) fi = ppm_fs_init(cols, maxval, 0); @@ -677,7 +908,7 @@ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows, pixel *prow; noprev = 1; - prow = next_pixrow(ifP, row); + prow = nextPixrow(ifP, row); for( col = ppm_fs_startrow(fi, prow); col < cols; col = ppm_fs_next(fi, col) ) { @@ -790,13 +1021,13 @@ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows, } ppm_fs_update3(fi, col, upr, upg, upb); } - bodysize += encode_row(ofp, raw_rowbuf, cols, nPlanes); + bodysize += encodeRow(ofP, raw_rowbuf, cols, nPlanes); if( maskmethod == mskHasMask ) - bodysize += encode_maskrow(ofp, raw_rowbuf, cols); + bodysize += encodeMaskrow(ofP, raw_rowbuf, cols); ppm_fs_endrow(fi); } - if( ofp && ODD(bodysize) ) - put_byte(0); + if( ofP && ODD(bodysize) ) + putByte(0); free(itoh); @@ -808,34 +1039,132 @@ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows, } -/************ deep (24-bit) ************/ - -static long do_deep_body ARGS((FILE *ifP, FILE *ofp, - int cols, int rows, - pixval maxval, int bitspercolor)); static void -ppm_to_deep(fp, cols, rows, maxval, bitspercolor) - FILE *fp; - int cols, rows, maxval, bitspercolor; -{ - int nPlanes; - long bodysize, oldsize, formsize; +ppmToHam(FILE * const ifP, + int const cols, + int const rows, + int const maxval, + pixel * const colormapArg, + int const colorsArg, + int const cmapmaxvalArg, + int const hamplanes) { + + int hamcolors, nPlanes, i, hammaxval; + long oldsize, bodysize, formsize, cmapsize; + int * table; + int colors; + pixel * colormap; + int cmapmaxval; + + table = NULL; /* initial value */ + colors = colorsArg; /* initial value*/ + colormap = colormapArg; /* initial value */ + cmapmaxval = cmapmaxvalArg; /* initial value */ if( maskmethod == mskHasTransparentColor ) { - pm_message("masking method '%s' not usable with deep ILBM - " + pm_message("masking method '%s' not usable with HAM - " "using '%s' instead", - mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]); + mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]); maskmethod = mskHasMask; } - nPlanes = 3*bitspercolor; + hamcolors = 1 << (hamplanes-2); + hammaxval = pm_bitstomaxval(hamplanes-2); + + if( colors == 0 ) { + /* no colormap, make our own */ + switch( hammapmode ) { + case HAMMODE_GRAY: + colors = hamcolors; + MALLOCARRAY_NOFAIL(colormap, colors); + table = makeValTable(hammaxval, MAXCOLVAL); + for( i = 0; i < colors; i++ ) + PPM_ASSIGN(colormap[i], table[i], table[i], table[i]); + free(table); + cmapmaxval = MAXCOLVAL; + break; + case HAMMODE_FIXED: { + int entries, val; + double step; + + /* generate a colormap of 7 "rays" in an RGB color cube: + r, g, b, r+g, r+b, g+b, r+g+b + we need one colormap entry for black, so the number of + entries per ray is (maxcolors-1)/7 */ + + entries = (hamcolors-1)/7; + colors = 7*entries+1; + MALLOCARRAY_NOFAIL(colormap, colors); + step = (double)MAXCOLVAL / (double)entries; + + PPM_ASSIGN(colormap[0], 0, 0, 0); + for( i = 1; i <= entries; i++ ) { + val = (int)((double)i * step); + PPM_ASSIGN(colormap[ i], val, 0, 0); /* r */ + PPM_ASSIGN(colormap[ entries+i], 0, val, 0); /* g */ + PPM_ASSIGN(colormap[2*entries+i], 0, 0, val); /* b */ + PPM_ASSIGN(colormap[3*entries+i], val, val, 0); /* r+g */ + PPM_ASSIGN(colormap[4*entries+i], val, 0, val); /* r+b */ + PPM_ASSIGN(colormap[5*entries+i], 0, val, val); /* g+b */ + PPM_ASSIGN(colormap[6*entries+i], val, val, val); /*r+g+b*/ + } + cmapmaxval = MAXCOLVAL; + } + break; + case HAMMODE_RGB4: + colormap = computeHamCmap(cols, rows, maxval, hamcolors, + &colors, 4); + cmapmaxval = 15; + break; + case HAMMODE_RGB5: + colormap = computeHamCmap(cols, rows, maxval, + hamcolors, &colors, 5); + cmapmaxval = 31; + break; + default: + pm_error("ppm_to_ham(): unknown hammapmode - can't happen"); + } + } + else { + hammapmode = HAMMODE_MAPFILE; + if( colors > hamcolors ) { + pm_message("colormap too large - using first %d colors", + hamcolors); + colors = hamcolors; + } + } + + if( cmapmaxval != maxval ) { + int i, *table; + pixel *newcmap; + + newcmap = ppm_allocrow(colors); + table = makeValTable(cmapmaxval, maxval); + for( i = 0; i < colors; i++ ) + PPM_ASSIGN(newcmap[i], + table[PPM_GETR(colormap[i])], + table[PPM_GETG(colormap[i])], + table[PPM_GETB(colormap[i])]); + free(table); + ppm_freerow(colormap); + colormap = newcmap; + } + if( sortcmap ) + ppm_sortcolorrow(colormap, colors, PPM_STDSORT); + + nPlanes = hamplanes; + cmapsize = colors * 3; bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols); if( DO_COMPRESS ) { - bodysize = do_deep_body(fp, NULL, cols, rows, maxval, bitspercolor); + bodysize = doHamBody(ifP, NULL, cols, rows, maxval, + hammaxval, nPlanes, colormap, colors); + /*bodysize = doHamBody(ifP, NULL, cols, + rows, maxval, hammaxval, nPlanes, colbits, nocolor);*/ if( bodysize > oldsize ) - pm_message("warning - %s compression increases BODY size by %ld%%", + pm_message("warning - %s compression increases BODY size " + "by %ld%%", cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize); else pm_message("BODY compression (%s): %ld%%", @@ -846,35 +1175,45 @@ ppm_to_deep(fp, cols, rows, maxval, bitspercolor) formsize = 4 + /* ILBM */ 4 + 4 + BitMapHeaderSize + /* BMHD size header */ + 4 + 4 + CAMGChunkSize + /* CAMG size viewportmodes */ + 4 + 4 + cmapsize + PAD(cmapsize) + /* CMAP size colormap */ 4 + 4 + bodysize + PAD(bodysize) + /* BODY size data */ - length_of_text_chunks(); - if( gen_camg ) - formsize += 4 + 4 + CAMGChunkSize; /* CAMG size viewportmodes */ + lengthOfTextChunks(); - put_big_long(ID_FORM); - put_big_long(formsize); - put_big_long(ID_ILBM); + pm_writebiglong(stdout, ID_FORM); + pm_writebiglong(stdout, formsize); + pm_writebiglong(stdout, ID_ILBM); - write_bmhd(cols, rows, nPlanes); - write_text_chunks(); - if( gen_camg ) - write_camg(); + writeBmhd(cols, rows, nPlanes); + writeTextChunks(); + writeCamg(); /* HAM requires CAMG chunk */ + writeCmap(colormap, colors, maxval); /* write body */ - put_big_long(ID_BODY); - put_big_long(bodysize); + pm_writebiglong(stdout, ID_BODY); + pm_writebiglong(stdout, bodysize); if( DO_COMPRESS ) - write_body_rows(); + writeBodyRows(); else - do_deep_body(fp, stdout, cols, rows, maxval, bitspercolor); + doHamBody(ifP, stdout, cols, rows, maxval, hammaxval, + nPlanes, colormap, colors); } + +/************ deep (24-bit) ************/ + + + static long -do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, - int bitspercolor) -{ - register int row, col; +doDeepBody(FILE * const ifP, + FILE * const ofP, + int const cols, + int const rows, + pixval const maxval, + int const bitspercolor) { + + int row, col; pixel *pP; int *table = NULL; long bodysize = 0; @@ -889,11 +1228,11 @@ do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, if( maxval != newmaxval ) { pm_message("maxval is not %d - automatically rescaling colors", newmaxval); - table = make_val_table(maxval, newmaxval); + table = makeValTable(maxval, newmaxval); } for( row = 0; row < rows; row++ ) { - pP = next_pixrow(ifP, row); + pP = nextPixrow(ifP, row); if( table ) { for( col = 0; col < cols; col++, pP++ ) { redbuf[col] = table[PPM_GETR(*pP)]; @@ -908,14 +1247,14 @@ do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, bluebuf[col] = PPM_GETB(*pP); } } - bodysize += encode_row(ofp, redbuf, cols, bitspercolor); - bodysize += encode_row(ofp, greenbuf, cols, bitspercolor); - bodysize += encode_row(ofp, bluebuf, cols, bitspercolor); + bodysize += encodeRow(ofP, redbuf, cols, bitspercolor); + bodysize += encodeRow(ofP, greenbuf, cols, bitspercolor); + bodysize += encodeRow(ofP, bluebuf, cols, bitspercolor); if( maskmethod == mskHasMask ) - bodysize += encode_maskrow(ofp, redbuf, cols); + bodysize += encodeMaskrow(ofP, redbuf, cols); } - if( ofp && ODD(bodysize) ) - put_byte(0); + if( ofP && ODD(bodysize) ) + putByte(0); /* clean up */ if( table ) @@ -928,83 +1267,78 @@ do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, } -/************ direct color ************/ - -static long do_dcol_body ARGS((FILE *ifP, FILE *ofp, int cols, int rows, - pixval maxval, DirectColor *dcol)); static void -ppm_to_dcol(fp, cols, rows, maxval, dcol) - FILE *fp; - int cols, rows, maxval; - DirectColor *dcol; -{ +ppmToDeep(FILE * const ifP, + int const cols, + int const rows, + int const maxval, + int const bitspercolor) { + int nPlanes; long bodysize, oldsize, formsize; if( maskmethod == mskHasTransparentColor ) { pm_message("masking method '%s' not usable with deep ILBM - " "using '%s' instead", - mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]); + mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]); maskmethod = mskHasMask; } - nPlanes = dcol->r + dcol->g + dcol->b; + nPlanes = 3*bitspercolor; bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols); if( DO_COMPRESS ) { - bodysize = do_dcol_body(fp, NULL, cols, rows, maxval, dcol); + bodysize = doDeepBody(ifP, NULL, cols, rows, maxval, bitspercolor); if( bodysize > oldsize ) pm_message("warning - %s compression increases BODY size by %ld%%", - cmpNAME[compmethod], - 100*(bodysize-oldsize)/oldsize); + cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize); else - pm_message("BODY compression (%s): %ld%%", cmpNAME[compmethod], - 100*(oldsize-bodysize)/oldsize); + pm_message("BODY compression (%s): %ld%%", + cmpNAME[compmethod], 100*(oldsize-bodysize)/oldsize); } - formsize = 4 + /* ILBM */ 4 + 4 + BitMapHeaderSize + /* BMHD size header */ - 4 + 4 + DirectColorSize + /* DCOL size dcol */ 4 + 4 + bodysize + PAD(bodysize) + /* BODY size data */ - length_of_text_chunks(); + lengthOfTextChunks(); if( gen_camg ) formsize += 4 + 4 + CAMGChunkSize; /* CAMG size viewportmodes */ - put_big_long(ID_FORM); - put_big_long(formsize); - put_big_long(ID_ILBM); - - write_bmhd(cols, rows, nPlanes); - write_text_chunks(); - - put_big_long(ID_DCOL); - put_big_long(DirectColorSize); - put_byte(dcol->r); - put_byte(dcol->g); - put_byte(dcol->b); - put_byte(0); /* pad */ + pm_writebiglong(stdout, ID_FORM); + pm_writebiglong(stdout, formsize); + pm_writebiglong(stdout, ID_ILBM); + writeBmhd(cols, rows, nPlanes); + writeTextChunks(); if( gen_camg ) - write_camg(); + writeCamg(); /* write body */ - put_big_long(ID_BODY); - put_big_long(bodysize); + pm_writebiglong(stdout, ID_BODY); + pm_writebiglong(stdout, bodysize); if( DO_COMPRESS ) - write_body_rows(); + writeBodyRows(); else - do_dcol_body(fp, stdout, cols, rows, maxval, dcol); + doDeepBody(ifP, stdout, cols, rows, maxval, bitspercolor); } + +/************ direct color ************/ + + + static long -do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, - DirectColor *dcol) -{ - register int row, col; +doDcolBody(FILE * const ifP, + FILE * const ofP, + int const cols, + int const rows, + pixval const maxval, + DirectColor * const dcol) { + + int row, col; pixel *pP; long bodysize = 0; rawtype *redbuf, *greenbuf, *bluebuf; @@ -1014,25 +1348,25 @@ do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, MALLOCARRAY_NOFAIL(greenbuf, cols); MALLOCARRAY_NOFAIL(bluebuf, cols); - redtable = make_val_table(maxval, pm_bitstomaxval(dcol->r)); - greentable = make_val_table(maxval, pm_bitstomaxval(dcol->g)); - bluetable = make_val_table(maxval, pm_bitstomaxval(dcol->b)); + redtable = makeValTable(maxval, pm_bitstomaxval(dcol->r)); + greentable = makeValTable(maxval, pm_bitstomaxval(dcol->g)); + bluetable = makeValTable(maxval, pm_bitstomaxval(dcol->b)); for( row = 0; row < rows; row++ ) { - pP = next_pixrow(ifP, row); + pP = nextPixrow(ifP, row); for( col = 0; col < cols; col++, pP++ ) { redbuf[col] = redtable[PPM_GETR(*pP)]; greenbuf[col] = greentable[PPM_GETG(*pP)]; bluebuf[col] = bluetable[PPM_GETB(*pP)]; } - bodysize += encode_row(ofp, redbuf, cols, dcol->r); - bodysize += encode_row(ofp, greenbuf, cols, dcol->g); - bodysize += encode_row(ofp, bluebuf, cols, dcol->b); + bodysize += encodeRow(ofP, redbuf, cols, dcol->r); + bodysize += encodeRow(ofP, greenbuf, cols, dcol->g); + bodysize += encodeRow(ofP, bluebuf, cols, dcol->b); if( maskmethod == mskHasMask ) - bodysize += encode_maskrow(ofp, redbuf, cols); + bodysize += encodeMaskrow(ofP, redbuf, cols); } - if( ofp && ODD(bodysize) ) - put_byte(0); + if( ofP && ODD(bodysize) ) + putByte(0); /* clean up */ free(redtable); @@ -1046,104 +1380,91 @@ do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, } -/************ normal colormapped ************/ - -static long do_std_body ARGS((FILE *ifP, FILE *ofp, int cols, int rows, - pixval maxval, pixel *colormap, - int colors, int nPlanes)); static void -ppm_to_std(fp, cols, rows, maxval, colormap, colors, cmapmaxval, - maxcolors, nPlanes) - FILE *fp; - int cols, rows, maxval; - pixel *colormap; - int cmapmaxval, colors, maxcolors, nPlanes; -{ - long formsize, cmapsize, bodysize, oldsize; +ppmToDcol(FILE * const ifP, + int const cols, + int const rows, + int const maxval, + DirectColor * const dcol) { - if( maskmethod == mskHasTransparentColor ) { - if( transpColor ) { - transpIndex = - ppm_addtocolorrow(colormap, &colors, maxcolors, transpColor); - } - else - if( colors < maxcolors ) - transpIndex = colors; + int nPlanes; + long bodysize, oldsize, formsize; - if( transpIndex < 0 ) { - pm_message("too many colors for masking method '%s' - " - "using '%s' instead", - mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]); - maskmethod = mskHasMask; - } + if( maskmethod == mskHasTransparentColor ) { + pm_message("masking method '%s' not usable with deep ILBM - " + "using '%s' instead", + mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]); + maskmethod = mskHasMask; } - if( cmapmaxval != maxval ) { - int i, *table; - pixel *newcmap; - - newcmap = ppm_allocrow(colors); - table = make_val_table(cmapmaxval, maxval); - for (i = 0; i < colors; ++i) - PPM_ASSIGN(newcmap[i], - table[PPM_GETR(colormap[i])], - table[PPM_GETG(colormap[i])], - table[PPM_GETB(colormap[i])]); - free(table); - colormap = newcmap; - } - if( sortcmap ) - ppm_sortcolorrow(colormap, colors, PPM_STDSORT); + nPlanes = dcol->r + dcol->g + dcol->b; bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols); if( DO_COMPRESS ) { - bodysize = do_std_body(fp, NULL, cols, rows, maxval, colormap, - colors, nPlanes); + bodysize = doDcolBody(ifP, NULL, cols, rows, maxval, dcol); if( bodysize > oldsize ) pm_message("warning - %s compression increases BODY size by %ld%%", - cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize); + cmpNAME[compmethod], + 100*(bodysize-oldsize)/oldsize); else - pm_message("BODY compression (%s): %ld%%", - cmpNAME[compmethod], 100*(oldsize-bodysize)/oldsize); + pm_message("BODY compression (%s): %ld%%", cmpNAME[compmethod], + 100*(oldsize-bodysize)/oldsize); } - cmapsize = colors * 3; formsize = 4 + /* ILBM */ 4 + 4 + BitMapHeaderSize + /* BMHD size header */ - 4 + 4 + cmapsize + PAD(cmapsize) + /* CMAP size colormap */ + 4 + 4 + DirectColorSize + /* DCOL size dcol */ 4 + 4 + bodysize + PAD(bodysize) + /* BODY size data */ - length_of_text_chunks(); + lengthOfTextChunks(); if( gen_camg ) formsize += 4 + 4 + CAMGChunkSize; /* CAMG size viewportmodes */ - put_big_long(ID_FORM); - put_big_long(formsize); - put_big_long(ID_ILBM); + pm_writebiglong(stdout, ID_FORM); + pm_writebiglong(stdout, formsize); + pm_writebiglong(stdout, ID_ILBM); + + writeBmhd(cols, rows, nPlanes); + writeTextChunks(); + + pm_writebiglong(stdout, ID_DCOL); + pm_writebiglong(stdout, DirectColorSize); + putByte(dcol->r); + putByte(dcol->g); + putByte(dcol->b); + putByte(0); /* pad */ - write_bmhd(cols, rows, nPlanes); - write_text_chunks(); if( gen_camg ) - write_camg(); - write_cmap(colormap, colors, maxval); + writeCamg(); /* write body */ - put_big_long(ID_BODY); - put_big_long(bodysize); + pm_writebiglong(stdout, ID_BODY); + pm_writebiglong(stdout, bodysize); if( DO_COMPRESS ) - write_body_rows(); + writeBodyRows(); else - do_std_body(fp, stdout, cols, rows, maxval, colormap, colors, nPlanes); + doDcolBody(ifP, stdout, cols, rows, maxval, dcol); } + +/************ normal colormapped ************/ + + + static long -do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, - pixel *colormap, int colors, int nPlanes) -{ - register int row, col, i; +doStdBody(FILE * const ifP, + FILE * const ofP, + int const cols, + int const rows, + pixval const maxval, + pixel * const colormap, + int const colors, + int const nPlanes) { + + int row, col, i; pixel *pP; rawtype *raw_rowbuf; ppm_fs_info *fi = NULL; @@ -1158,7 +1479,7 @@ do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, for( row = 0; row < rows; row++ ) { pixel *prow; - prow = next_pixrow(ifP, row); + prow = nextPixrow(ifP, row); for( col = ppm_fs_startrow(fi, prow); col < cols; @@ -1188,13 +1509,13 @@ do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, raw_rowbuf[col] = i; ppm_fs_update(fi, col, &colormap[i]); } - bodysize += encode_row(ofp, raw_rowbuf, cols, nPlanes); + bodysize += encodeRow(ofP, raw_rowbuf, cols, nPlanes); if( maskmethod == mskHasMask ) - bodysize += encode_maskrow(ofp, raw_rowbuf, cols); + bodysize += encodeMaskrow(ofP, raw_rowbuf, cols); ppm_fs_endrow(fi); } - if( ofp && ODD(bodysize) ) - put_byte(0); + if( ofP && ODD(bodysize) ) + putByte(0); /* clean up */ ppm_freecolorhash(cht); @@ -1204,14 +1525,117 @@ do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, return bodysize; } + + +static void +ppmToStd(FILE * const ifP, + int const cols, + int const rows, + int const maxval, + pixel * const colormapArg, + int const colorsArg, + int const cmapmaxvalArg, + int const maxcolors, + int const nPlanes) { + + long formsize, cmapsize, bodysize, oldsize; + + int colors; + pixel * colormap; + int cmapmaxval; + + colors = colorsArg; /* initial value */ + colormap = colormapArg; /* initial value */ + cmapmaxval = cmapmaxvalArg; /* initial value */ + + if( maskmethod == mskHasTransparentColor ) { + if( transpColor ) { + transpIndex = + ppm_addtocolorrow(colormap, &colors, maxcolors, transpColor); + } + else + if( colors < maxcolors ) + transpIndex = colors; + + if( transpIndex < 0 ) { + pm_message("too many colors for masking method '%s' - " + "using '%s' instead", + mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]); + maskmethod = mskHasMask; + } + } + + if( cmapmaxval != maxval ) { + int i, *table; + pixel *newcmap; + + newcmap = ppm_allocrow(colors); + table = makeValTable(cmapmaxval, maxval); + for (i = 0; i < colors; ++i) + PPM_ASSIGN(newcmap[i], + table[PPM_GETR(colormap[i])], + table[PPM_GETG(colormap[i])], + table[PPM_GETB(colormap[i])]); + free(table); + colormap = newcmap; + } + if( sortcmap ) + ppm_sortcolorrow(colormap, colors, PPM_STDSORT); + + bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols); + if( DO_COMPRESS ) { + bodysize = doStdBody(ifP, NULL, cols, rows, maxval, colormap, + colors, nPlanes); + if( bodysize > oldsize ) + pm_message("warning - %s compression increases BODY size by %ld%%", + cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize); + else + pm_message("BODY compression (%s): %ld%%", + cmpNAME[compmethod], 100*(oldsize-bodysize)/oldsize); + } + + cmapsize = colors * 3; + + formsize = + 4 + /* ILBM */ + 4 + 4 + BitMapHeaderSize + /* BMHD size header */ + 4 + 4 + cmapsize + PAD(cmapsize) + /* CMAP size colormap */ + 4 + 4 + bodysize + PAD(bodysize) + /* BODY size data */ + lengthOfTextChunks(); + if( gen_camg ) + formsize += 4 + 4 + CAMGChunkSize; /* CAMG size viewportmodes */ + + pm_writebiglong(stdout, ID_FORM); + pm_writebiglong(stdout, formsize); + pm_writebiglong(stdout, ID_ILBM); + + writeBmhd(cols, rows, nPlanes); + writeTextChunks(); + if( gen_camg ) + writeCamg(); + writeCmap(colormap, colors, maxval); + + /* write body */ + pm_writebiglong(stdout, ID_BODY); + pm_writebiglong(stdout, bodysize); + if( DO_COMPRESS ) + writeBodyRows(); + else + doStdBody(ifP, stdout, cols, rows, maxval, colormap, colors, nPlanes); +} + + + /************ RGB8 ************/ + + static void -ppm_to_rgb8(ifP, cols, rows, maxval) - FILE *ifP; - int cols, rows; - int maxval; -{ +ppmToRgb8(FILE * const ifP, + int const cols, + int const rows, + int const maxval) { + long bodysize, oldsize, formsize; pixel *pP; int *table = NULL; @@ -1224,13 +1648,13 @@ ppm_to_rgb8(ifP, cols, rows, maxval) if( maxval != 255 ) { pm_message("maxval is not 255 - automatically rescaling colors"); - table = make_val_table(maxval, 255); + table = makeValTable(maxval, 255); } oldsize = cols * rows * 4; bodysize = 0; for( row = 0; row < rows; row++ ) { - pP = next_pixrow(ifP, row); + pP = nextPixrow(ifP, row); compr_len = 0; for( col1 = 0; col1 < cols; col1 = col2 ) { col2 = col1 + 1; @@ -1264,7 +1688,7 @@ ppm_to_rgb8(ifP, cols, rows, maxval) ++compr_len; } } - store_bodyrow(compr_row, compr_len); + storeBodyrow(compr_row, compr_len); bodysize += compr_len; } @@ -1275,31 +1699,34 @@ ppm_to_rgb8(ifP, cols, rows, maxval) 4 + 4 + BitMapHeaderSize + /* BMHD size header */ 4 + 4 + CAMGChunkSize + /* CAMG size viewportmode */ 4 + 4 + bodysize + PAD(bodysize) + /* BODY size data */ - length_of_text_chunks(); + lengthOfTextChunks(); /* write header */ - put_big_long(ID_FORM); - put_big_long(formsize); - put_big_long(ID_RGB8); + pm_writebiglong(stdout, ID_FORM); + pm_writebiglong(stdout, formsize); + pm_writebiglong(stdout, ID_RGB8); - write_bmhd(cols, rows, 25); - write_text_chunks(); - write_camg(); /* RGB8 requires CAMG chunk */ + writeBmhd(cols, rows, 25); + writeTextChunks(); + writeCamg(); /* RGB8 requires CAMG chunk */ - put_big_long(ID_BODY); - put_big_long(bodysize); - write_body_rows(); + pm_writebiglong(stdout, ID_BODY); + pm_writebiglong(stdout, bodysize); + writeBodyRows(); } + /************ RGBN ************/ + + static void -ppm_to_rgbn(ifP, cols, rows, maxval) - FILE *ifP; - int cols, rows; - int maxval; -{ +ppmToRgbn(FILE * const ifP, + int const cols, + int const rows, + int const maxval) { + long bodysize, oldsize, formsize; pixel *pP; int *table = NULL; @@ -1312,13 +1739,13 @@ ppm_to_rgbn(ifP, cols, rows, maxval) if( maxval != 15 ) { pm_message("maxval is not 15 - automatically rescaling colors"); - table = make_val_table(maxval, 15); + table = makeValTable(maxval, 15); } oldsize = cols * rows * 2; bodysize = 0; for( row = 0; row < rows; row++ ) { - pP = next_pixrow(ifP, row); + pP = nextPixrow(ifP, row); compr_len = 0; for( col1 = 0; col1 < cols; col1 = col2 ) { col2 = col1 + 1; @@ -1368,7 +1795,7 @@ ppm_to_rgbn(ifP, cols, rows, maxval) } } } - store_bodyrow(compr_row, compr_len); + storeBodyrow(compr_row, compr_len); bodysize += compr_len; } @@ -1379,40 +1806,43 @@ ppm_to_rgbn(ifP, cols, rows, maxval) 4 + 4 + BitMapHeaderSize + /* BMHD size header */ 4 + 4 + CAMGChunkSize + /* CAMG size viewportmode */ 4 + 4 + bodysize + PAD(bodysize) + /* BODY size data */ - length_of_text_chunks(); + lengthOfTextChunks(); /* write header */ - put_big_long(ID_FORM); - put_big_long(formsize); - put_big_long(ID_RGBN); + pm_writebiglong(stdout, ID_FORM); + pm_writebiglong(stdout, formsize); + pm_writebiglong(stdout, ID_RGBN); - write_bmhd(cols, rows, 13); - write_text_chunks(); - write_camg(); /* RGBN requires CAMG chunk */ + writeBmhd(cols, rows, 13); + writeTextChunks(); + writeCamg(); /* RGBN requires CAMG chunk */ - put_big_long(ID_BODY); - put_big_long(bodysize); - write_body_rows(); + pm_writebiglong(stdout, ID_BODY); + pm_writebiglong(stdout, bodysize); + writeBodyRows(); } + /************ multipalette ************/ + + #ifdef ILBM_PCHG static pixel *ppmslice[2]; /* need 2 for laced ILBMs, else 1 */ -void ppm_to_pchg() -{ +void +ppmToPchg() { /* read first slice build a colormap from this slice - select upto <maxcolors> colors + select up to <maxcolors> colors build colormap from selected colors map slice to colormap write slice while( !finished ) { read next slice - compute distances for each pixel and select upto + compute distances for each pixel and select up to <maxchangesperslice> unused colors in this slice modify selected colors to the ones with maximum(?) distance map slice to colormap @@ -1431,432 +1861,6 @@ void ppm_to_pchg() #endif -/************ ILBM functions ************/ - -static int -length_of_text_chunks ARGS((void)) -{ - int len, n; - - len = 0; - if( anno_chunk ) { - n = strlen(anno_chunk); - len += 4 + 4 + n + PAD(n); /* ID chunksize text */ - } - if( auth_chunk ) { - n = strlen(auth_chunk); - len += 4 + 4 + n + PAD(n); /* ID chunksize text */ - } - if( name_chunk ) { - n = strlen(name_chunk); - len += 4 + 4 + n + PAD(n); /* ID chunksize text */ - } - if( copyr_chunk ) { - n = strlen(copyr_chunk); - len += 4 + 4 + n + PAD(n); /* ID chunksize text */ - } - if( text_chunk ) { - n = strlen(text_chunk); - len += 4 + 4 + n + PAD(n); /* ID chunksize text */ - } - return len; -} - - -static void -write_text_chunks ARGS((void)) -{ - int n; - - if( anno_chunk ) { - n = strlen(anno_chunk); - put_big_long(ID_ANNO); - put_big_long(n); - write_bytes((unsigned char *)anno_chunk, n); - if( ODD(n) ) - put_byte(0); - } - if( auth_chunk ) { - n = strlen(auth_chunk); - put_big_long(ID_AUTH); - put_big_long(n); - write_bytes((unsigned char *)auth_chunk, n); - if( ODD(n) ) - put_byte(0); - } - if( copyr_chunk ) { - n = strlen(copyr_chunk); - put_big_long(ID_copy); - put_big_long(n); - write_bytes((unsigned char *)copyr_chunk, n); - if( ODD(n) ) - put_byte(0); - } - if( name_chunk ) { - n = strlen(name_chunk); - put_big_long(ID_NAME); - put_big_long(n); - write_bytes((unsigned char *)name_chunk, n); - if( ODD(n) ) - put_byte(0); - } - if( text_chunk ) { - n = strlen(text_chunk); - put_big_long(ID_TEXT); - put_big_long(n); - write_bytes((unsigned char *)text_chunk, n); - if( ODD(n) ) - put_byte(0); - } -} - - -static void -write_cmap(colormap, colors, maxval) - pixel *colormap; - int colors, maxval; -{ - int cmapsize, i; - - cmapsize = 3 * colors; - - /* write colormap */ - put_big_long(ID_CMAP); - put_big_long(cmapsize); - if( maxval != MAXCOLVAL ) { - int *table; - pm_message("maxval is not %d - automatically rescaling colors", - MAXCOLVAL); - table = make_val_table(maxval, MAXCOLVAL); - for( i = 0; i < colors; i++ ) { - put_byte(table[PPM_GETR(colormap[i])]); - put_byte(table[PPM_GETG(colormap[i])]); - put_byte(table[PPM_GETB(colormap[i])]); - } - free(table); - } - else { - for( i = 0; i < colors; i++ ) { - put_byte(PPM_GETR(colormap[i])); - put_byte(PPM_GETG(colormap[i])); - put_byte(PPM_GETB(colormap[i])); - } - } - if( ODD(cmapsize) ) - put_byte(0); -} - - -static void -write_bmhd(cols, rows, nPlanes) - int cols, rows, nPlanes; -{ - unsigned char xasp = 10, yasp = 10; - - if( viewportmodes & vmLACE ) - xasp *= 2; - if( viewportmodes & vmHIRES ) - yasp *= 2; - - put_big_long(ID_BMHD); - put_big_long(BitMapHeaderSize); - - put_big_short(cols); - put_big_short(rows); - put_big_short(0); /* x-offset */ - put_big_short(0); /* y-offset */ - put_byte(nPlanes); /* no of planes */ - put_byte(maskmethod); /* masking */ - put_byte(compmethod); /* compression */ - put_byte(BMHD_FLAGS_CMAPOK); /* flags */ - if( maskmethod == mskHasTransparentColor ) - put_big_short(transpIndex); - else - put_big_short(0); - put_byte(xasp); /* x-aspect */ - put_byte(yasp); /* y-aspect */ - put_big_short(cols); /* pageWidth */ - put_big_short(rows); /* pageHeight */ -} - - -/* encode algorithm by Johan Widen (jw@jwdata.se) */ -static const unsigned char bitmask[] = {1, 2, 4, 8, 16, 32, 64, 128}; - -static long -encode_row(outfile, rawrow, cols, nPlanes) - FILE *outfile; /* if non-NULL, write uncompressed row to this file */ - rawtype *rawrow; - int cols, nPlanes; -{ - int plane, bytes; - long retbytes = 0; - - bytes = RowBytes(cols); - - /* Encode and write raw bytes in plane-interleaved form. */ - for( plane = 0; plane < nPlanes; plane++ ) { - register int col, cbit; - register rawtype *rp; - register unsigned char *cp; - int mask; - - mask = 1 << plane; - cbit = -1; - cp = coded_rowbuf-1; - rp = rawrow; - for( col = 0; col < cols; col++, cbit--, rp++ ) { - if( cbit < 0 ) { - cbit = 7; - *++cp = 0; - } - if( *rp & mask ) - *cp |= bitmask[cbit]; - } - if( outfile ) { - write_bytes(coded_rowbuf, bytes); - retbytes += bytes; - } - else - retbytes += compress_row(bytes); - } - return retbytes; -} - - -static long -encode_maskrow(ofp, rawrow, cols) - FILE *ofp; - rawtype *rawrow; - int cols; -{ - int col; - - for( col = 0; col < cols; col++ ) { - if( maskrow[col] == PBM_BLACK ) - rawrow[col] = 1; - else - rawrow[col] = 0; - } - return encode_row(ofp, rawrow, cols, 1); -} - - -static int -compress_row(bytes) - int bytes; -{ - int newbytes; - - switch( compmethod ) { - case cmpByteRun1: - newbytes = runbyte1(bytes); - break; - default: - pm_error("compress_row(): unknown compression method %d", - compmethod); - } - store_bodyrow(compr_rowbuf, newbytes); - - return newbytes; -} - - -static void -store_bodyrow(row, len) - unsigned char *row; - int len; -{ - int idx = cur_block->used; - if( idx >= ROWS_PER_BLOCK ) { - MALLOCVAR_NOFAIL(cur_block->next); - cur_block = cur_block->next; - cur_block->used = idx = 0; - cur_block->next = NULL; - } - MALLOCARRAY_NOFAIL(cur_block->row[idx], len); - cur_block->len[idx] = len; - memcpy(cur_block->row[idx], row, len); - cur_block->used++; -} - - -static void -write_body_rows ARGS((void)) -{ - bodyblock *b; - int i; - long total = 0; - - for( b = &firstblock; b != NULL; b = b->next ) { - for( i = 0; i < b->used; i++ ) { - write_bytes(b->row[i], b->len[i]); - total += b->len[i]; - } - } - if( ODD(total) ) - put_byte(0); -} - - -static void -write_camg ARGS((void)) -{ - put_big_long(ID_CAMG); - put_big_long(CAMGChunkSize); - put_big_long(viewportmodes); -} - - -/************ compression ************/ - - -/* runbyte1 algorithm by Robert A. Knop (rknop@mop.caltech.edu) */ -static int -runbyte1(size) - int size; -{ - int in,out,count,hold; - register unsigned char *inbuf = coded_rowbuf; - register unsigned char *outbuf = compr_rowbuf; - - - in=out=0; - while( in<size ) { - if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) { - /*Begin replicate run*/ - for( count=0, hold=in; - in < size && inbuf[in] == inbuf[hold] && count < 128; - in++, count++) - ; - outbuf[out++]=(unsigned char)(char)(-count+1); - outbuf[out++]=inbuf[hold]; - } - else { /*Do a literal run*/ - hold=out; out++; count=0; - while( ((in>=size-2)&&(in<size)) || - ((in<size-2) && ((inbuf[in]!=inbuf[in+1]) - ||(inbuf[in]!=inbuf[in+2]))) ) { - outbuf[out++]=inbuf[in++]; - if( ++count>=128 ) - break; - } - outbuf[hold]=count-1; - } - } - return(out); -} - - - -/************ other utility functions ************/ - -static void -put_big_short(short s) -{ - if ( pm_writebigshort( stdout, s ) == -1 ) - pm_error( "write error" ); -} - - -static void -put_big_long(l) - long l; -{ - if ( pm_writebiglong( stdout, l ) == -1 ) - pm_error( "write error" ); -} - - -static void -write_bytes(buffer, bytes) - unsigned char *buffer; - int bytes; -{ - if( fwrite(buffer, 1, bytes, stdout) != bytes ) - pm_error("write error"); -} - - -static int * -make_val_table(oldmaxval, newmaxval) - int oldmaxval, newmaxval; -{ - unsigned int i; - int * table; - - MALLOCARRAY_NOFAIL(table, oldmaxval + 1); - for (i = 0; i <= oldmaxval; ++i) - table[i] = ROUNDDIV(i * newmaxval, oldmaxval); - - return table; -} - - - -static int gFormat; -static int gCols; -static int gMaxval; - -static void -init_read(fp, colsP, rowsP, maxvalP, formatP, readall) - FILE *fp; - int *colsP, *rowsP; - pixval *maxvalP; - int *formatP; - int readall; -{ - ppm_readppminit(fp, colsP, rowsP, maxvalP, formatP); - - if( *rowsP >INT16MAX || *colsP >INT16MAX ) - pm_error ("Input image is too large."); - - if( readall ) { - int row; - - pixels = ppm_allocarray(*colsP, *rowsP); - for( row = 0; row < *rowsP; row++ ) - ppm_readppmrow(fp, pixels[row], *colsP, *maxvalP, *formatP); - /* pixels = ppm_readppm(fp, colsP, rowsP, maxvalP); */ - } - else { - pixrow = ppm_allocrow(*colsP); - } - gCols = *colsP; - gMaxval = *maxvalP; - gFormat = *formatP; -} - - -static pixel * -next_pixrow(fp, row) - FILE *fp; - int row; -{ - if( pixels ) - pixrow = pixels[row]; - else { - ppm_readppmrow(fp, pixrow, gCols, gMaxval, gFormat); - } - if( maskrow ) { - int col; - - if( maskfile ) - pbm_readpbmrow(maskfile, maskrow, maskcols, maskformat); - else { - for( col = 0; col < gCols; col++ ) - maskrow[col] = PBM_BLACK; - } - if( transpColor ) { - for( col = 0; col < gCols; col++ ) - if( PPM_EQUAL(pixrow[col], *transpColor) ) - maskrow[col] = PBM_WHITE; - } - } - return pixrow; -} - - int main(int argc, char ** argv) { @@ -1902,7 +1906,7 @@ main(int argc, char ** argv) { pm_keymatch(argv[argn], "-mp", 3) ) { if( ++argn >= argc ) pm_error("-maxplanes requires a value"); - maxplanes = get_int_val(argv[argn], argv[argn-1], 1, MAXPLANES); + maxplanes = getIntVal(argv[argn], argv[argn-1], 1, MAXPLANES); fixplanes = 0; } else @@ -1910,7 +1914,7 @@ main(int argc, char ** argv) { pm_keymatch(argv[argn], "-fp", 3) ) { if( ++argn >= argc ) pm_error("-fixplanes requires a value"); - fixplanes = get_int_val(argv[argn], argv[argn-1], 1, MAXPLANES); + fixplanes = getIntVal(argv[argn], argv[argn-1], 1, MAXPLANES); maxplanes = fixplanes; } else @@ -1923,7 +1927,7 @@ main(int argc, char ** argv) { if( pm_keymatch(argv[argn], "-mmethod", 3) ) { if( ++argn >= argc ) pm_error("-mmethod requires a value"); - maskmethod = get_mask_type(argv[argn]); + maskmethod = getMaskType(argv[argn]); switch( maskmethod ) { case mskNone: case mskHasMask: @@ -1985,7 +1989,8 @@ main(int argc, char ** argv) { if( ++argn >= argc ) pm_error("-camg requires a value"); value = strtol(argv[argn], &tail, 16); - /* TODO: should do some error checking here */ + if(argv[argn] == tail) + pm_error("-camg requires a value"); viewportmodes |= value; gen_camg = 1; } @@ -2003,14 +2008,14 @@ main(int argc, char ** argv) { if( pm_keymatch(argv[argn], "-hamplanes", 5) ) { if( ++argn >= argc ) pm_error("-hamplanes requires a value"); - hamplanes = get_int_val(argv[argn], argv[argn-1], 3, HAMMAXPLANES); + hamplanes = getIntVal(argv[argn], argv[argn-1], 3, HAMMAXPLANES); } else if( pm_keymatch(argv[argn], "-hambits", 5) ) { if( ++argn >= argc ) pm_usage("-hambits requires a value"); hamplanes = - get_int_val(argv[argn], argv[argn-1], 3, HAMMAXPLANES-2) +2; + getIntVal(argv[argn], argv[argn-1], 3, HAMMAXPLANES-2) +2; } else if( pm_keymatch(argv[argn], "-ham6", 5) ) { @@ -2026,7 +2031,7 @@ main(int argc, char ** argv) { if( pm_keymatch(argv[argn], "-hammap", 5) ) { if( ++argn >= argc ) pm_error("-hammap requires a value"); - hammapmode = get_hammap_mode(argv[argn]); + hammapmode = getHammapMode(argv[argn]); } else if( pm_keymatch(argv[argn], "-hamif", 5) ) @@ -2068,7 +2073,7 @@ main(int argc, char ** argv) { if( pm_keymatch(argv[argn], "-deepplanes", 6) ) { if( ++argn >= argc ) pm_error("-deepplanes requires a value"); - deepbits = get_int_val(argv[argn], argv[argn-1], 3, 3*MAXPLANES); + deepbits = getIntVal(argv[argn], argv[argn-1], 3, 3*MAXPLANES); if( deepbits % 3 != 0 ) pm_error("option \"%s\" argument value must be divisible by 3", argv[argn-1]); @@ -2078,7 +2083,7 @@ main(int argc, char ** argv) { if( pm_keymatch(argv[argn], "-deepbits", 6) ) { if( ++argn >= argc ) pm_error("-deepbits requires a value"); - deepbits = get_int_val(argv[argn], argv[argn-1], 1, MAXPLANES); + deepbits = getIntVal(argv[argn], argv[argn-1], 1, MAXPLANES); } else if( pm_keymatch(argv[argn], "-deepif", 6) ) @@ -2117,9 +2122,9 @@ main(int argc, char ** argv) { pm_keymatch(argv[argn], "-dcplanes", 4) ) { if( argc - argn < 4 ) pm_error("-dcbits requires 4 arguments"); - dcol.r = get_int_val(argv[argn+1], argv[argn], 1, MAXPLANES); - dcol.g = get_int_val(argv[argn+2], argv[argn], 1, MAXPLANES); - dcol.b = get_int_val(argv[argn+3], argv[argn], 1, MAXPLANES); + dcol.r = getIntVal(argv[argn+1], argv[argn], 1, MAXPLANES); + dcol.g = getIntVal(argv[argn+2], argv[argn], 1, MAXPLANES); + dcol.b = getIntVal(argv[argn+3], argv[argn], 1, MAXPLANES); argn += 3; } else @@ -2146,7 +2151,7 @@ main(int argc, char ** argv) { if( pm_keymatch(argv[argn], "-cmethod", 4) ) { if( ++argn >= argc ) pm_error("-cmethod requires a value"); - compmethod = get_compr_method(argv[argn]); + compmethod = getComprMethod(argv[argn]); } else if( pm_keymatch(argv[argn], "-floyd", 3) || @@ -2205,22 +2210,22 @@ main(int argc, char ** argv) { switch(forcemode) { case MODE_HAM: if (hammapmode == HAMMODE_RGB4 || hammapmode == HAMMODE_RGB5) - init_read(ifP, &cols, &rows, &maxval, &format, 1); + initRead(ifP, &cols, &rows, &maxval, &format, 1); else - init_read(ifP, &cols, &rows, &maxval, &format, 0); + initRead(ifP, &cols, &rows, &maxval, &format, 0); break; case MODE_DCOL: case MODE_DEEP: mapfile = NULL; - init_read(ifP, &cols, &rows, &maxval, &format, 0); + initRead(ifP, &cols, &rows, &maxval, &format, 0); break; case MODE_RGB8: mapfile = NULL; - init_read(ifP, &cols, &rows, &maxval, &format, 0); + initRead(ifP, &cols, &rows, &maxval, &format, 0); break; case MODE_RGBN: mapfile = NULL; - init_read(ifP, &cols, &rows, &maxval, &format, 0); + initRead(ifP, &cols, &rows, &maxval, &format, 0); break; case MODE_CMAP: /* Figure out the colormap. */ @@ -2234,9 +2239,9 @@ main(int argc, char ** argv) { break; default: if (mapfile) - init_read(ifP, &cols, &rows, &maxval, &format, 0); + initRead(ifP, &cols, &rows, &maxval, &format, 0); else { - init_read(ifP, &cols, &rows, &maxval, &format, 1); + initRead(ifP, &cols, &rows, &maxval, &format, 1); /* read file into memory */ pm_message("computing colormap..."); colormap = @@ -2250,7 +2255,7 @@ main(int argc, char ** argv) { nPlanes = fixplanes; } else { /* too many colors */ mode = ifmode; - report_too_many_colors(ifmode, maxplanes, hamplanes, + reportTooManyColors(ifmode, maxplanes, hamplanes, dcol, deepbits ); } } @@ -2294,37 +2299,40 @@ main(int argc, char ** argv) { for (i = 0; i < RowBytes(cols); ++i) coded_rowbuf[i] = 0; if (DO_COMPRESS) - MALLOCARRAY_NOFAIL(compr_rowbuf, WORSTCOMPR(RowBytes(cols))); + pm_rlenc_allocoutbuf(&compr_rowbuf, RowBytes(cols), PM_RLE_PACKBITS); } switch (mode) { case MODE_HAM: viewportmodes |= vmHAM; - ppm_to_ham(ifP, cols, rows, maxval, - colormap, colors, cmapmaxval, hamplanes); + ppmToHam(ifP, cols, rows, maxval, + colormap, colors, cmapmaxval, hamplanes); break; case MODE_DEEP: - ppm_to_deep(ifP, cols, rows, maxval, deepbits); + ppmToDeep(ifP, cols, rows, maxval, deepbits); break; case MODE_DCOL: - ppm_to_dcol(ifP, cols, rows, maxval, &dcol); + ppmToDcol(ifP, cols, rows, maxval, &dcol); break; case MODE_RGB8: - ppm_to_rgb8(ifP, cols, rows, maxval); + ppmToRgb8(ifP, cols, rows, maxval); break; case MODE_RGBN: - ppm_to_rgbn(ifP, cols, rows, maxval); + ppmToRgbn(ifP, cols, rows, maxval); break; case MODE_CMAP: - ppm_to_cmap(colormap, colors, cmapmaxval); + ppmToCmap(colormap, colors, cmapmaxval); break; default: if (mapfile == NULL) floyd = 0; /* would only slow down conversion */ - ppm_to_std(ifP, cols, rows, maxval, colormap, colors, - cmapmaxval, MAXCOLORS, nPlanes); + ppmToStd(ifP, cols, rows, maxval, colormap, colors, + cmapmaxval, MAXCOLORS, nPlanes); break; } pm_close(ifP); return 0; } + + + diff --git a/converter/ppm/ppmtompeg/BUGS b/converter/ppm/ppmtompeg/BUGS index 64269dfb..9724014e 100644 --- a/converter/ppm/ppmtompeg/BUGS +++ b/converter/ppm/ppmtompeg/BUGS @@ -14,7 +14,7 @@ Known BUGS: REFERENCE_FRAME DECODED does not work -5. Cannot use both STDIN and CDL_FILEs (ok, since it doesnt make sense...) +5. Cannot use both STDIN and CDL_FILEs (ok, since it doesn't make sense...) 6. <fixed> diff --git a/converter/ppm/ppmtompeg/CHANGES b/converter/ppm/ppmtompeg/CHANGES index fffa7a65..efb8fdcf 100644 --- a/converter/ppm/ppmtompeg/CHANGES +++ b/converter/ppm/ppmtompeg/CHANGES @@ -28,7 +28,7 @@ Changes chronology - non-integer frame rates now work for all machines - fixed parsing of -mv_histogram - fixed numPadding bug (file name problem) - - fixed full pixel assertation bug + - fixed full pixel assertion bug - corrected ASPECT_RATIO bug (was forced to 1) - buffer size is now set correctly - complains when file is too small diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile index a1004fdd..eeab9727 100644 --- a/converter/ppm/ppmtompeg/Makefile +++ b/converter/ppm/ppmtompeg/Makefile @@ -31,14 +31,17 @@ endif # 1) long's are 32 bits and # 2) int's are not # -# if you are using a non-ANSI compiler, then use: -# -DNON_ANSI_COMPILER -# # one other option: # -DHEINOUS_DEBUG_MODE # -MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o +MP_BASE_OBJS = \ + mfwddct.o \ + postdct.o \ + huff.o \ + bitio.o \ + mheaders.o \ + MP_ENCODE_OBJS = \ frames.o \ iframe.o \ @@ -46,12 +49,25 @@ MP_ENCODE_OBJS = \ 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 -ifeq ($(OMIT_NETWORK),y) + 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 \ + +ifeq ($(OMIT_NETWORK),Y) MP_OTHER_OBJS += noparallel.o else MP_OTHER_OBJS += parallel.o psocket.o @@ -62,14 +78,19 @@ else MP_OTHER_OBJS += gethostname.o endif -NONMAIN_OBJS = $(MP_BASE_OBJS) $(MP_OTHER_OBJS) $(MP_ENCODE_OBJS) \ - $(JPEG_MODULE).o -OBJECTS = ppmtompeg.o $(NONMAIN_OBJS) -MERGE_OBJECTS = ppmtompeg.o2 $(NONMAIN_OBJS) +ADDL_OBJECTS = \ + $(MP_BASE_OBJS) \ + $(MP_OTHER_OBJS) \ + $(MP_ENCODE_OBJS) \ + $(JPEG_MODULE).o \ + +OBJECTS = ppmtompeg.o $(ADDL_OBJECTS) +MERGE_OBJECTS = ppmtompeg.o2 $(ADDL_OBJECTS) MP_INCLUDE = mproto.h mtypes.h huff.h bitio.h MP_MISC = Makefile huff.table parse_huff.pl -BINARIES = ppmtompeg +PORTBINARIES = ppmtompeg +BINARIES = $(PORTBINARIES) MERGEBINARIES = $(BINARIES) SCRIPTS = @@ -84,18 +105,14 @@ else LIBOPTR = endif -ppmtompeg: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ \ - $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIBX)) \ - $(NETWORKLD) $(MATHLIB) $(LDFLAGS) $(LDLIBS) \ - $(RPATH) $(LADD) - -profile: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ -Bstatic -pg \ - $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIBX)) \ - $(NETWORKLD) $(MATHLIB) $(LDFLAGS) $(LDLIBS) \ - $(RPATH) $(LADD) +ppmtompeg: $(ADDL_OBJECTS) $(LIBOPT) +ppmtompeg: LDFLAGS_TARGET = \ + $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIBX)) $(NETWORKLD) +profile: $(ADDL_OBJECTS) $(LIBOPT) +profile: LDFLAGS_TARGET = \ + -Bstatic -pg \ + $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIBX)) $(NETWORKLD) ######### # OTHER # diff --git a/converter/ppm/ppmtompeg/bframe.c b/converter/ppm/ppmtompeg/bframe.c index 1dbc1846..f5009d6c 100644 --- a/converter/ppm/ppmtompeg/bframe.c +++ b/converter/ppm/ppmtompeg/bframe.c @@ -523,7 +523,7 @@ makeNonSkipBlock(int const y, MpegFrame * const curr, MpegFrame * const prev, MpegFrame * const next, - boolean const specificsOn, + bool const specificsOn, int const mbAddress, int const QScale, const LumBlock * const currentBlockP, diff --git a/converter/ppm/ppmtompeg/bitio.c b/converter/ppm/ppmtompeg/bitio.c index e0dc4d4e..3812bc39 100644 --- a/converter/ppm/ppmtompeg/bitio.c +++ b/converter/ppm/ppmtompeg/bitio.c @@ -244,8 +244,8 @@ Bitio_Write(BitBucket * const bbPtr, assert(nbits <= 32 && nbits >= 0); /* - * Clear top bits if not part of data, necessary due to down and - * dirty calls of Bitio_Write with unecessary top bits set. + * Clear top bits if not part of data, necessary because of down and + * dirty calls of Bitio_Write with unnecessary top bits set. */ bits &= lower_mask[nbits]; diff --git a/converter/ppm/ppmtompeg/bsearch.c b/converter/ppm/ppmtompeg/bsearch.c index 70edfef6..c618bbd4 100644 --- a/converter/ppm/ppmtompeg/bsearch.c +++ b/converter/ppm/ppmtompeg/bsearch.c @@ -43,7 +43,7 @@ * Changed copyrights * * Revision 1.6 1994/12/07 00:40:36 smoot - * Added seperate P and B search ranges + * Added separate P and B search ranges * * Revision 1.5 1994/03/15 00:27:11 keving * nothing @@ -834,7 +834,6 @@ BMotionSearchCross2(const LumBlock * const currentBlockP, interpErrF = FindBestMatch(&forwardBlock, currentBlockP, next, by, bx, &newMotion.bwd, bestErr, searchRangeB); - bestErr = min(bestErr, interpErr); interpErrB = FindBestMatch(&backBlock, currentBlockP, prev, by, bx, &newMotion.fwd, bestErr, searchRangeB); diff --git a/converter/ppm/ppmtompeg/combine.c b/converter/ppm/ppmtompeg/combine.c index 8e0d3281..c00f9c71 100644 --- a/converter/ppm/ppmtompeg/combine.c +++ b/converter/ppm/ppmtompeg/combine.c @@ -104,7 +104,7 @@ appendSpecifiedGopFiles(struct inputSource * const inputSourceP, FILE * ifP; GetNthInputFileName(inputSourceP, fileSeq, &inputFileName); - asprintfN(&fileName, "%s/%s", currentGOPPath, inputFileName); + pm_asprintf(&fileName, "%s/%s", currentGOPPath, inputFileName); for (nAttempts = 0, ifP = NULL; nAttempts < READ_ATTEMPTS && !ifP; @@ -122,8 +122,8 @@ appendSpecifiedGopFiles(struct inputSource * const inputSourceP, } else pm_error("Unable to read file '%s' after %u attempts.", fileName, READ_ATTEMPTS); - strfree(fileName); - strfree(inputFileName); + pm_strfree(fileName); + pm_strfree(inputFileName); } } @@ -140,7 +140,7 @@ appendDefaultGopFiles(const char * const outputFileName, const char * fileName; FILE * ifP; - asprintfN(&fileName, "%s.gop.%u", outputFileName, fileSeq); + pm_asprintf(&fileName, "%s.gop.%u", outputFileName, fileSeq); ifP = fopen(fileName, "rb"); if (ifP == NULL) @@ -151,7 +151,7 @@ appendDefaultGopFiles(const char * const outputFileName, AppendFile(ofP, ifP); } - strfree(fileName); + pm_strfree(fileName); } } diff --git a/converter/ppm/ppmtompeg/docs/template.param b/converter/ppm/ppmtompeg/docs/template.param index 66b6dd98..78ad5300 100644 --- a/converter/ppm/ppmtompeg/docs/template.param +++ b/converter/ppm/ppmtompeg/docs/template.param @@ -18,7 +18,7 @@ # files in the order in which they must appear, followed by 'END_INPUT' # # Also, if you use the `command` method of generating input file names, -# the command will only be executed in the INPUT_DIR if INPUT_DIR preceeds +# the command will only be executed in the INPUT_DIR if INPUT_DIR precedes # the INPUT parameter. # # <option> MUST be in UPPER CASE diff --git a/converter/ppm/ppmtompeg/examples/template.param b/converter/ppm/ppmtompeg/examples/template.param index 66b6dd98..78ad5300 100644 --- a/converter/ppm/ppmtompeg/examples/template.param +++ b/converter/ppm/ppmtompeg/examples/template.param @@ -18,7 +18,7 @@ # files in the order in which they must appear, followed by 'END_INPUT' # # Also, if you use the `command` method of generating input file names, -# the command will only be executed in the INPUT_DIR if INPUT_DIR preceeds +# the command will only be executed in the INPUT_DIR if INPUT_DIR precedes # the INPUT parameter. # # <option> MUST be in UPPER CASE diff --git a/converter/ppm/ppmtompeg/frame.c b/converter/ppm/ppmtompeg/frame.c index 09f46f66..75b209f8 100644 --- a/converter/ppm/ppmtompeg/frame.c +++ b/converter/ppm/ppmtompeg/frame.c @@ -753,7 +753,7 @@ Frame_AllocHalf(MpegFrame * const frameP) { *===========================================================================*/ void Frame_AllocDecoded(MpegFrame * const frameP, - boolean const makeReference) { + bool const makeReference) { if (frameP->decoded_y != NULL) { /* already allocated */ diff --git a/converter/ppm/ppmtompeg/gethostname.c b/converter/ppm/ppmtompeg/gethostname.c index 014b42e8..d20af17c 100644 --- a/converter/ppm/ppmtompeg/gethostname.c +++ b/converter/ppm/ppmtompeg/gethostname.c @@ -1,3 +1,4 @@ +#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _BSD_SOURCE /* Make sure strdup() is in string.h */ #include <string.h> diff --git a/converter/ppm/ppmtompeg/gethostname_win32.c b/converter/ppm/ppmtompeg/gethostname_win32.c index 383f4e55..e37fbb37 100644 --- a/converter/ppm/ppmtompeg/gethostname_win32.c +++ b/converter/ppm/ppmtompeg/gethostname_win32.c @@ -94,7 +94,7 @@ get_string_version(push_string_t *str) return FALSE; } - /* Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. */ + /* Call GetNativeSystemInfo if available; GetSystemInfo otherwise. */ pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); diff --git a/converter/ppm/ppmtompeg/headers/all.h b/converter/ppm/ppmtompeg/headers/all.h index e350aab8..8f095d8e 100644 --- a/converter/ppm/ppmtompeg/headers/all.h +++ b/converter/ppm/ppmtompeg/headers/all.h @@ -33,7 +33,7 @@ * added little_endian force for irizx * * Revision 1.8 1995/02/02 22:02:18 smoot - * added ifdefs for compatability on stranger and stranger architectures... + * added ifdefs for compatibility on stranger and stranger architectures... * * Revision 1.7 1995/02/02 07:26:45 eyhung * added parens to all.h to remove compiler warning @@ -80,7 +80,6 @@ #include <time.h> #endif -#include "ansi.h" #include "general.h" /* some machines have #define index strchr; get rid of this nonsense */ diff --git a/converter/ppm/ppmtompeg/headers/ansi.h b/converter/ppm/ppmtompeg/headers/ansi.h deleted file mode 100644 index b3c3ab17..00000000 --- a/converter/ppm/ppmtompeg/headers/ansi.h +++ /dev/null @@ -1,76 +0,0 @@ -/*===========================================================================* - * ansi.h * - * * - * macro for non-ansi compilers * - * * - *===========================================================================*/ - -/* - * Copyright (c) 1995 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement is - * hereby granted, provided that the above copyright notice and the following - * two paragraphs appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF - * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -/* - * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/ansi.h,v 1.6 1995/08/15 23:43:13 smoot Exp $ - * $Log: ansi.h,v $ - * Revision 1.6 1995/08/15 23:43:13 smoot - * *** empty log message *** - * - * Revision 1.5 1995/01/19 23:54:35 eyhung - * Changed copyrights - * - * Revision 1.4 1994/11/12 02:12:13 keving - * nothing - * - * Revision 1.3 1993/07/22 22:24:23 keving - * nothing - * - * Revision 1.2 1993/07/09 00:17:23 keving - * nothing - * - * Revision 1.1 1993/06/14 22:50:22 keving - * nothing - * - */ - - -#ifndef ANSI_INCLUDED -#define ANSI_INCLUDED - - -/* - * _ANSI_ARGS_ macro stolen from Tcl6.5 by John Ousterhout - */ -#undef _ANSI_ARGS_ -#undef const -#ifdef NON_ANSI_COMPILER -#define _ANSI_ARGS_(x) () -#define CONST -#else -#define _ANSI_ARGS_(x) x -#define CONST const -#ifdef __cplusplus -#define VARARGS (...) -#else -#define VARARGS () -#endif -#endif - - -#endif /* ANSI_INCLUDED */ diff --git a/converter/ppm/ppmtompeg/headers/bitio.h b/converter/ppm/ppmtompeg/headers/bitio.h index a24c21cd..931bcdd9 100644 --- a/converter/ppm/ppmtompeg/headers/bitio.h +++ b/converter/ppm/ppmtompeg/headers/bitio.h @@ -63,7 +63,6 @@ #include <stdio.h> #include "general.h" -#include "ansi.h" /*===========* diff --git a/converter/ppm/ppmtompeg/headers/dct.h b/converter/ppm/ppmtompeg/headers/dct.h index e024b6c1..3b824cf0 100644 --- a/converter/ppm/ppmtompeg/headers/dct.h +++ b/converter/ppm/ppmtompeg/headers/dct.h @@ -31,7 +31,6 @@ #define DCT_INCLUDED -#include "ansi.h" @@ -47,11 +46,12 @@ typedef DCTELEM DCTBLOCK_2D[DCTSIZE][DCTSIZE]; /* * from mfwddct.c: */ -extern void mp_fwd_dct_block2 _ANSI_ARGS_((DCTBLOCK_2D src, DCTBLOCK_2D dest)); +void init_fdct (void); +extern void mp_fwd_dct_block2 (DCTBLOCK_2D src, DCTBLOCK_2D dest); /* jrevdct.c */ -extern void init_pre_idct _ANSI_ARGS_((void )); -extern void mpeg_jrevdct _ANSI_ARGS_((DCTBLOCK data )); +extern void init_pre_idct (void ); +extern void mpeg_jrevdct (DCTBLOCK data ); /* We assume that right shift corresponds to signed division by 2 with diff --git a/converter/ppm/ppmtompeg/headers/frame.h b/converter/ppm/ppmtompeg/headers/frame.h index acd74419..e1f587a2 100644 --- a/converter/ppm/ppmtompeg/headers/frame.h +++ b/converter/ppm/ppmtompeg/headers/frame.h @@ -34,8 +34,7 @@ * HEADER FILES * *==============*/ -#include "general.h" -#include "ansi.h" +#include "netpbm/pm_c_util.h" #include "mtypes.h" /*===========* @@ -54,8 +53,10 @@ typedef struct mpegFrame { int type; char inputFileName[256]; int id; /* the frame number -- starts at 0 */ - boolean inUse; /* TRUE iff this frame is currently being used */ - /* FALSE means any data here can be thrashed */ + bool inUse; + /* this frame is currently being used (if not, any data here can be + thrashed) + */ /* * now, the YCrCb data. All pixel information is stored in unsigned @@ -64,17 +65,17 @@ typedef struct mpegFrame { * * if orig_y is NULL, then orig_cr, orig_cb are undefined */ - uint8 **orig_y, **orig_cr, **orig_cb; + uint8_t **orig_y, **orig_cr, **orig_cb; /* now, the decoded data -- relevant only if * referenceFrame == DECODED_FRAME * * if decoded_y is NULL, then decoded_cr, decoded_cb are undefined */ - uint8 **decoded_y, **decoded_cr, **decoded_cb; + uint8_t **decoded_y, **decoded_cr, **decoded_cb; /* reference data */ - uint8 **ref_y, **ref_cr, **ref_cb; + uint8_t **ref_y, **ref_cr, **ref_cb; /* * these are the Blocks which will ultimately compose MacroBlocks. @@ -86,9 +87,9 @@ typedef struct mpegFrame { /* * this is the half-pixel luminance data (for reference frames) */ - uint8 **halfX, **halfY, **halfBoth; + uint8_t **halfX, **halfY, **halfBoth; - boolean halfComputed; /* TRUE iff half-pixels already computed */ + bool halfComputed; /* TRUE iff half-pixels already computed */ struct mpegFrame *next; /* points to the next B-frame to be encoded, if * stdin is used as the input. @@ -120,7 +121,7 @@ Frame_AllocHalf(MpegFrame * const frameP); void Frame_AllocDecoded(MpegFrame * const frameP, - boolean const makeReference); + bool const makeReference); void Frame_Resize(MpegFrame * const omf, diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h index f2bcf6ae..2ec11d69 100644 --- a/converter/ppm/ppmtompeg/headers/frames.h +++ b/converter/ppm/ppmtompeg/headers/frames.h @@ -13,7 +13,6 @@ *==============*/ #include "pm_config.h" /* For __inline__ */ -#include "ansi.h" #include "mtypes.h" #include "mheaders.h" #include "iframe.h" @@ -255,7 +254,6 @@ extern int gopSize; extern int slicesPerFrame; extern int blocksPerSlice; extern int referenceFrame; -extern boolean specificsOn; extern int quietTime; /* shut up for at least quietTime seconds; * negative means shut up forever */ diff --git a/converter/ppm/ppmtompeg/headers/frametype.h b/converter/ppm/ppmtompeg/headers/frametype.h index 63bee964..33b604e6 100644 --- a/converter/ppm/ppmtompeg/headers/frametype.h +++ b/converter/ppm/ppmtompeg/headers/frametype.h @@ -7,7 +7,7 @@ FType_Type(unsigned int const frameNum); unsigned int FType_FutureRef(unsigned int const currFrameNum); -int FType_PastRef _ANSI_ARGS_((int currFrameNum)); +int FType_PastRef (int currFrameNum); void SetFramePattern(const char * const pattern); diff --git a/converter/ppm/ppmtompeg/headers/general.h b/converter/ppm/ppmtompeg/headers/general.h index f29c9445..59c33c73 100644 --- a/converter/ppm/ppmtompeg/headers/general.h +++ b/converter/ppm/ppmtompeg/headers/general.h @@ -111,15 +111,7 @@ int pclose(); #define NEWLINE '\n' -/*==================* - * TYPE DEFINITIONS * - *==================*/ - -#ifndef HAVE_BOOLEAN typedef int boolean; -#define HAVE_BOOLEAN -/* JPEG library also defines boolean */ -#endif /* In the following, we need the "signed" in order to make these typedefs match those in AIX system header files. Otherwise, compile fails on @@ -167,8 +159,6 @@ typedef signed int int32; #define max(a,b) ((a) > (b) ? (a) : (b)) #undef min #define min(a,b) ((a) < (b) ? (a) : (b)) -#undef abs -#define abs(a) ((a) >= 0 ? (a) : -(a)) #endif diff --git a/converter/ppm/ppmtompeg/headers/huff.h b/converter/ppm/ppmtompeg/headers/huff.h index 47ffb843..a6379248 100644 --- a/converter/ppm/ppmtompeg/headers/huff.h +++ b/converter/ppm/ppmtompeg/headers/huff.h @@ -24,8 +24,11 @@ */ /* - * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + * THIS FILE WAS ORIGINALLY MACHINE GENERATED */ + +#include "general.h" + #define HUFF_MAXRUN 32 #define HUFF_MAXLEVEL 41 diff --git a/converter/ppm/ppmtompeg/headers/jpeg.h b/converter/ppm/ppmtompeg/headers/jpeg.h index 62c6f930..76d73d9e 100644 --- a/converter/ppm/ppmtompeg/headers/jpeg.h +++ b/converter/ppm/ppmtompeg/headers/jpeg.h @@ -1,5 +1,5 @@ -#include "ansi.h" - +#include <stdio.h> +#include "frame.h" void JMovie2JPEG(const char * const infilename, diff --git a/converter/ppm/ppmtompeg/headers/mheaders.h b/converter/ppm/ppmtompeg/headers/mheaders.h index 21d43e3d..edd9552d 100644 --- a/converter/ppm/ppmtompeg/headers/mheaders.h +++ b/converter/ppm/ppmtompeg/headers/mheaders.h @@ -54,7 +54,6 @@ *==============*/ #include "general.h" -#include "ansi.h" #include "bitio.h" @@ -62,7 +61,7 @@ * EXTERNAL PROCEDURE prototypes * *===============================*/ -void SetGOPStartTime _ANSI_ARGS_((int index)); +void SetGOPStartTime (int index); void Mhead_GenSequenceHeader(BitBucket * const bbPtr, @@ -80,21 +79,21 @@ Mhead_GenSequenceHeader(BitBucket * const bbPtr, uint8 * const user_data, int32 const user_data_size); -void Mhead_GenSequenceEnder _ANSI_ARGS_((BitBucket *bbPtr)); -void Mhead_GenGOPHeader _ANSI_ARGS_((BitBucket *bbPtr, +void Mhead_GenSequenceEnder (BitBucket *bbPtr); +void Mhead_GenGOPHeader (BitBucket *bbPtr, int32 drop_frame_flag, int32 tc_hrs, int32 tc_min, int32 tc_sec, int32 tc_pict, int32 closed_gop, int32 broken_link, uint8 *ext_data, int32 ext_data_size, - uint8 *user_data, int32 user_data_size)); -void Mhead_GenPictureHeader _ANSI_ARGS_((BitBucket *bbPtr, int frameType, - int pictCount, int f_code)); -void Mhead_GenSliceHeader _ANSI_ARGS_((BitBucket *bbPtr, uint32 slicenum, + uint8 *user_data, int32 user_data_size); +void Mhead_GenPictureHeader (BitBucket *bbPtr, int frameType, + int pictCount, int f_code); +void Mhead_GenSliceHeader (BitBucket *bbPtr, uint32 slicenum, uint32 qscale, uint8 *extra_info, - uint32 extra_info_size)); -void Mhead_GenSliceEnder _ANSI_ARGS_((BitBucket *bbPtr)); -void Mhead_GenMBHeader _ANSI_ARGS_((BitBucket *bbPtr, + uint32 extra_info_size); +void Mhead_GenSliceEnder (BitBucket *bbPtr); +void Mhead_GenMBHeader (BitBucket *bbPtr, uint32 pict_code_type, uint32 addr_incr, uint32 q_scale, uint32 forw_f_code, uint32 back_f_code, @@ -103,7 +102,7 @@ void Mhead_GenMBHeader _ANSI_ARGS_((BitBucket *bbPtr, int32 motion_forw, int32 m_horiz_forw, int32 m_vert_forw, int32 motion_back, int32 m_horiz_back, int32 m_vert_back, - uint32 mb_pattern, uint32 mb_intra)); + uint32 mb_pattern, uint32 mb_intra); #endif /* MHEADERS_INCLUDED */ diff --git a/converter/ppm/ppmtompeg/headers/motion_search.h b/converter/ppm/ppmtompeg/headers/motion_search.h index 62f3abab..d00509c4 100644 --- a/converter/ppm/ppmtompeg/headers/motion_search.h +++ b/converter/ppm/ppmtompeg/headers/motion_search.h @@ -9,7 +9,6 @@ * HEADER FILES * *==============*/ -#include "ansi.h" /*===========* @@ -140,7 +139,7 @@ extern int psearchAlg; * Changed copyrights * * Revision 1.4 1994/12/07 00:42:01 smoot - * Added seperate P and B search ranges + * Added separate P and B search ranges * * Revision 1.3 1994/11/12 02:12:58 keving * nothing diff --git a/converter/ppm/ppmtompeg/headers/mpeg.h b/converter/ppm/ppmtompeg/headers/mpeg.h index 56862c42..fbfaaf2c 100644 --- a/converter/ppm/ppmtompeg/headers/mpeg.h +++ b/converter/ppm/ppmtompeg/headers/mpeg.h @@ -34,7 +34,6 @@ #include "pm_c_util.h" #include "ppm.h" -#include "ansi.h" #include "mtypes.h" #include "frame.h" @@ -80,7 +79,7 @@ ComputeGOPFrames(int const whichGOP, unsigned int * const lastFrameP, unsigned int const numFrames); -extern void IncrementTCTime _ANSI_ARGS_((void)); +extern void IncrementTCTime (void); void SetReferenceFrameType(const char * const type); boolean @@ -93,7 +92,7 @@ ReadDecodedRefFrame(MpegFrame * const frameP, void SetBitRateFileName(const char * const fileName); -extern void SetFrameRate _ANSI_ARGS_((void)); +extern void SetFrameRate (void); /*==================* diff --git a/converter/ppm/ppmtompeg/headers/mproto.h b/converter/ppm/ppmtompeg/headers/mproto.h index d8fefd84..5b003b2e 100644 --- a/converter/ppm/ppmtompeg/headers/mproto.h +++ b/converter/ppm/ppmtompeg/headers/mproto.h @@ -70,7 +70,6 @@ *==============*/ #include "general.h" -#include "ansi.h" #include "bitio.h" @@ -86,39 +85,39 @@ typedef DCTELEM DCTBLOCK[DCTSIZE2]; /* * from mbasic.c: */ -void mp_reset _ANSI_ARGS_((void)); -void mp_free _ANSI_ARGS_((MpegFrame *mf)); -MpegFrame *mp_new _ANSI_ARGS_((int fnumber, char type, MpegFrame *oldFrame)); -void mp_ycc_calc _ANSI_ARGS_((MpegFrame *mf)); -void mp_dct_blocks _ANSI_ARGS_((MpegFrame *mf)); -void AllocDecoded _ANSI_ARGS_((MpegFrame *frame)); +void mp_reset (void); +void mp_free (MpegFrame *mf); +MpegFrame *mp_new (int fnumber, char type, MpegFrame *oldFrame); +void mp_ycc_calc (MpegFrame *mf); +void mp_dct_blocks (MpegFrame *mf); +void AllocDecoded (MpegFrame *frame); /* * from moutput.c: */ -boolean mp_quant_zig_block _ANSI_ARGS_((Block in, FlatBlock out, int qscale, int iblock)); -void UnQuantZig _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock)); -void mp_rle_huff_block _ANSI_ARGS_((FlatBlock in, BitBucket *out)); -void mp_rle_huff_pblock _ANSI_ARGS_((FlatBlock in, BitBucket *out)); -void mp_create_blocks _ANSI_ARGS_((MpegFrame *mf)); +boolean mp_quant_zig_block (Block in, FlatBlock out, int qscale, int iblock); +void UnQuantZig (FlatBlock in, Block out, int qscale, boolean iblock); +void mp_rle_huff_block (FlatBlock in, BitBucket *out); +void mp_rle_huff_pblock (FlatBlock in, BitBucket *out); +void mp_create_blocks (MpegFrame *mf); -void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width, - int height)); -boolean ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer)); -void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); +void ReadEYUV (MpegFrame * mf, FILE *fpointer, int width, + int height); +boolean ReadPPM (MpegFrame *mf, FILE *fpointer); +void PPMtoYCC (MpegFrame * mf); -void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); -void mp_validate_size _ANSI_ARGS_((int *x, int *y)); -void AllocYCC _ANSI_ARGS_((MpegFrame * mf)); +void ComputeHalfPixelData (MpegFrame *frame); +void mp_validate_size (int *x, int *y); +void AllocYCC (MpegFrame * mf); /* jrevdct.c */ -void init_pre_idct _ANSI_ARGS_((void )); -void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos )); -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 )); +void init_pre_idct (void ); +void j_rev_dct_sparse (DCTBLOCK data , int pos ); +void j_rev_dct (DCTBLOCK data ); +void j_rev_dct_sparse (DCTBLOCK data , int pos ); +void j_rev_dct (DCTBLOCK data ); diff --git a/converter/ppm/ppmtompeg/headers/mtypes.h b/converter/ppm/ppmtompeg/headers/mtypes.h index 0db5a330..a44ce680 100644 --- a/converter/ppm/ppmtompeg/headers/mtypes.h +++ b/converter/ppm/ppmtompeg/headers/mtypes.h @@ -10,12 +10,7 @@ #ifndef MTYPES_INCLUDED #define MTYPES_INCLUDED - -/*==============* - * HEADER FILES * - *==============*/ - -#include "general.h" +#include "netpbm/pm_config.h" #include "dct.h" @@ -48,12 +43,12 @@ typedef struct motion { /* * your basic Block type */ -typedef int16 Block[DCTSIZE][DCTSIZE]; -typedef int16 FlatBlock[DCTSIZE_SQ]; +typedef int16_t Block[DCTSIZE][DCTSIZE]; +typedef int16_t FlatBlock[DCTSIZE_SQ]; typedef struct { - int32 l[2*DCTSIZE][2*DCTSIZE]; + int32_t l[2*DCTSIZE][2*DCTSIZE]; } LumBlock; -typedef int32 ChromBlock[DCTSIZE][DCTSIZE]; +typedef int32_t ChromBlock[DCTSIZE][DCTSIZE]; /*========* * MACROS * diff --git a/converter/ppm/ppmtompeg/headers/opts.h b/converter/ppm/ppmtompeg/headers/opts.h index 5901a677..1756334e 100644 --- a/converter/ppm/ppmtompeg/headers/opts.h +++ b/converter/ppm/ppmtompeg/headers/opts.h @@ -38,7 +38,6 @@ */ #include "general.h" -#include "ansi.h" #include "mtypes.h" /* @@ -110,14 +109,14 @@ extern int LaplaceNum, LaplaceCnum; extern boolean BSkipBlocks; /* Procedures Prototypes */ -int GetIQScale _ANSI_ARGS_((void)); -int GetPQScale _ANSI_ARGS_((void)); -int GetBQScale _ANSI_ARGS_((void)); -void Tune_Init _ANSI_ARGS_((void)); -int CalcRLEHuffLength _ANSI_ARGS_((FlatBlock in)); +int GetIQScale (void); +int GetPQScale (void); +int GetBQScale (void); +void Tune_Init (void); +int CalcRLEHuffLength (FlatBlock in); void ParseTuneParam(const char * const charPtr); -int mse _ANSI_ARGS_((Block blk1, Block blk2)); -void Mpost_UnQuantZigBlockLaplace _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock)); +int mse (Block blk1, Block blk2); +void Mpost_UnQuantZigBlockLaplace (FlatBlock in, Block out, int qscale, boolean iblock); extern void CalcLambdas(void); diff --git a/converter/ppm/ppmtompeg/headers/parallel.h b/converter/ppm/ppmtompeg/headers/parallel.h index 90edd874..0a31fac2 100644 --- a/converter/ppm/ppmtompeg/headers/parallel.h +++ b/converter/ppm/ppmtompeg/headers/parallel.h @@ -30,7 +30,6 @@ * HEADER FILES * *==============*/ -#include "ansi.h" #include "bitio.h" #include "frame.h" diff --git a/converter/ppm/ppmtompeg/headers/param.h b/converter/ppm/ppmtompeg/headers/param.h index c7f57b44..46a544b3 100644 --- a/converter/ppm/ppmtompeg/headers/param.h +++ b/converter/ppm/ppmtompeg/headers/param.h @@ -1,7 +1,6 @@ /* COPYRIGHT information is at end of file */ #include "pm_c_util.h" -#include "ansi.h" #include "input.h" @@ -51,7 +50,7 @@ extern char machineName[MAX_MACHINES][256]; extern char userName[MAX_MACHINES][256]; extern char executable[MAX_MACHINES][1024]; extern char remoteParamFile[MAX_MACHINES][1024]; -extern boolean remote[MAX_MACHINES]; +extern bool remote[MAX_MACHINES]; extern char currentPath[MAXPATHLEN]; extern char currentFramePath[MAXPATHLEN]; extern char currentGOPPath[MAXPATHLEN]; @@ -62,12 +61,21 @@ extern int realWidth, realHeight; extern char ioConversion[1024]; extern char slaveConversion[1024]; extern FILE * bitRateFile; -extern boolean showBitRatePerFrame; -extern boolean computeMVHist; extern const double VidRateNum[9]; -extern boolean keepTempFiles; +extern bool keepTempFiles; +extern int outputWidth, outputHeight; +extern bool specificsOn; +extern char specificsFile[256]; +extern char specificsDefines[1024]; +extern bool GammaCorrection; +extern float GammaValue; +extern char userDataFileName[256]; +/* Defined in ppmtompeg.c; computed from command line */ +extern bool showBitRatePerFrame; +extern bool computeMVHist; + /* * Copyright (c) 1995 The Regents of the University of California. * All rights reserved. diff --git a/converter/ppm/ppmtompeg/headers/prototypes.h b/converter/ppm/ppmtompeg/headers/prototypes.h index b421af35..432062e3 100644 --- a/converter/ppm/ppmtompeg/headers/prototypes.h +++ b/converter/ppm/ppmtompeg/headers/prototypes.h @@ -30,7 +30,6 @@ *==============*/ #include "general.h" -#include "ansi.h" #include "frame.h" @@ -38,34 +37,34 @@ * EXTERNAL PROCEDURE prototypes * *===============================*/ -int GetBQScale _ANSI_ARGS_((void)); -int GetPQScale _ANSI_ARGS_((void)); -void ResetBFrameStats _ANSI_ARGS_((void)); -void ResetPFrameStats _ANSI_ARGS_((void)); +int GetBQScale (void); +int GetPQScale (void); +void ResetBFrameStats (void); +void ResetPFrameStats (void); void SetSearchRange (int const pixelsP, int const pixelsB); void SetPixelSearch(const char * const searchType); -void SetPQScale _ANSI_ARGS_((int qP)); -void SetBQScale _ANSI_ARGS_((int qB)); -float EstimateSecondsPerPFrame _ANSI_ARGS_((void)); -float EstimateSecondsPerBFrame _ANSI_ARGS_((void)); -void SetGOPSize _ANSI_ARGS_((int size)); +void SetPQScale (int qP); +void SetBQScale (int qB); +float EstimateSecondsPerPFrame (void); +float EstimateSecondsPerBFrame (void); +void SetGOPSize (int size); void SetStatFileName(const char * const fileName); -void DCTFrame _ANSI_ARGS_((MpegFrame * mf)); +void DCTFrame (MpegFrame * mf); -void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); +void PPMtoYCC (MpegFrame * mf); -void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); +void MotionSearchPreComputation (MpegFrame *frame); -void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); -void mp_validate_size _ANSI_ARGS_((int *x, int *y)); +void ComputeHalfPixelData (MpegFrame *frame); +void mp_validate_size (int *x, int *y); /* psearch.c */ -void ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer)); -void ShowBBMVHistogram _ANSI_ARGS_((FILE *fpointer)); -void ShowBFMVHistogram _ANSI_ARGS_((FILE *fpointer)); +void ShowPMVHistogram (FILE *fpointer); +void ShowBBMVHistogram (FILE *fpointer); +void ShowBFMVHistogram (FILE *fpointer); diff --git a/converter/ppm/ppmtompeg/headers/rate.h b/converter/ppm/ppmtompeg/headers/rate.h index df5ca1cc..a5f5076f 100644 --- a/converter/ppm/ppmtompeg/headers/rate.h +++ b/converter/ppm/ppmtompeg/headers/rate.h @@ -64,11 +64,11 @@ targetRateControl(MpegFrame * const frameP); * MB_RateOut * * Prints out sampling of MB rate control data. Every "nth" block - * stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE + * stats are printed, with "n" controlled by global RC_MB_SAMPLE_RATE * * RETURNS: nothing *===========================================================================*/ -extern void MB_RateOut _ANSI_ARGS_((int type)); +extern void MB_RateOut (int type); /*===========================================================================* @@ -92,7 +92,7 @@ updateRateControl(int const type); * * RETURNS: new Qscale *===========================================================================*/ -extern int needQScaleChange _ANSI_ARGS_((int oldQScale, Block blk0, Block blk1, Block blk2, Block blk3)); +extern int needQScaleChange (int oldQScale, Block blk0, Block blk1, Block blk2, Block blk3); /*===========================================================================* * @@ -101,7 +101,7 @@ extern int needQScaleChange _ANSI_ARGS_((int oldQScale, Block blk0, Block blk1, * * RETURNS: nothing *===========================================================================*/ -extern void incNumBlocks _ANSI_ARGS_((int num)); +extern void incNumBlocks (int num); /*===========================================================================* @@ -113,7 +113,7 @@ extern void incNumBlocks _ANSI_ARGS_((int num)); * * RETURNS: nothing *===========================================================================*/ -extern void incMacroBlockBits _ANSI_ARGS_((int num)); +extern void incMacroBlockBits (int num); /*===========================================================================* @@ -125,7 +125,7 @@ extern void incMacroBlockBits _ANSI_ARGS_((int num)); * * RETURNS: nothing *===========================================================================*/ -extern void SetRateControl _ANSI_ARGS_((char *charPtr)); +extern void SetRateControl (char *charPtr); /*===========================================================================* @@ -150,7 +150,7 @@ setBufferSize(const char * const charPtr); * * RETURNS: int (or -1 if invalid) *===========================================================================*/ -extern int getBufferSize _ANSI_ARGS_((void)); +extern int getBufferSize (void); /*===========================================================================* @@ -178,7 +178,7 @@ setBitRate(const char * const charPtr); * * RETURNS: int (-1 if Variable mode operation) *===========================================================================*/ -extern int getBitRate _ANSI_ARGS_((void)); +extern int getBitRate (void); /*===========================================================================* @@ -189,7 +189,7 @@ extern int getBitRate _ANSI_ARGS_((void)); * * RETURNS: integer *===========================================================================*/ -extern int getRateMode _ANSI_ARGS_((void)); +extern int getRateMode (void); /*===========================================================================* @@ -200,5 +200,5 @@ extern int getRateMode _ANSI_ARGS_((void)); * * RETURNS: nothing *===========================================================================*/ -extern void incQuantOverride _ANSI_ARGS_((int num)); +extern void incQuantOverride (int num); diff --git a/converter/ppm/ppmtompeg/headers/specifics.h b/converter/ppm/ppmtompeg/headers/specifics.h index 7bcf4ace..4f5c7074 100644 --- a/converter/ppm/ppmtompeg/headers/specifics.h +++ b/converter/ppm/ppmtompeg/headers/specifics.h @@ -1,4 +1,3 @@ -#include "ansi.h" /*===========* @@ -29,8 +28,8 @@ typedef struct fsl_def { } FrameSpecList; -void Specifics_Init _ANSI_ARGS_((void)); -int SpecLookup _ANSI_ARGS_((int fn, int typ, int num, - BlockMV **info, int start_qs)); -int SpecTypeLookup _ANSI_ARGS_((int fn)); +void Specifics_Init (void); +int SpecLookup (int fn, int typ, int num, + BlockMV **info, int start_qs); +int SpecTypeLookup (int fn); diff --git a/converter/ppm/ppmtompeg/huff.c b/converter/ppm/ppmtompeg/huff.c index 821daca1..f2be16ef 100644 --- a/converter/ppm/ppmtompeg/huff.c +++ b/converter/ppm/ppmtompeg/huff.c @@ -24,8 +24,9 @@ */ /* - * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + * THIS FILE WAS ORIGINALLY MACHINE GENERATED */ +#include "general.h" #include "mtypes.h" #include "huff.h" diff --git a/converter/ppm/ppmtompeg/input.c b/converter/ppm/ppmtompeg/input.c index 2b87afa7..4266d39b 100644 --- a/converter/ppm/ppmtompeg/input.c +++ b/converter/ppm/ppmtompeg/input.c @@ -104,17 +104,17 @@ GetNthInputFileName(struct inputSource * const inputSourceP, } if (mapNEntryP->repeat != TRUE) - asprintfN(fileNameP, "%s%s%s", - mapNEntryP->left, &numBuffer[32-numPadding], - mapNEntryP->right); + pm_asprintf(fileNameP, "%s%s%s", + mapNEntryP->left, &numBuffer[32-numPadding], + mapNEntryP->right); else - asprintfN(fileNameP, "%s", mapNEntryP->left); + pm_asprintf(fileNameP, "%s", mapNEntryP->left); } else { if (mapNEntryP->repeat != TRUE) - asprintfN(fileNameP, "%s%d%s", - mapNEntryP->left, index, mapNEntryP->right); + pm_asprintf(fileNameP, "%s%d%s", + mapNEntryP->left, index, mapNEntryP->right); else - asprintfN(fileNameP, "%s", mapNEntryP->left); + pm_asprintf(fileNameP, "%s", mapNEntryP->left); } lastN = n; diff --git a/converter/ppm/ppmtompeg/jpeg.c b/converter/ppm/ppmtompeg/jpeg.c index a703cf39..24c9ae2d 100644 --- a/converter/ppm/ppmtompeg/jpeg.c +++ b/converter/ppm/ppmtompeg/jpeg.c @@ -17,7 +17,6 @@ #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 (ftp://ftp.wizards.dupont.com/pub/ImageMagick/delegates/ljpeg-6b.tar.gz), the name of min_DCT_scaled_size changes to min_codec_data_unit, @@ -26,16 +25,17 @@ #define min_codec_data_unit min_DCT_scaled_size #include <jpeglib.h> #undef min_codec_data_unit -#include "mtypes.h" -#include "frames.h" -#include "prototypes.h" -#include "param.h" -#include "readframe.h" + +#include "netpbm/pm_config.h" +#include "netpbm/pm_c_util.h" +#include "netpbm/mallocvar.h" +#include "netpbm/pm.h" + #include "fsize.h" -#include "rgbtoycc.h" +#include "frame.h" + #include "jpeg.h" -#include "mallocvar.h" /* make it happier.... */ #undef DCTSIZE2 @@ -101,7 +101,7 @@ JMovie2JPEG(const char * const infilename, char ofname[256]; /* output filename string */ int Temp = 0, temp = 0; /* dummy variables */ int image_offset = 0; /* counting variable */ - /* J_Movie header infomation */ + /* J_Movie header information */ int ver_no; /* version number - expected to be 2 */ int fps; /* frame rate - frames per second */ int no_frames; /* total number of frames in jmovie */ @@ -360,7 +360,7 @@ JMovie2JPEG(const char * const infilename, * * allocate and initialize JPEG decompression object * specify data source (eg, a file) - * jpeg_read_header(); // obtain image dimensions and other parameters + * jpeg_read_header(); obtain image dimensions and other parameters * set parameters for decompression * jpeg_start_decompress(); * while (scan lines remain to be read) @@ -385,7 +385,7 @@ ReadJPEG(MpegFrame * const mf, jpeg_component_info *compptr; int buffer_height; int current_row[3]; - uint8 **orig[3]; + uint8_t **orig[3]; int h_samp[3],v_samp[3]; int max_h_samp,max_v_samp; int temp_h, temp_v; @@ -500,7 +500,7 @@ ReadJPEG(MpegFrame * const mf, (void) jpeg_read_raw_data(&cinfo, scanarray, buffer_height); - /* alter subsample ratio's if neccessary */ + /* alter subsample ratio's if necessary */ if ((h_samp[0]==2) && (h_samp[1]==1) && (h_samp[2]==1) && (v_samp[0]==2) && (v_samp[1]==1) && (v_samp[2]==1)) { /* we are 4:1:1 as expected by the encoder*/ diff --git a/converter/ppm/ppmtompeg/jrevdct.c b/converter/ppm/ppmtompeg/jrevdct.c index 2e99a67a..bf9196c4 100644 --- a/converter/ppm/ppmtompeg/jrevdct.c +++ b/converter/ppm/ppmtompeg/jrevdct.c @@ -28,7 +28,6 @@ #include <memory.h> #include "all.h" -#include "ansi.h" #include "dct.h" @@ -162,9 +161,9 @@ ones here or successive P-frames will drift too much with Reference frame coding /* Switch on reverse_dct choices */ -void reference_rev_dct _ANSI_ARGS_((int16 *block)); -void mpeg_jrevdct_quick _ANSI_ARGS_((int16 *block)); -void init_idctref _ANSI_ARGS_((void)); +void reference_rev_dct (int16 *block); +void mpeg_jrevdct_quick (int16 *block); +void init_idctref (void); extern boolean pureDCT; @@ -199,7 +198,7 @@ mpeg_jrevdct_quick(data) dataptr = data; for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { - /* Due to quantization, we will usually find that many of the input + /* Because of quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any row in which all * the AC terms are zero. In that case each output is equal to the diff --git a/converter/ppm/ppmtompeg/mfwddct.c b/converter/ppm/ppmtompeg/mfwddct.c index 4643bf25..75c3a718 100644 --- a/converter/ppm/ppmtompeg/mfwddct.c +++ b/converter/ppm/ppmtompeg/mfwddct.c @@ -122,33 +122,68 @@ #define OSIN_5_16 OCOS_3_16 #define OCOS_5_16 OSIN_3_16 -/* Prototypes */ -void reference_fwd_dct _ANSI_ARGS_((Block block, Block dest)); -void mp_fwd_dct_fast _ANSI_ARGS_((Block data2d, Block dest2d)); -void init_fdct _ANSI_ARGS_((void)); -/* - * -------------------------------------------------------------- - * - * mp_fwd_dct_block2 -- - * - * Select the appropriate mp_fwd_dct routine - * - * Results: None - * - * Side effects: None - * - * -------------------------------------------------------------- - */ -extern boolean pureDCT; -void -mp_fwd_dct_block2(data, dest) - Block data, dest; +static double trans_coef[8][8]; /* transform coefficients */ + + + +static void reference_fwd_dct(block, dest) +Block block, dest; { - if (pureDCT) reference_fwd_dct(data, dest); - else mp_fwd_dct_fast(data, dest); + int i, j, k; + double s; + double tmp[64]; + + if (DoLaplace) { + LaplaceNum++; + } + + for (i=0; i<8; i++) + for (j=0; j<8; j++) + { + s = 0.0; + + for (k=0; k<8; k++) + s += trans_coef[j][k] * block[i][k]; + + tmp[8*i+j] = s; + } + + for (i=0; i<8; i++) + for (j=0; j<8; j++) + { + s = 0.0; + + for (k=0; k<8; k++) + s += trans_coef[i][k] * tmp[8*k+j]; + + if (collect_quant) { + fprintf(collect_quant_fp, "%d %f\n", 8*i+j, s); + } + if (DoLaplace) { + L1[LaplaceCnum][i*8+j] += s*s; + L2[LaplaceCnum][i*8+j] += s; + } + + + dest[i][j] = (int)floor(s+0.499999); + /* + * reason for adding 0.499999 instead of 0.5: + * s is quite often x.5 (at least for i and/or j = 0 or 4) + * and setting the rounding threshold exactly to 0.5 leads to an + * extremely high arithmetic implementation dependency of the result; + * s being between x.5 and x.500001 (which is now incorrectly rounded + * downwards instead of upwards) is assumed to occur less often + * (if at all) + */ + } } + + +static void +mp_fwd_dct_fast(data2d, dest2d) + Block data2d, dest2d; /* * -------------------------------------------------------------- * @@ -166,9 +201,6 @@ mp_fwd_dct_block2(data, dest) * -------------------------------------------------------------- */ -void -mp_fwd_dct_fast(data2d, dest2d) - Block data2d, dest2d; { int16 *data = (int16 *) data2d; /* this algorithm wants * a 1-d array */ @@ -236,10 +268,12 @@ mp_fwd_dct_fast(data2d, dest2d) tmp13 = tmp0 - tmp3; outptr[0] = (int16) UNFIXH((tmp10 + tmp11) * SIN_1_4); - outptr[DCTSIZE * 4] = (int16) UNFIXH((tmp10 - tmp11) * COS_1_4); - - outptr[DCTSIZE * 2] = (int16) UNFIXH(tmp13 * COS_1_8 + tmp12 * SIN_1_8); - outptr[DCTSIZE * 6] = (int16) UNFIXH(tmp13 * SIN_1_8 - tmp12 * COS_1_8); + outptr[DCTSIZE * 4] = + (int16) UNFIXH((tmp10 - tmp11) * COS_1_4); + outptr[DCTSIZE * 2] = + (int16) UNFIXH(tmp13 * COS_1_8 + tmp12 * SIN_1_8); + outptr[DCTSIZE * 6] = + (int16) UNFIXH(tmp13 * SIN_1_8 - tmp12 * COS_1_8); tmp16 = UNFIXO((tmp6 + tmp5) * SIN_1_4); tmp15 = UNFIXO((tmp6 - tmp5) * COS_1_4); @@ -257,10 +291,14 @@ mp_fwd_dct_fast(data2d, dest2d) tmp26 = tmp7 - tmp16; tmp17 = tmp7 + tmp16; - outptr[DCTSIZE] = (int16) UNFIXH(tmp17 * OCOS_1_16 + tmp14 * OSIN_1_16); - outptr[DCTSIZE * 7] = (int16) UNFIXH(tmp17 * OCOS_7_16 - tmp14 * OSIN_7_16); - outptr[DCTSIZE * 5] = (int16) UNFIXH(tmp26 * OCOS_5_16 + tmp25 * OSIN_5_16); - outptr[DCTSIZE * 3] = (int16) UNFIXH(tmp26 * OCOS_3_16 - tmp25 * OSIN_3_16); + outptr[DCTSIZE] = + (int16) UNFIXH(tmp17 * OCOS_1_16 + tmp14 * OSIN_1_16); + outptr[DCTSIZE * 7] = + (int16) UNFIXH(tmp17 * OCOS_7_16 - tmp14 * OSIN_7_16); + outptr[DCTSIZE * 5] = + (int16) UNFIXH(tmp26 * OCOS_5_16 + tmp25 * OSIN_5_16); + outptr[DCTSIZE * 3] = + (int16) UNFIXH(tmp26 * OCOS_3_16 - tmp25 * OSIN_3_16); inptr += DCTSIZE; /* advance inptr to next row */ outptr++; /* advance outptr to next column */ @@ -285,6 +323,28 @@ mp_fwd_dct_fast(data2d, dest2d) } +extern boolean pureDCT; +void +mp_fwd_dct_block2(data, dest) + DCTBLOCK_2D data, dest; +/* + * -------------------------------------------------------------- + * + * mp_fwd_dct_block2 -- + * + * Select the appropriate mp_fwd_dct routine + * + * Results: None + * + * Side effects: None + * + * -------------------------------------------------------------- + */ +{ + if (pureDCT) reference_fwd_dct(data, dest); + else mp_fwd_dct_fast(data, dest); +} + /* Modifies from the MPEG2 verification coder */ /* fdctref.c, forward discrete cosine transform, double precision */ @@ -323,9 +383,6 @@ mp_fwd_dct_fast(data2d, dest2d) #endif #endif -/* private data */ -static double trans_coef[8][8]; /* transform coefficients */ - void init_fdct() { int i, j; @@ -340,54 +397,5 @@ void init_fdct() } } -void reference_fwd_dct(block, dest) -Block block, dest; -{ - int i, j, k; - double s; - double tmp[64]; - - if (DoLaplace) { - LaplaceNum++; - } - - for (i=0; i<8; i++) - for (j=0; j<8; j++) - { - s = 0.0; - - for (k=0; k<8; k++) - s += trans_coef[j][k] * block[i][k]; - tmp[8*i+j] = s; - } - for (i=0; i<8; i++) - for (j=0; j<8; j++) - { - s = 0.0; - - for (k=0; k<8; k++) - s += trans_coef[i][k] * tmp[8*k+j]; - - if (collect_quant) { - fprintf(collect_quant_fp, "%d %f\n", 8*i+j, s); - } - if (DoLaplace) { - L1[LaplaceCnum][i*8+j] += s*s; - L2[LaplaceCnum][i*8+j] += s; - } - - - dest[i][j] = (int)floor(s+0.499999); - /* - * reason for adding 0.499999 instead of 0.5: - * s is quite often x.5 (at least for i and/or j = 0 or 4) - * and setting the rounding threshold exactly to 0.5 leads to an - * extremely high arithmetic implementation dependency of the result; - * s being between x.5 and x.500001 (which is now incorrectly rounded - * downwards instead of upwards) is assumed to occur less often - * (if at all) - */ - } -} diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c index 6557f377..24d337ed 100644 --- a/converter/ppm/ppmtompeg/mpeg.c +++ b/converter/ppm/ppmtompeg/mpeg.c @@ -30,6 +30,7 @@ * HEADER FILES * *==============*/ +#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _BSD_SOURCE /* Make sure strdup() is in string.h */ #include "all.h" @@ -125,9 +126,9 @@ int32 bit_rate, buf_size; * INTERNAL PROCEDURE prototypes * *===============================*/ -static void ComputeDHMSTime _ANSI_ARGS_((int32 someTime, char *timeText)); -static void OpenBitRateFile _ANSI_ARGS_((void)); -static void CloseBitRateFile _ANSI_ARGS_((void)); +static void ComputeDHMSTime (int32 someTime, char *timeText); +static void OpenBitRateFile (void); +static void CloseBitRateFile (void); static void @@ -413,11 +414,11 @@ bitioNew(const char * const outputFileName, else { const char * fileName; - asprintfN(&fileName, "%s.frame.%d", outputFileName, frameNumber); + pm_asprintf(&fileName, "%s.frame.%d", outputFileName, frameNumber); bbP = Bitio_New_Filename(fileName); - strfree(fileName); + pm_strfree(fileName); } return bbP; } @@ -771,12 +772,12 @@ doFirstFrameStuff(enum frameContext const context, time_t now; time(&now); - asprintfN(&userDataString,"MPEG stream encoded by UCB Encoder " - "(mpeg_encode) v%s on %s.", - VERSION, ctime(&now)); + pm_asprintf(&userDataString,"MPEG stream encoded by UCB Encoder " + "(mpeg_encode) v%s on %s.", + VERSION, ctime(&now)); userData = strdup(userDataString); userDataSize = strlen(userData); - strfree(userDataString); + pm_strfree(userDataString); } Mhead_GenSequenceHeader(bbP, Fsize_x, Fsize_y, /* pratio */ aspectRatio, @@ -1322,12 +1323,12 @@ PrintStartStats(time_t const startTime, GetNthInputFileName(inputSourceP, 0, &inputFileName); fprintf(fpointer, "FIRST FILE: %s/%s\n", currentPath, inputFileName); - strfree(inputFileName); + pm_strfree(inputFileName); GetNthInputFileName(inputSourceP, inputSourceP->numInputFiles-1, &inputFileName); fprintf(fpointer, "LAST FILE: %s/%s\n", currentPath, inputFileName); - strfree(inputFileName); + pm_strfree(inputFileName); } fprintf(fpointer, "OUTPUT: %s\n", outputFileName); @@ -1680,7 +1681,7 @@ ReadDecodedRefFrame(MpegFrame * const frameP, } if ((fpointer = fopen(fileName, "rb")) == NULL) { - sleepN(1000); + pm_sleep(1000); if ((fpointer = fopen(fileName, "rb")) == NULL) { fprintf(stderr, "Cannot open %s\n", fileName); exit(1); diff --git a/converter/ppm/ppmtompeg/opts.c b/converter/ppm/ppmtompeg/opts.c index c4d0c0b3..841efdab 100644 --- a/converter/ppm/ppmtompeg/opts.c +++ b/converter/ppm/ppmtompeg/opts.c @@ -40,6 +40,7 @@ #include <stdlib.h> #include <math.h> #include "opts.h" +#include "dct.h" /*==============* * EXTERNALS * @@ -51,8 +52,7 @@ extern int32 qtable[], niqtable[]; extern int ZAG[]; extern boolean printSNR, decodeRefFrames; -void init_idctref _ANSI_ARGS_((void)); -void init_fdct _ANSI_ARGS_((void)); +void init_idctref (void); /*===================* @@ -255,7 +255,7 @@ SetupLocalDCT(const char * const charPtr) * * SetupLaplace * - * Setup encoder to find distrubution for I-frames, and use for -snr + * Setup encoder to find distribution for I-frames, and use for -snr * * RETURNS: nothing * diff --git a/converter/ppm/ppmtompeg/parallel.c b/converter/ppm/ppmtompeg/parallel.c index e13bf221..2835c67c 100644 --- a/converter/ppm/ppmtompeg/parallel.c +++ b/converter/ppm/ppmtompeg/parallel.c @@ -156,7 +156,7 @@ machineDebug(const char format[], ...) { if (debugMachines) { const char * const hostname = GetHostName(); fprintf(stderr, "%s: ---", hostname); - strfree(hostname); + pm_strfree(hostname); vfprintf(stderr, format, args); fputc('\n', stderr); } @@ -175,7 +175,7 @@ errorExit(const char format[], ...) { va_start(args, format); fprintf(stderr, "%s: FATAL ERROR. ", hostname); - strfree(hostname); + pm_strfree(hostname); vfprintf(stderr, format, args); fputc('\n', stderr); @@ -767,13 +767,13 @@ routeFromSocketToDisk(int const otherSock, ReadBytes(otherSock, bigBuffer, numBytes); /* open file to output this stuff to */ - asprintfN(&fileName, "%s.frame.%d", outputFileName, frameNumber); + pm_asprintf(&fileName, "%s.frame.%d", outputFileName, frameNumber); filePtr = fopen(fileName, "wb"); if (filePtr == NULL) errorExit("I/O SERVER: Could not open output file(3): %s", fileName); - strfree(fileName); + pm_strfree(fileName); /* now write the bytes here */ fwrite(bigBuffer, sizeof(char), numBytes, filePtr); @@ -968,7 +968,7 @@ IoServer(struct inputSource * const inputSourceP, -----------------------------------------------------------------------------*/ int ioPortNum; int serverSocket; - boolean done; + bool done; unsigned char *bigBuffer; /* A work buffer that we keep around permanently. We increase its size as needed, but never shrink it. @@ -1104,8 +1104,8 @@ GetRemoteFrame(MpegFrame * const frameP, if (numBytes > sizeof(buffer)) errorExit("Invalid message received: numBytes = %d, " - "which is greater than %d\n", - numBytes, sizeof(numBytes)); + "which is greater than %u", + numBytes, (unsigned)sizeof(numBytes)); ReadBytes(clientSocket, buffer, numBytes); fwrite(buffer, 1, numBytes, filePtr); @@ -1209,7 +1209,7 @@ openInputFile(const char * const fileName, pm_message("ERROR Couldn't read frame file '%s' errno = %d (%s)" "attempt %d", fileName, errno, strerror(errno), attempts); - sleepN(1000); + pm_sleep(1000); } ++attempts; } @@ -1246,11 +1246,11 @@ waitForOutputFile(void * const inputHandle, } machineDebug("COMBINE SERVER: Wait for frame %u over", frameNumber); - asprintfN(&fileName, "%s.frame.%u", outputFileName, frameNumber); + pm_asprintf(&fileName, "%s.frame.%u", outputFileName, frameNumber); openInputFile(fileName, ifPP); - strfree(fileName); + pm_strfree(fileName); } } @@ -1263,11 +1263,11 @@ unlinkFile(void * const inputHandle, if (!keepTempFiles) { const char * fileName; - asprintfN(&fileName, "%s.frame.%u", outputFileName, frameNumber); + pm_asprintf(&fileName, "%s.frame.%u", outputFileName, frameNumber); unlink(fileName); - strfree(fileName); + pm_strfree(fileName); } } @@ -1340,13 +1340,13 @@ startCombineServer(const char * const encoderName, int otherSock; const char * error; - snprintf(command, sizeof(command), - "%s %s -max_machines %d -output_server %s %d %d %s", - encoderName, - debugMachines ? "-debug_machines" : "", - numMachines, masterHostName, masterPortNum, - numInputFiles, paramFileName); - + pm_snprintf(command, sizeof(command), + "%s %s -max_machines %d -output_server %s %d %d %s", + encoderName, + debugMachines ? "-debug_machines" : "", + numMachines, masterHostName, masterPortNum, + numInputFiles, paramFileName); + machineDebug("MASTER: Starting combine server with shell command '%s'", command); @@ -1382,12 +1382,12 @@ startDecodeServer(const char * const encoderName, int otherSock; const char * error; - snprintf(command, sizeof(command), - "%s %s -max_machines %d -decode_server %s %d %d %s", - encoder_name, - debugMachines ? "-debug_machines" : "", - numMachines, masterHostName, masterPortNum, - numInputFiles, paramFileName); + pm_snprintf(command, sizeof(command), + "%s %s -max_machines %d -decode_server %s %d %d %s", + encoder_name, + debugMachines ? "-debug_machines" : "", + numMachines, masterHostName, masterPortNum, + numInputFiles, paramFileName); machineDebug("MASTER: Starting decode server with shell command '%s'", command); @@ -1680,23 +1680,23 @@ startChildren(struct scheduler * const schedulerP, } --childrenLeftCurrentIoServer; } - snprintf(command, sizeof(command), - "%s %s -l %s %s " - "%s %s -child %s %d %d %d %d %d %d " - "-frames %d %d %s", - rsh, - machineName[childNum], userName[childNum], - beNice ? "nice" : "", - executable[childNum], - debugMachines ? "-debug_machines" : "", - masterHostName, masterPortNum, - remote[childNum] ? ioPortNum[numIoServers-1] : 0, - combinePortNum, decodePortNum, childNum, - remote[childNum] ? 1 : 0, - startFrame, startFrame + nFrames - 1, - remote[childNum] ? - remoteParamFile[childNum] : paramFileName - ); + pm_snprintf(command, sizeof(command), + "%s %s -l %s %s " + "%s %s -child %s %d %d %d %d %d %d " + "-frames %d %d %s", + rsh, + machineName[childNum], userName[childNum], + beNice ? "nice" : "", + executable[childNum], + debugMachines ? "-debug_machines" : "", + masterHostName, masterPortNum, + remote[childNum] ? ioPortNum[numIoServers-1] : 0, + combinePortNum, decodePortNum, childNum, + remote[childNum] ? 1 : 0, + startFrame, startFrame + nFrames - 1, + remote[childNum] ? + remoteParamFile[childNum] : paramFileName + ); machineDebug("MASTER: Starting child server " "with shell command '%s'", command); @@ -2070,7 +2070,7 @@ MasterServer(struct inputSource * const inputSourceP, fclose(statFile); free(childState); - strfree(hostName); + pm_strfree(hostName); } diff --git a/converter/ppm/ppmtompeg/param.c b/converter/ppm/ppmtompeg/param.c index a145d33c..45605981 100644 --- a/converter/ppm/ppmtompeg/param.c +++ b/converter/ppm/ppmtompeg/param.c @@ -73,14 +73,14 @@ #define LAST_OPTION 15 /* put any non-required options after LAST_OPTION */ -#define OPTION_RESIZE 16 +#define OPTION_RESIZE 16 #define OPTION_IO_CONVERT 17 #define OPTION_SLAVE_CONVERT 18 -#define OPTION_IQTABLE 19 -#define OPTION_NIQTABLE 20 +#define OPTION_IQTABLE 19 +#define OPTION_NIQTABLE 20 #define OPTION_FRAME_RATE 21 #define OPTION_ASPECT_RATIO 22 -#define OPTION_YUV_SIZE 23 +#define OPTION_YUV_SIZE 23 #define OPTION_SPECIFICS 24 #define OPTION_DEFS_SPECIFICS 25 #define OPTION_BUFFER_SIZE 26 @@ -98,48 +98,49 @@ * GLOBAL VARIABLES * *==================*/ -extern char currentPath[MAXPATHLEN]; -char outputFileName[256]; -int outputWidth, outputHeight; +char outputFileName[256]; +int outputWidth, outputHeight; char inputConversion[1024]; char ioConversion[1024]; char slaveConversion[1024]; char yuvConversion[256]; char specificsFile[256],specificsDefines[1024]=""; -boolean GammaCorrection=FALSE; -float GammaValue; +bool GammaCorrection=FALSE; +float GammaValue; char userDataFileName[256]={0}; -boolean specificsOn = FALSE; +bool specificsOn = FALSE; char currentGOPPath[MAXPATHLEN]; char currentFramePath[MAXPATHLEN]; -boolean keepTempFiles; +bool keepTempFiles; +int numMachines; +char machineName[MAX_MACHINES][256]; +char userName[MAX_MACHINES][256]; +char executable[MAX_MACHINES][1024]; +char remoteParamFile[MAX_MACHINES][1024]; +bool remote[MAX_MACHINES]; +int mult_seq_headers = 0; /* 0 for none, N for header/N GOPs */ + + +extern char currentPath[MAXPATHLEN]; static const char * const optionText[LAST_OPTION+1] = { "GOP_SIZE", "PATTERN", "PIXEL", "PQSCALE", "OUTPUT", "RANGE", "PSEARCH_ALG", "IQSCALE", "INPUT_DIR", "INPUT_CONVERT", "INPUT", "BQSCALE", "BASE_FILE_FORMAT", "SLICES_PER_FRAME", "BSEARCH_ALG", "REFERENCE_FRAME"}; -static boolean optionSeen[NUM_OPTIONS+1]; +static bool optionSeen[NUM_OPTIONS+1]; /* optionSeen[x] means we have seen option x in the parameter file we've been reading. */ -int numMachines; -char machineName[MAX_MACHINES][256]; -char userName[MAX_MACHINES][256]; -char executable[MAX_MACHINES][1024]; -char remoteParamFile[MAX_MACHINES][1024]; -boolean remote[MAX_MACHINES]; -int mult_seq_headers = 0; /* 0 for none, N for header/N GOPs */ - /*===========================================================================* * * SkipSpacesTabs * - * skip all spaces and tabs + * skip all spaces and tabs * - * RETURNS: point to next character not a space or tab + * RETURNS: point to next character not a space or tab * * SIDE EFFECTS: none * @@ -172,13 +173,13 @@ static int GetAspectRatio(const char * const p) { float ratio; - int ttRatio; + int ttRatio; int retval; sscanf(p, "%f", &ratio); ttRatio = (int)(0.5+ratio*10000.0); - if ( ttRatio == 10000 ) retval = 1; + if ( ttRatio == 10000 ) retval = 1; else if ( ttRatio == 6735 ) retval = 2; else if ( ttRatio == 7031 ) retval = 3; else if ( ttRatio == 7615 ) retval = 4; @@ -205,9 +206,9 @@ GetAspectRatio(const char * const p) * * ReadMachineNames * - * read a list of machine names for parallel execution + * read a list of machine names for parallel execution * - * RETURNS: nothing + * RETURNS: nothing * * SIDE EFFECTS: machine info updated * @@ -219,7 +220,7 @@ ReadMachineNames(FILE * const fpointer) const char *charPtr; while ( (fgets(input, 256, fpointer) != NULL) && - (strncmp(input, "END_PARALLEL", 12) != 0) ) { + (strncmp(input, "END_PARALLEL", 12) != 0) ) { if ( input[0] == '#' || input[0] == '\n') { continue; } @@ -229,13 +230,13 @@ ReadMachineNames(FILE * const fpointer) remote[numMachines] = TRUE; sscanf(charPtr, "%s %s %s %s", machineName[numMachines], - userName[numMachines], executable[numMachines], - remoteParamFile[numMachines]); + userName[numMachines], executable[numMachines], + remoteParamFile[numMachines]); } else { remote[numMachines] = FALSE; sscanf(input, "%s %s %s", machineName[numMachines], - userName[numMachines], executable[numMachines]); + userName[numMachines], executable[numMachines]); } numMachines++; @@ -259,13 +260,13 @@ static int GetFrameRate(const char * const p) { float rate; - int thouRate; + int thouRate; int retval; sscanf(p, "%f", &rate); thouRate = (int)(0.5+1000.0*rate); - if ( thouRate == 23976 ) retval = 1; + if ( thouRate == 23976 ) retval = 1; else if ( thouRate == 24000 ) retval = 2; else if ( thouRate == 25000 ) retval = 3; else if ( thouRate == 29970 ) retval = 4; @@ -988,7 +989,7 @@ ReadParamFile(const char * const fileName, paramP); /* May read additional lines from file */ - strfree(input); + pm_strfree(input); } fclose(fpointer); diff --git a/converter/ppm/ppmtompeg/ppmtompeg.c b/converter/ppm/ppmtompeg/ppmtompeg.c index f53ffea9..cd94db39 100644 --- a/converter/ppm/ppmtompeg/ppmtompeg.c +++ b/converter/ppm/ppmtompeg/ppmtompeg.c @@ -30,12 +30,14 @@ * HEADER FILES * *==============*/ +#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _BSD_SOURCE /* Make sure strdup() is in string.h */ #include <assert.h> #include "all.h" #include "mtypes.h" +#include "dct.h" #include "mpeg.h" #include "motion_search.h" #include "prototypes.h" @@ -57,14 +59,15 @@ #include <time.h> -int main _ANSI_ARGS_((int argc, char **argv)); +int main (int argc, char **argv); /*==================* * GLOBAL VARIABLES * *==================*/ -boolean showBitRatePerFrame; +bool showBitRatePerFrame; +bool computeMVHist = FALSE; boolean frameSummary; extern time_t IOtime; @@ -78,9 +81,7 @@ boolean noFrameSummaryOption = FALSE; boolean debugSockets = FALSE; boolean debugMachines = FALSE; boolean bitRateInfoOption = FALSE; -boolean computeMVHist = FALSE; int baseFormat; -extern boolean specificsOn; extern FrameSpecList *fsl; boolean pureDCT=FALSE; char encoder_name[1024]; @@ -91,8 +92,7 @@ const char * hostname; * External PROCEDURE prototypes * *================================*/ -void init_idctref _ANSI_ARGS_((void)); -void init_fdct _ANSI_ARGS_((void)); +void init_idctref (void); struct cmdlineInfo { @@ -335,9 +335,9 @@ announceJob(enum frameContext const context, const char * combineDest; if (context == CONTEXT_JUSTFRAMES) - asprintfN(&outputDest, "to individual frame files"); + pm_asprintf(&outputDest, "to individual frame files"); else - asprintfN(&outputDest, "to file '%s'", outputFileName); + pm_asprintf(&outputDest, "to file '%s'", outputFileName); if (childProcess) combineDest = strdup("for delivery to combine server"); @@ -347,8 +347,8 @@ announceJob(enum frameContext const context, pm_message("%s: ENCODING FRAMES %u-%u to %s %s", hostname, frameStart, frameEnd, outputDest, combineDest); - strfree(combineDest); - strfree(outputDest); + pm_strfree(combineDest); + pm_strfree(outputDest); } } @@ -540,15 +540,15 @@ getUserFrameFile(void * const handle, GetNthInputFileName(inputSourceP, frameNumber, &inputFileName); - asprintfN(&fileName, "%s/%s", currentFramePath, inputFileName); + pm_asprintf(&fileName, "%s/%s", currentFramePath, inputFileName); *ifPP = fopen(fileName, "rb"); if (*ifPP == NULL) pm_error("Unable to open file '%s'. Errno = %d (%s)", fileName, errno, strerror(errno)); - strfree(inputFileName); - strfree(fileName); + pm_strfree(inputFileName); + pm_strfree(fileName); } } @@ -702,7 +702,7 @@ main(int argc, char **argv) { } Frame_Exit(); - strfree(hostname); + pm_strfree(hostname); return 0; } diff --git a/converter/ppm/ppmtompeg/psearch.c b/converter/ppm/ppmtompeg/psearch.c index 83c62d04..3cca1241 100644 --- a/converter/ppm/ppmtompeg/psearch.c +++ b/converter/ppm/ppmtompeg/psearch.c @@ -962,7 +962,7 @@ ShowBFMVHistogram(fpointer) * Changed copyrights * * Revision 1.8 1994/12/07 00:40:36 smoot - * Added seperate P and B search ranges + * Added separate P and B search ranges * * Revision 1.7 1994/11/12 02:09:45 eyhung * full pixel bug diff --git a/converter/ppm/ppmtompeg/psocket.c b/converter/ppm/ppmtompeg/psocket.c index 707f1d84..6a50dc27 100644 --- a/converter/ppm/ppmtompeg/psocket.c +++ b/converter/ppm/ppmtompeg/psocket.c @@ -91,7 +91,7 @@ errorExit(const char format[], ...) { va_start(args, format); fprintf(stderr, "%s: FATAL ERROR. ", hostname); - strfree(hostname); + pm_strfree(hostname); vfprintf(stderr, format, args); fputc('\n', stderr); @@ -272,13 +272,13 @@ ConnectToSocket(const char * const machineName, if ((*hostEnt) == NULL) { (*hostEnt) = gethostbyname(machineName); if ((*hostEnt) == NULL) - asprintfN(errorP, "Couldn't get host by name (%s)", machineName); + pm_asprintf(errorP, "Couldn't get host by name (%s)", machineName); } if (!*errorP) { rc = socket(AF_INET, SOCK_STREAM, 0); if (rc < 0) - asprintfN(errorP, "socket() failed with errno %d (%s)", - errno, strerror(errno)); + pm_asprintf(errorP, "socket() failed with errno %d (%s)", + errno, strerror(errno)); else { int const socketFd = rc; @@ -298,10 +298,10 @@ ConnectToSocket(const char * const machineName, sizeof(struct sockaddr)); if (rc != 0) - asprintfN(errorP, - "connect() to host '%s', port %d failed with " - "errno %d (%s)", - machineName, portNum, errno, strerror(errno)); + pm_asprintf(errorP, + "connect() to host '%s', port %d failed with " + "errno %d (%s)", + machineName, portNum, errno, strerror(errno)); else { *errorP = NULL; *socketFdP = socketFd; @@ -364,14 +364,14 @@ bindToUnusedPort(int const socketFd, foundPort = TRUE; *portNumP = trialPortNum; } else if (!portInUseErrno(errno)) - asprintfN(errorP, "bind() of TCP port number %hu failed " - "with errno %d (%s)", - trialPortNum, errno, strerror(errno)); + pm_asprintf(errorP, "bind() of TCP port number %hu failed " + "with errno %d (%s)", + trialPortNum, errno, strerror(errno)); } if (!*errorP && !foundPort) - asprintfN(errorP, "Unable to find a free port. Every TCP port " - "in the range 2048-16383 is in use"); + pm_asprintf(errorP, "Unable to find a free port. Every TCP port " + "in the range 2048-16383 is in use"); } @@ -392,10 +392,10 @@ CreateListeningSocket(int * const socketP, rc = socket(AF_INET, SOCK_STREAM, 0); if (rc < 0) - asprintfN(errorP, - "Unable to create socket. " - "socket() failed with errno %d (%s)", - errno, strerror(errno)); + pm_asprintf(errorP, + "Unable to create socket. " + "socket() failed with errno %d (%s)", + errno, strerror(errno)); else { int const socketFd = rc; @@ -414,9 +414,9 @@ CreateListeningSocket(int * const socketP, */ rc = listen(socketFd, SOMAXCONN); if (rc != 0) - asprintfN(errorP, "Unable to listen on TCP socket. " - "listen() fails with errno %d (%s)", - errno, strerror(errno)); + pm_asprintf(errorP, "Unable to listen on TCP socket. " + "listen() fails with errno %d (%s)", + errno, strerror(errno)); } if (*errorP) close(socketFd); @@ -443,8 +443,8 @@ AcceptConnection(int const listenSocketFd, rc = accept(listenSocketFd, &otherSocket, &otherSize); if (rc < 0) - asprintfN(errorP, "accept() failed with errno %d (%s). ", - errno, strerror(errno)); + pm_asprintf(errorP, "accept() failed with errno %d (%s). ", + errno, strerror(errno)); else { *connectSocketFdP = rc; *errorP = NULL; diff --git a/converter/ppm/ppmtompeg/rate.c b/converter/ppm/ppmtompeg/rate.c index 1a44cb95..c775e055 100644 --- a/converter/ppm/ppmtompeg/rate.c +++ b/converter/ppm/ppmtompeg/rate.c @@ -204,13 +204,13 @@ extern int framePatternLen; * INTERNAL PROCEDURE prototypes * *===============================*/ -int initGOPRateControl _ANSI_ARGS_((void)); -int determineMBCount _ANSI_ARGS_((void)); -void checkBufferFullness _ANSI_ARGS_((int count)); -void checkSpatialActivity _ANSI_ARGS_((Block blk0, Block blk1, Block blk2, Block blk3)); -void incNumBlocks _ANSI_ARGS_((int num)); -void calculateVBVDelay _ANSI_ARGS_((int num)); -int BlockExperiments _ANSI_ARGS_((int16 *OrigBlock, int16 *NewBlock, int control)); +int initGOPRateControl (void); +int determineMBCount (void); +void checkBufferFullness (int count); +void checkSpatialActivity (Block blk0, Block blk1, Block blk2, Block blk3); +void incNumBlocks (int num); +void calculateVBVDelay (int num); +int BlockExperiments (int16 *OrigBlock, int16 *NewBlock, int control); @@ -236,7 +236,7 @@ analyzePattern(const char * const framePattern, case 'p': ++*gop_pP; break; case 'b': ++*gop_bP; break; default: - asprintfN(errorP, "Bad pattern - not composed of i, p, and b"); + pm_asprintf(errorP, "Bad pattern - not composed of i, p, and b"); } } assert(*gop_xP == *gop_iP + *gop_pP + *gop_bP); @@ -285,7 +285,7 @@ initRateControl(bool const wantUnderflowWarning, if (error) { pm_message("Unable to set up rate control. Switching to variable. " "%s", error); - strfree(error); + pm_strfree(error); RateControlMode = VARIABLE_RATE; return -1; } @@ -595,7 +595,7 @@ updateRateControl(int const type) { * MB_RateOut * * Prints out sampling of MB rate control data. Every "nth" block - * stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE + * stats are printed, with "n" controlled by global RC_MB_SAMPLE_RATE * (NB. "skipped" blocks do not go through this function and thus do not * show up in the sample ) * diff --git a/converter/ppm/ppmtompeg/readframe.c b/converter/ppm/ppmtompeg/readframe.c index d1423c1f..23752706 100644 --- a/converter/ppm/ppmtompeg/readframe.c +++ b/converter/ppm/ppmtompeg/readframe.c @@ -67,9 +67,6 @@ struct YuvLine { * Global VARIABLES * *==================*/ -extern boolean GammaCorrection; -extern float GammaValue; -extern int outputWidth,outputHeight; boolean resizeFrame; const char *CurrFile; @@ -77,19 +74,19 @@ const char *CurrFile; * INTERNAL PROCEDURE prototypes * *===============================*/ -static void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, - int width, int height)); -static void ReadAYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, - int width, int height)); -static void SeparateLine _ANSI_ARGS_((FILE *fpointer, struct YuvLine *lineptr, - int width)); -static void ReadY _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, - int width, int height)); -static void ReadSub4 _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, - int width, int height)); -static void DoGamma _ANSI_ARGS_((MpegFrame *mf, int width, int height)); +static void ReadEYUV (MpegFrame * mf, FILE *fpointer, + int width, int height); +static void ReadAYUV (MpegFrame * mf, FILE *fpointer, + int width, int height); +static void SeparateLine (FILE *fpointer, struct YuvLine *lineptr, + int width); +static void ReadY (MpegFrame * mf, FILE *fpointer, + int width, int height); +static void ReadSub4 (MpegFrame * mf, FILE *fpointer, + int width, int height); +static void DoGamma (MpegFrame *mf, int width, int height); -static void DoKillDim _ANSI_ARGS_((MpegFrame *mf, int w, int h)); +static void DoKillDim (MpegFrame *mf, int w, int h); #define safe_fread(ptr,sz,len,fileptr) \ if ((safe_read_count=fread(ptr,sz,len,fileptr))!=sz*len) { \ @@ -155,7 +152,7 @@ openFile(struct inputSource * const inputSourceP, GetNthInputFileName(inputSourceP, frameNumber, &fileName); - asprintfN(&fullFileName, "%s/%s", currentPath, fileName); + pm_asprintf(&fullFileName, "%s/%s", currentPath, fileName); CurrFile = fullFileName; @@ -207,8 +204,8 @@ openFile(struct inputSource * const inputSourceP, if (baseFormat == JMOVIE_FILE_TYPE) unlink(fullFileName); } - strfree(fullFileName); - strfree(fileName); + pm_strfree(fullFileName); + pm_strfree(fileName); } } @@ -377,10 +374,10 @@ ReadFrame(MpegFrame * const frameP, void SetFileType(const char * const conversion) { - if ( strcmp(conversion, "*") == 0 ) { - fileType = BASE_FILE_TYPE; + if (streq(conversion, "*")) { + fileType = BASE_FILE_TYPE; } else { - fileType = ANY_FILE_TYPE; + fileType = ANY_FILE_TYPE; } } @@ -399,23 +396,23 @@ SetFileType(const char * const conversion) void SetFileFormat(const char * const format) { - if ( strcmp(format, "PPM") == 0 ) { - baseFormat = PNM_FILE_TYPE; - } else if ( strcmp(format, "YUV") == 0 ) { - baseFormat = YUV_FILE_TYPE; - } else if ( strcmp(format, "Y") == 0 ) { - baseFormat = Y_FILE_TYPE; - } else if ( strcmp(format, "PNM") == 0 ) { - baseFormat = PNM_FILE_TYPE; - } else if (( strcmp(format, "JPEG") == 0 ) || ( strcmp(format, "JPG") == 0 )) { - baseFormat = JPEG_FILE_TYPE; - } else if ( strcmp(format, "JMOVIE") == 0 ) { - baseFormat = JMOVIE_FILE_TYPE; - } else if ( strcmp(format, "SUB4") == 0 ) { - baseFormat = SUB4_FILE_TYPE; + if (streq(format, "PPM")) { + baseFormat = PNM_FILE_TYPE; + } else if (streq(format, "YUV")) { + baseFormat = YUV_FILE_TYPE; + } else if (streq(format, "Y")) { + baseFormat = Y_FILE_TYPE; + } else if (streq(format, "PNM")) { + baseFormat = PNM_FILE_TYPE; + } else if (streq(format, "JPEG") || streq(format, "JPG")) { + baseFormat = JPEG_FILE_TYPE; + } else if (streq(format, "JMOVIE")) { + baseFormat = JMOVIE_FILE_TYPE; + } else if (streq(format, "SUB4")) { + baseFormat = SUB4_FILE_TYPE; } else { - fprintf(stderr, "ERROR: Invalid file format: %s\n", format); - exit(1); + fprintf(stderr, "ERROR: Invalid file format: %s\n", format); + exit(1); } } @@ -435,9 +432,9 @@ ReadIOConvert(struct inputSource * const inputSourceP, GetNthInputFileName(inputSourceP, frameNumber, &fileName); - asprintfN(&fullFileName, "%s/%s", currentPath, fileName); + pm_asprintf(&fullFileName, "%s/%s", currentPath, fileName); - if ( strcmp(ioConversion, "*") == 0 ) { + if (streq(ioConversion, "*")) { char buff[1024]; ifp = fopen(fullFileName, "rb"); sprintf(buff,"fopen \"%s\"",fullFileName); @@ -483,8 +480,8 @@ ReadIOConvert(struct inputSource * const inputSourceP, exit(1); } - strfree(fullFileName); - strfree(fileName); + pm_strfree(fullFileName); + pm_strfree(fileName); return ifp; } @@ -828,7 +825,7 @@ MpegFrame *mf; int w,h; { static int GammaVal[256]; - static boolean init_done=FALSE; + static bool init_done=FALSE; int i,j; if (!init_done) { @@ -882,7 +879,7 @@ DoKillDim(mf, w, h) MpegFrame *mf; int w,h; { - static boolean init_done=FALSE; + static bool init_done=FALSE; static unsigned char mapper[256]; register int i,j; double slope, intercept; diff --git a/converter/ppm/ppmtompeg/rgbtoycc.c b/converter/ppm/ppmtompeg/rgbtoycc.c index 766b8902..2dd1899a 100644 --- a/converter/ppm/ppmtompeg/rgbtoycc.c +++ b/converter/ppm/ppmtompeg/rgbtoycc.c @@ -84,11 +84,11 @@ compute_mult_tables(const pixval maxval) { if (mult299 == NULL || mult587 == NULL || mult114 == NULL || mult16874 == NULL || mult33126 == NULL || mult5 == NULL || mult41869 == NULL || mult08131 == NULL) - pm_error("Unable to allocate storage for arithmetic tables.\n" + pm_error("Unable to allocate storage for arithmetic tables. " "We need %d bytes, which is the maxval of the input " - "image, plus 1,\n" + "image, plus 1, " "times the storage size of a floating point value.", - 8 * (table_maxval+1)*sizeof(float)); + (unsigned)(8 * (table_maxval+1)*sizeof(float))); { int index; diff --git a/converter/ppm/ppmtompeg/specifics.c b/converter/ppm/ppmtompeg/specifics.c index 38e8fc43..fb5e3649 100644 --- a/converter/ppm/ppmtompeg/specifics.c +++ b/converter/ppm/ppmtompeg/specifics.c @@ -46,28 +46,26 @@ #include <stdio.h> #include <string.h> #include "prototypes.h" +#include "param.h" /*==================* * GLOBAL VARIABLES * *==================*/ -extern boolean specificsOn; -extern char specificsFile[]; -extern char specificsDefines[]; FrameSpecList *fsl; /*=====================* * Internal procedures * *=====================*/ -void Parse_Specifics_File _ANSI_ARGS_((FILE *fp)); -void Parse_Specifics_File_v1 _ANSI_ARGS_((FILE *fp)); -void Parse_Specifics_File_v2 _ANSI_ARGS_((FILE *fp)); -FrameSpecList *MakeFslEntry _ANSI_ARGS_((void)); -void AddSlc _ANSI_ARGS_((FrameSpecList *c,int snum, int qs)); -Block_Specifics *AddBs _ANSI_ARGS_((FrameSpecList *c,int bnum, - boolean rel, int qs)); -FrameSpecList *MakeFslEntry _ANSI_ARGS_((void)); +void Parse_Specifics_File (FILE *fp); +void Parse_Specifics_File_v1 (FILE *fp); +void Parse_Specifics_File_v2 (FILE *fp); +FrameSpecList *MakeFslEntry (void); +void AddSlc (FrameSpecList *c,int snum, int qs); +Block_Specifics *AddBs (FrameSpecList *c,int bnum, + boolean rel, int qs); +FrameSpecList *MakeFslEntry (void); #define my_upper(c) (((c>='a') && (c<='z')) ? (c-'a'+'A') : c) #define CvtType(x) ReallyCvt(my_upper(x)) #define ReallyCvt(x) (x=='I' ? 1 : (x=='P')?2: ((x=='B')?3:-1)) @@ -91,7 +89,7 @@ version N Specify the version of the specifics file format (this is 1) frame N T M Sets frame number N to type T and Qscale M - (type T is I,B,P,other, other means unspec. I recomend - ) + (type T is I,B,P,other, other means unspec. I recommend - ) slice M Q Sets slice M (in frame N as defined by a previous frame command) to qscale Q @@ -559,7 +557,7 @@ int start_qs; } else { /* if not next, check from the start. (this allows people to put frames out of order,even - though the spec doesnt allow it.) */ + though the spec doesn't allow it.) */ tmp = fsl; found_it = FALSE; while (tmp != (FrameSpecList *) NULL) { diff --git a/converter/ppm/ppmtopcx.c b/converter/ppm/ppmtopcx.c index edc44149..fa68edc5 100644 --- a/converter/ppm/ppmtopcx.c +++ b/converter/ppm/ppmtopcx.c @@ -12,6 +12,10 @@ ** ** 11/Dec/94: first version ** 12/Dec/94: added handling of "packed" format (16 colors or less) +** +** ZSoft PCX File Format Technical Reference Manual +** http://bespin.org/~qz/pc-gpe/pcx.txt +** http://web.archive.org/web/20100206055706/http://www.qzx.com/pc-gpe/pcx.txt */ #include <assert.h> @@ -79,7 +83,7 @@ parseCommandLine(int argc, char ** argv, was passed to us as the argv array. We also trash *argv. -----------------------------------------------------------------------------*/ optEntry *option_def; - /* Instructions to optParseOptions3 on how to parse our options. + /* Instructions to pm_optParseOptions3 on how to parse our options. */ optStruct3 opt; @@ -111,7 +115,7 @@ parseCommandLine(int argc, char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3( &argc, argv, opt, sizeof(opt), 0 ); + pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0 ); /* Uses and sets argc, argv, and some of *cmdline_p and others. */ if (!xposSpec) @@ -158,6 +162,8 @@ parseCommandLine(int argc, char ** argv, pm_error("Program takes at most one argument " "(input file specification). You specified %d", argc-1); + + free(option_def); } @@ -632,6 +638,16 @@ generateStandardPalette(struct pcxCmapEntry ** const pcxcmapP, putPcxColorInHash(cht, pcxColor, colorIndex, maxval); } + /* Set remaining slots in palette to black. The values are not + meaningful, but this suppresses a Valgrind warning about our writing + undefined values to the file and makes our output constant with input. + */ + for ( ; colorIndex < MAXCOLORS; ++colorIndex) { + pcxcmap[colorIndex].r = 0; + pcxcmap[colorIndex].g = 0; + pcxcmap[colorIndex].b = 0; + } + *chtP = cht; *colorsP = stdPaletteSize; } diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c index 1b9f2d5c..36464b6c 100644 --- a/converter/ppm/ppmtopict.c +++ b/converter/ppm/ppmtopict.c @@ -11,464 +11,462 @@ ** implied warranty. */ +#include <assert.h> +#include "pm_c_util.h" +#include "pm.h" #include "ppm.h" -#define HEADER_SIZE 512 +#define HEADER_SIZE 512 -#define RUN_THRESH 3 -#define MAX_RUN 128 /* 0xff = 2, 0xfe = 3, etc */ -#define MAX_COUNT 128 /* 0x00 = 1, 0x01 = 2, etc */ +#define RUN_THRESH 3 +#define MAX_RUN 128 /* 0xff = 2, 0xfe = 3, etc */ +#define MAX_COUNT 128 /* 0x00 = 1, 0x01 = 2, etc */ /* Opcodes */ -#define PICT_NOP 0x00 -#define PICT_clipRgn 0x01 -#define PICT_bkPat 0x02 -#define PICT_txFont 0x03 -#define PICT_txFace 0x04 -#define PICT_txMode 0x05 -#define PICT_spExtra 0x06 -#define PICT_pnSize 0x07 -#define PICT_pnMode 0x08 -#define PICT_pnPat 0x09 -#define PICT_thePat 0x0A -#define PICT_ovSize 0x0B -#define PICT_origin 0x0C -#define PICT_txSize 0x0D -#define PICT_fgColor 0x0E -#define PICT_bkColor 0x0F -#define PICT_txRatio 0x10 -#define PICT_picVersion 0x11 -#define PICT_blPixPat 0x12 -#define PICT_pnPixPat 0x13 -#define PICT_fillPixPat 0x14 -#define PICT_pnLocHFrac 0x15 -#define PICT_chExtra 0x16 -#define PICT_rgbFgCol 0x1A -#define PICT_rgbBkCol 0x1B -#define PICT_hiliteMode 0x1C -#define PICT_hiliteColor 0x1D -#define PICT_defHilite 0x1E -#define PICT_opColor 0x1F -#define PICT_line 0x20 -#define PICT_line_from 0x21 -#define PICT_short_line 0x22 -#define PICT_short_line_from 0x23 -#define PICT_long_text 0x28 -#define PICT_DH_text 0x29 -#define PICT_DV_text 0x2A -#define PICT_DHDV_text 0x2B -#define PICT_frameRect 0x30 -#define PICT_paintRect 0x31 -#define PICT_eraseRect 0x32 -#define PICT_invertRect 0x33 -#define PICT_fillRect 0x34 -#define PICT_frameSameRect 0x38 -#define PICT_paintSameRect 0x39 -#define PICT_eraseSameRect 0x3A -#define PICT_invertSameRect 0x3B -#define PICT_fillSameRect 0x3C -#define PICT_frameRRect 0x40 -#define PICT_paintRRect 0x41 -#define PICT_eraseRRect 0x42 -#define PICT_invertRRect 0x43 -#define PICT_fillRRect 0x44 -#define PICT_frameSameRRect 0x48 -#define PICT_paintSameRRect 0x49 -#define PICT_eraseSameRRect 0x4A -#define PICT_invertSameRRect 0x4B -#define PICT_fillSameRRect 0x4C -#define PICT_frameOval 0x50 -#define PICT_paintOval 0x51 -#define PICT_eraseOval 0x52 -#define PICT_invertOval 0x53 -#define PICT_fillOval 0x54 -#define PICT_frameSameOval 0x58 -#define PICT_paintSameOval 0x59 -#define PICT_eraseSameOval 0x5A -#define PICT_invertSameOval 0x5B -#define PICT_fillSameOval 0x5C -#define PICT_frameArc 0x60 -#define PICT_paintArc 0x61 -#define PICT_eraseArc 0x62 -#define PICT_invertArc 0x63 -#define PICT_fillArc 0x64 -#define PICT_frameSameArc 0x68 -#define PICT_paintSameArc 0x69 -#define PICT_eraseSameArc 0x6A -#define PICT_invertSameArc 0x6B -#define PICT_fillSameArc 0x6C -#define PICT_framePoly 0x70 -#define PICT_paintPoly 0x71 -#define PICT_erasePoly 0x72 -#define PICT_invertPoly 0x73 -#define PICT_fillPoly 0x74 -#define PICT_frameSamePoly 0x78 -#define PICT_paintSamePoly 0x79 -#define PICT_eraseSamePoly 0x7A -#define PICT_invertSamePoly 0x7B -#define PICT_fillSamePoly 0x7C -#define PICT_frameRgn 0x80 -#define PICT_paintRgn 0x81 -#define PICT_eraseRgn 0x82 -#define PICT_invertRgn 0x83 -#define PICT_fillRgn 0x84 -#define PICT_frameSameRgn 0x88 -#define PICT_paintSameRgn 0x89 -#define PICT_eraseSameRgn 0x8A -#define PICT_invertSameRgn 0x8B -#define PICT_fillSameRgn 0x8C -#define PICT_BitsRect 0x90 -#define PICT_BitsRgn 0x91 -#define PICT_PackBitsRect 0x98 -#define PICT_PackBitsRgn 0x99 -#define PICT_shortComment 0xA0 -#define PICT_longComment 0xA1 -#define PICT_EndOfPicture 0xFF -#define PICT_headerOp 0x0C00 - -static void putFill ARGS(( FILE *fd, int n )); -static void putShort ARGS(( FILE *fd, int i )); -static void putLong ARGS(( FILE *fd, long i )); -static void putFixed ARGS(( FILE *fd, int in, int frac )); -static void putRect ARGS(( FILE *fd, int x1, int x2, int y1, int y2 )); -static int putRow ARGS(( FILE *fd, int row, int cols, pixel *rowpixels, char *packed )); +#define PICT_NOP 0x00 +#define PICT_clipRgn 0x01 +#define PICT_bkPat 0x02 +#define PICT_txFont 0x03 +#define PICT_txFace 0x04 +#define PICT_txMode 0x05 +#define PICT_spExtra 0x06 +#define PICT_pnSize 0x07 +#define PICT_pnMode 0x08 +#define PICT_pnPat 0x09 +#define PICT_thePat 0x0A +#define PICT_ovSize 0x0B +#define PICT_origin 0x0C +#define PICT_txSize 0x0D +#define PICT_fgColor 0x0E +#define PICT_bkColor 0x0F +#define PICT_txRatio 0x10 +#define PICT_picVersion 0x11 +#define PICT_blPixPat 0x12 +#define PICT_pnPixPat 0x13 +#define PICT_fillPixPat 0x14 +#define PICT_pnLocHFrac 0x15 +#define PICT_chExtra 0x16 +#define PICT_rgbFgCol 0x1A +#define PICT_rgbBkCol 0x1B +#define PICT_hiliteMode 0x1C +#define PICT_hiliteColor 0x1D +#define PICT_defHilite 0x1E +#define PICT_opColor 0x1F +#define PICT_line 0x20 +#define PICT_line_from 0x21 +#define PICT_short_line 0x22 +#define PICT_short_line_from 0x23 +#define PICT_long_text 0x28 +#define PICT_DH_text 0x29 +#define PICT_DV_text 0x2A +#define PICT_DHDV_text 0x2B +#define PICT_frameRect 0x30 +#define PICT_paintRect 0x31 +#define PICT_eraseRect 0x32 +#define PICT_invertRect 0x33 +#define PICT_fillRect 0x34 +#define PICT_frameSameRect 0x38 +#define PICT_paintSameRect 0x39 +#define PICT_eraseSameRect 0x3A +#define PICT_invertSameRect 0x3B +#define PICT_fillSameRect 0x3C +#define PICT_frameRRect 0x40 +#define PICT_paintRRect 0x41 +#define PICT_eraseRRect 0x42 +#define PICT_invertRRect 0x43 +#define PICT_fillRRect 0x44 +#define PICT_frameSameRRect 0x48 +#define PICT_paintSameRRect 0x49 +#define PICT_eraseSameRRect 0x4A +#define PICT_invertSameRRect 0x4B +#define PICT_fillSameRRect 0x4C +#define PICT_frameOval 0x50 +#define PICT_paintOval 0x51 +#define PICT_eraseOval 0x52 +#define PICT_invertOval 0x53 +#define PICT_fillOval 0x54 +#define PICT_frameSameOval 0x58 +#define PICT_paintSameOval 0x59 +#define PICT_eraseSameOval 0x5A +#define PICT_invertSameOval 0x5B +#define PICT_fillSameOval 0x5C +#define PICT_frameArc 0x60 +#define PICT_paintArc 0x61 +#define PICT_eraseArc 0x62 +#define PICT_invertArc 0x63 +#define PICT_fillArc 0x64 +#define PICT_frameSameArc 0x68 +#define PICT_paintSameArc 0x69 +#define PICT_eraseSameArc 0x6A +#define PICT_invertSameArc 0x6B +#define PICT_fillSameArc 0x6C +#define PICT_framePoly 0x70 +#define PICT_paintPoly 0x71 +#define PICT_erasePoly 0x72 +#define PICT_invertPoly 0x73 +#define PICT_fillPoly 0x74 +#define PICT_frameSamePoly 0x78 +#define PICT_paintSamePoly 0x79 +#define PICT_eraseSamePoly 0x7A +#define PICT_invertSamePoly 0x7B +#define PICT_fillSamePoly 0x7C +#define PICT_frameRgn 0x80 +#define PICT_paintRgn 0x81 +#define PICT_eraseRgn 0x82 +#define PICT_invertRgn 0x83 +#define PICT_fillRgn 0x84 +#define PICT_frameSameRgn 0x88 +#define PICT_paintSameRgn 0x89 +#define PICT_eraseSameRgn 0x8A +#define PICT_invertSameRgn 0x8B +#define PICT_fillSameRgn 0x8C +#define PICT_BitsRect 0x90 +#define PICT_BitsRgn 0x91 +#define PICT_PackBitsRect 0x98 +#define PICT_PackBitsRgn 0x99 +#define PICT_shortComment 0xA0 +#define PICT_longComment 0xA1 +#define PICT_EndOfPicture 0xFF +#define PICT_headerOp 0x0C00 #define MAXCOLORS 256 static colorhash_table cht; -int -main(argc, argv) -int argc; -char *argv[]; -{ - FILE *ifp; - int argn, rows, cols, colors, i, row, oc; - register pixel **pixels; - char *packed; - pixval maxval; - long lmaxval, rval, gval, bval; - colorhist_vector chv; - - - ppm_init( &argc, argv ); - - argn = 1; - if (argn < argc) - { - ifp = pm_openr(argv[1]); - argn++; - } - else - ifp = stdin; - if (argn != argc) - pm_usage("[ppmfile]"); - - pixels = ppm_readppm(ifp, &cols, &rows, &maxval); - if (cols < 8) - pm_error("ppm input too narrow, must be >= 8 pixels wide" ); - lmaxval = (long)maxval; - pm_close(ifp); - - /* Figure out the colormap. */ - pm_message("computing colormap..." ); - chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors); - if (chv == (colorhist_vector) 0) - pm_error("too many colors - try doing a 'pnmquant %d'", MAXCOLORS); - pm_message("%d colors found", colors ); - - /* Make a hash table for fast color lookup. */ - cht = ppm_colorhisttocolorhash(chv, colors); - - /* write the header */ - putFill(stdout, HEADER_SIZE); - - /* write picSize and picFrame */ - putShort(stdout, 0); - putRect(stdout, 0, 0, rows, cols); - - /* write version op and version */ - putShort(stdout, PICT_picVersion); - putShort(stdout, 0x02FF); - putShort(stdout, PICT_headerOp); - putLong(stdout, -1L); - putFixed(stdout, 0, 0); - putFixed(stdout, 0, 0); - putFixed(stdout, cols, 0); - putFixed(stdout, rows, 0); - putFill(stdout, 4); - - /* seems to be needed by many PICT2 programs */ - putShort(stdout, PICT_clipRgn); - putShort(stdout, 10); - putRect(stdout, 0, 0, rows, cols); - - /* write picture */ - putShort(stdout, PICT_PackBitsRect); - putShort(stdout, cols | 0x8000); - putRect(stdout, 0, 0, rows, cols); - putShort(stdout, 0); /* pmVersion */ - putShort(stdout, 0); /* packType */ - putLong(stdout, 0L); /* packSize */ - putFixed(stdout, 72, 0); /* hRes */ - putFixed(stdout, 72, 0); /* vRes */ - putShort(stdout, 0); /* pixelType */ - putShort(stdout, 8); /* pixelSize */ - putShort(stdout, 1); /* cmpCount */ - putShort(stdout, 8); /* cmpSize */ - putLong(stdout, 0L); /* planeBytes */ - putLong(stdout, 0L); /* pmTable */ - putLong(stdout, 0L); /* pmReserved */ - putLong(stdout, 0L); /* ctSeed */ - putShort(stdout, 0); /* ctFlags */ - putShort(stdout, colors-1); /* ctSize */ - - /* Write out the colormap. */ - for (i = 0; i < colors; i++) - { - putShort(stdout, i); - rval = PPM_GETR(chv[i].color); - gval = PPM_GETG(chv[i].color); - bval = PPM_GETB(chv[i].color); - if (lmaxval != 65535L) - { - rval = rval * 65535L / lmaxval; - gval = gval * 65535L / lmaxval; - bval = bval * 65535L / lmaxval; - } - putShort(stdout, (short)rval); - putShort(stdout, (short)gval); - putShort(stdout, (short)bval); - } - - putRect(stdout, 0, 0, rows, cols); /* srcRect */ - putRect(stdout, 0, 0, rows, cols); /* dstRect */ - putShort(stdout, 0); /* mode */ - - /* Finally, write out the data. */ - packed = (char*) malloc((unsigned)(cols+cols/MAX_COUNT+1)); - oc = 0; - for (row = 0; row < rows; row++) - oc += putRow(stdout, row, cols, pixels[row], packed); - - /* if we wrote an odd number of pixdata bytes, pad */ - if (oc & 1) - (void) putc(0, stdout); - putShort(stdout, PICT_EndOfPicture); - - lmaxval = ftell(stdout) - HEADER_SIZE; - if (fseek(stdout, (long)HEADER_SIZE, 0) >= 0) - putShort(stdout, (short)(lmaxval & 0xffff)); - - exit(0); -} + static void -putFill(fd, n) -FILE *fd; -int n; -{ - register int i; - - for (i = 0; i < n; i++) - (void) putc(0, fd); +putFill(FILE * const ifP, + unsigned int const n) { + + unsigned int i; + + for (i = 0; i < n; ++i) + putc(0, ifP); } + + static void -putShort(fd, i) -FILE *fd; -int i; -{ - (void) putc((i >> 8) & 0xff, fd); - (void) putc(i & 0xff, fd); +putShort(FILE * const ifP, + int const i) { + putc((i >> 8) & 0xff, ifP); + putc(i & 0xff, ifP); } + + static void -putLong( FILE *fd, long i ) -{ - (void) putc((int)((i >> 24) & 0xff), fd); - (void) putc(((int)(i >> 16) & 0xff), fd); - (void) putc(((int)(i >> 8) & 0xff), fd); - (void) putc((int)(i & 0xff), fd); +putLong(FILE * const ifP, + long const i) { + putc((int)((i >> 24) & 0xff), ifP); + putc(((int)(i >> 16) & 0xff), ifP); + putc(((int)(i >> 8) & 0xff), ifP); + putc((int)(i & 0xff), ifP); } + + static void -putFixed(fd, in, frac) -FILE *fd; -int in, frac; -{ - putShort(fd, in); - putShort(fd, frac); +putFixed(FILE * const ifP, + int const in, + int const frac) { + putShort(ifP, in); + putShort(ifP, frac); } + + static void -putRect(fd, x1, x2, y1, y2) -FILE *fd; -int x1, x2, y1, y2; -{ - putShort(fd, x1); - putShort(fd, x2); - putShort(fd, y1); - putShort(fd, y2); +putRect(FILE * const ifP, + int const x1, + int const x2, + int const y1, + int const y2) { + putShort(ifP, x1); + putShort(ifP, x2); + putShort(ifP, y1); + putShort(ifP, y2); } -#define RUNLENGTH -#ifdef RUNLENGTH - -#define runtochar(c) (257-(c)) -#define counttochar(c) ((c)-1) - -static int -putRow(fd, row, cols, rowpixels, packed) -FILE *fd; -int row, cols; -pixel *rowpixels; -char *packed; -{ - register int i; - int packcols, count, run, rep, oc; - register pixel *pP; - pixel lastp; - register char *p; - - run = count = 0; - for (cols--, i = cols, pP = rowpixels + cols, p = packed, lastp = *pP; - i >= 0; i--, lastp = *pP, pP--) - { - if (PPM_EQUAL(lastp, *pP)) - run++; - else if (run < RUN_THRESH) - { - while (run > 0) - { - *p++ = ppm_lookupcolor(cht, &lastp); - run--; - count++; - if (count == MAX_COUNT) - { - *p++ = counttochar(MAX_COUNT); - count -= MAX_COUNT; - } - } - run = 1; - } - else - { - if (count > 0) - *p++ = counttochar(count); - count = 0; - while (run > 0) - { - rep = run > MAX_RUN ? MAX_RUN : run; - *p++ = ppm_lookupcolor(cht, &lastp); - *p++ = runtochar(rep); - run -= rep; - } - run = 1; - } - } - if (run < RUN_THRESH) - { - while (run > 0) - { - *p++ = ppm_lookupcolor(cht, &lastp); - run--; - count++; - if (count == MAX_COUNT) - { - *p++ = counttochar(MAX_COUNT); - count -= MAX_COUNT; - } - } - } - else - { - if (count > 0) - *p++ = counttochar(count); - count = 0; - while (run > 0) - { - rep = run > MAX_RUN ? MAX_RUN : run; - *p++ = ppm_lookupcolor(cht, &lastp); - *p++ = runtochar(rep); - run -= rep; - } - run = 1; - } - if (count > 0) - *p++ = counttochar(count); - - packcols = p - packed; /* how many did we write? */ - if (cols > 200) - { - putShort(fd, packcols); - oc = packcols + 2; - } - else - { - (void) putc(packcols, fd); - oc = packcols + 1; - } - - /* now write out the packed row */ - while(p != packed) - { - --p; - (void) putc(*p, fd); - } - - return (oc); + + +#define runtochar(c) (257-(c)) +#define counttochar(c) ((c)-1) + +static void +putRow(FILE * const ofP, + unsigned int const row, + unsigned int const cols, + pixel * const rowpixels, + char * const outBuf, + unsigned int * const outCountP) { +/*---------------------------------------------------------------------------- + Write the row rowpixels[], which is 'cols' pixels wide and is row 'row' of + the image, to file *ofP in PICT format. + + Return as *outCountP the number of bytes we write to *ofP. + + Use buffer 'outBuf'. +-----------------------------------------------------------------------------*/ + unsigned int i; + unsigned int count; + unsigned int run; + unsigned int rep; + unsigned int outCount; + pixel lastpix; + char * p; + + run = 0; + count = 0; + lastpix = rowpixels[cols-1]; + + for (i = 0, p = &outBuf[0]; i < cols; ++i) { + + pixel const pix = rowpixels[cols - 1 - i]; + + if (PPM_EQUAL(lastpix, pix)) + ++run; + else if (run < RUN_THRESH) { + while (run > 0) { + *p++ = ppm_lookupcolor(cht, &lastpix); + --run; + ++count; + if (count == MAX_COUNT) { + *p++ = counttochar(MAX_COUNT); + count -= MAX_COUNT; + } + } + run = 1; + } else { + if (count > 0) + *p++ = counttochar(count); + count = 0; + while (run > 0) { + rep = MIN(run, MAX_RUN); + *p++ = ppm_lookupcolor(cht, &lastpix); + *p++ = runtochar(rep); + assert(run >= rep); + run -= rep; + } + run = 1; + } + lastpix = pix; + } + if (run < RUN_THRESH) { + while (run > 0) { + *p++ = ppm_lookupcolor(cht, &lastpix); + --run; + ++count; + if (count == MAX_COUNT) { + *p++ = counttochar(MAX_COUNT); + count -= MAX_COUNT; + } + } + } else { + if (count > 0) + *p++ = counttochar(count); + count = 0; + while (run > 0) { + rep = MIN(run, MAX_RUN); + *p++ = ppm_lookupcolor(cht, &lastpix); + *p++ = runtochar(rep); + assert(run >= rep); + run -= rep; + } + run = 1; + } + if (count > 0) + *p++ = counttochar(count); + + { + unsigned int const packcols = p - outBuf; + /* How many we wrote */ + if (cols-1 > 200) { + putShort(ofP, packcols); + outCount = packcols + 2; + } else { + putc(packcols, ofP); + outCount = packcols + 1; + } + } + /* now write out the packed row */ + while (p != outBuf) { + --p; + putc(*p, ofP); + } + *outCountP = outCount; } -#else /* RUNLENGTH */ + + +# if 0 /* real dumb putRow with no compression */ -static int -putRow(fd, row, cols, rowpixels, packed) -FILE *fd; -int row, cols; -pixel *rowpixels; -char *packed; -{ - register int i, j, bc, oc; - register pixel *pP; - -#if notdef - bzero(aux, cols); /* aux?? */ -#endif /*notdef*/ - bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT; - if (bc > 200) - { - putShort(fd, bc); - oc = bc + 2; - } - else - { - (void) putc(bc, fd); - oc = bc + 1; - } - for (i = 0, pP = rowpixels; i < cols;) - { - if (cols - i > MAX_COUNT) - { - (void) putc(MAX_COUNT - 1, fd); - for (j = 0; j < MAX_COUNT; j++) - { - (void) putc(ppm_lookupcolor(cht, pP), fd); - pP++; - } - i += MAX_COUNT; - } - else - { - (void) putc(cols - i - 1, fd); - for (j = 0; j < cols - i; j++) - { - (void) putc(ppm_lookupcolor(cht, pP), fd); - pP++; - } - i = cols; - } - } - return (oc); +static void +putRow(FILE * const ifP, + unsigned int const row, + unsigned int const cols, + pixel * const rowpixels, + char * const outBuf, + unsigned int * const outCountP) { + + unsigned int const bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT; + + unsigned int i; + + if (bc > 200) { + putShort(ifP, bc); + *outCountP = bc + 2; + } else { + putc(bc, ifP); + *outCountP = bc + 1; + } + for (col = 0; col < cols;) { + if (cols - col > MAX_COUNT) { + unsigned int j; + putc(MAX_COUNT - 1, ifP); + for (j = 0; j < MAX_COUNT; ++j) { + putc(ppm_lookupcolor(cht, &rowPixels[col]), ifP); + ++col + } + col += MAX_COUNT; + } else { + unsigned int j; + putc(cols - col - 1, ifP); + for (j = 0; j < cols - col; ++j) { + putc(ppm_lookupcolor(cht, &rowPixels[col]), ifP); + ++pP; + } + col = cols; + } + } +} +#endif /* 0 */ + + + +int +main(int argc, const char ** argv) { + + FILE * ifP; + int nColors; + unsigned int oc; + unsigned int i; + int rows, cols; + unsigned int row; + pixel ** pixels; + char * outBuf; + pixval maxval; + long lmaxval, rval, gval, bval; + colorhist_vector chv; + + pm_proginit(&argc, argv); + + if (argc-1 > 0) + ifP = pm_openr(argv[1]); + else + ifP = stdin; + if (argc-1 > 1) + pm_error("Too many arguments. The only argument is the " + "input file name"); + + pixels = ppm_readppm(ifP, &cols, &rows, &maxval); + if (cols < 8) + pm_error("ppm input too narrow, must be >= 8 pixels wide" ); + lmaxval = (long)maxval; + pm_close(ifP); + + /* Figure out the colormap. */ + pm_message("computing colormap..." ); + chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &nColors); + if (chv == NULL) + pm_error("too many colors - try doing a 'pnmquant %u'", MAXCOLORS); + pm_message("%u colors found", nColors); + + /* Make a hash table for fast color lookup. */ + cht = ppm_colorhisttocolorhash(chv, nColors); + + /* write the header */ + putFill(stdout, HEADER_SIZE); + + /* write picSize and picFrame */ + putShort(stdout, 0); + putRect(stdout, 0, 0, rows, cols); + + /* write version op and version */ + putShort(stdout, PICT_picVersion); + putShort(stdout, 0x02FF); + putShort(stdout, PICT_headerOp); + putLong(stdout, -1L); + putFixed(stdout, 0, 0); + putFixed(stdout, 0, 0); + putFixed(stdout, cols, 0); + putFixed(stdout, rows, 0); + putFill(stdout, 4); + + /* seems to be needed by many PICT2 programs */ + putShort(stdout, PICT_clipRgn); + putShort(stdout, 10); + putRect(stdout, 0, 0, rows, cols); + + /* write picture */ + putShort(stdout, PICT_PackBitsRect); + putShort(stdout, cols | 0x8000); + putRect(stdout, 0, 0, rows, cols); + putShort(stdout, 0); /* pmVersion */ + putShort(stdout, 0); /* packType */ + putLong(stdout, 0L); /* packSize */ + putFixed(stdout, 72, 0); /* hRes */ + putFixed(stdout, 72, 0); /* vRes */ + putShort(stdout, 0); /* pixelType */ + putShort(stdout, 8); /* pixelSize */ + putShort(stdout, 1); /* cmpCount */ + putShort(stdout, 8); /* cmpSize */ + putLong(stdout, 0L); /* planeBytes */ + putLong(stdout, 0L); /* pmTable */ + putLong(stdout, 0L); /* pmReserved */ + putLong(stdout, 0L); /* ctSeed */ + putShort(stdout, 0); /* ctFlags */ + putShort(stdout, nColors-1); /* ctSize */ + + /* Write out the colormap. */ + for (i = 0; i < nColors; ++i) { + putShort(stdout, i); + rval = PPM_GETR(chv[i].color); + gval = PPM_GETG(chv[i].color); + bval = PPM_GETB(chv[i].color); + if (lmaxval != 65535L) { + rval = rval * 65535L / lmaxval; + gval = gval * 65535L / lmaxval; + bval = bval * 65535L / lmaxval; + } + putShort(stdout, (short)rval); + putShort(stdout, (short)gval); + putShort(stdout, (short)bval); + } + + putRect(stdout, 0, 0, rows, cols); /* srcRect */ + putRect(stdout, 0, 0, rows, cols); /* dstRect */ + putShort(stdout, 0); /* mode */ + + /* Finally, write out the data. */ + outBuf = malloc((unsigned)(cols+cols/MAX_COUNT+1)); + for (row = 0, oc = 0; row < rows; ++row) { + unsigned int rowSize; + putRow(stdout, row, cols, pixels[row], outBuf, &rowSize); + oc += rowSize; + } + /* if we wrote an odd number of pixdata bytes, pad */ + if (oc & 0x1) + putc(0, stdout); + putShort(stdout, PICT_EndOfPicture); + + lmaxval = ftell(stdout) - HEADER_SIZE; + if (fseek(stdout, (long)HEADER_SIZE, 0) >= 0) + putShort(stdout, (short)(lmaxval & 0xffff)); + + return 0; } -#endif /* RUNLENGTH */ + + + diff --git a/converter/ppm/ppmtopjxl.c b/converter/ppm/ppmtopjxl.c index 91cd1a45..90bcef0f 100644 --- a/converter/ppm/ppmtopjxl.c +++ b/converter/ppm/ppmtopjxl.c @@ -12,6 +12,7 @@ * */ +#include <assert.h> #include <stdio.h> #include <math.h> #include <string.h> @@ -19,6 +20,7 @@ #include "pm_c_util.h" #include "nstring.h" #include "ppm.h" +#include "runlength.h" #define MAXCOLORS 1024 @@ -33,7 +35,7 @@ const char * const usage="[-nopack] [-gamma <n>] [-presentation] [-dark]\n\ #define PCL_MAXHEIGHT 32767 #define PCL_MAXVAL 255 -static int nopack = 0; +static bool nopack = false; static int dark = 0; static int diffuse = 0; static int dither = 0; @@ -73,16 +75,28 @@ static const struct options { {"-nopack", BOOL, &nopack }, }; -#define putword(w) (putchar(((w)>>8) & 255), putchar((w) & 255)) -static int -bitsperpixel(int v) { - int bpp = 0; - while (v > 0) { /* calculate # bits for value */ - ++bpp; - v>>=1; - } - return (bpp); + +static void +putword(unsigned short const w) { + putchar((w >> 8) & 0xff); + putchar((w >> 0) & 0xff); +} + + + +static unsigned int +bitsperpixel(unsigned int v) { + + unsigned int bpp; + + /* calculate # bits for value */ + + for (bpp = 0; v > 0; ) { + ++bpp; + v >>= 1; + } + return bpp; } @@ -94,101 +108,77 @@ static char *outrow = NULL; static signed char *runcnt = NULL; static void -putbits(b, n) { - /* put #n bits in b out, packing into bytes; n=0 flushes bits */ - /* n should never be > 8 */ - - static int out = 0; - static int cnt = 0; - static int num = 0; - static int pack = 0; - if (n) { - int xo = 0; - int xc = 0; - if (cnt+n > 8) { /* overflowing current byte? */ - xc = cnt + n - 8; - xo = (b & ~(-1 << xc)) << (8-xc); - n -= xc; - b >>= xc; - } - cnt += n; - out |= (b & ~(-1 << n)) << (8-cnt); - if (cnt >= 8) { - inrow[num++] = out; - out = xo; - cnt = xc; - } - } else { /* flush row */ - int i; - if (cnt) { - inrow[num++] = out; - out = cnt = 0; - } - for (; num > 0 && inrow[num-1] == 0; num--); /* remove trailing zeros */ - printf("\033*b"); - if (num && !nopack) { /* TIFF 4.0 packbits encoding */ - int start = 0; - int next; - runcnt[start] = 0; - for (i = 1; i < num; i++) { - if (inrow[i] == inrow[i-1]) { - if (runcnt[start] <= 0 && runcnt[start] > -127) - runcnt[start]--; - else - runcnt[start = i] = 0; - } else { - if (runcnt[start] >= 0 && runcnt[start] < 127) - runcnt[start]++; - else - runcnt[start = i] = 0; +putbits(int const bArg, + int const nArg) { +/*---------------------------------------------------------------------------- + Put 'n' bits in 'b' out, packing into bytes; n=0 flushes bits. + + n should never be > 8 +-----------------------------------------------------------------------------*/ + static int out = 0; + static int cnt = 0; + static int num = 0; + static bool pack = false; + + int b; + int n; + + b = bArg; + n = nArg; + + if (n) { + int xo = 0; + int xc = 0; + + assert(n <= 8); + + if (cnt + n > 8) { /* overflowing current byte? */ + xc = cnt + n - 8; + xo = (b & ~(-1 << xc)) << (8-xc); + n -= xc; + b >>= xc; } - } - start = 0; - for (i = 0; i < num; i = next) { - int count = runcnt[i]; - int from = i; - if (count >= 0) { /* merge two-byte runs */ - for (;;) { - next = i+1+runcnt[i]; - if(next >= num || runcnt[next] < 0 || - count+runcnt[next]+1 > 127) - break; - count += runcnt[next]+1; - i = next; - } + cnt += n; + out |= (b & ~(-1 << n)) << (8-cnt); + if (cnt >= 8) { + inrow[num++] = out; + out = xo; + cnt = xc; } - next = i + 1 + ((runcnt[i] < 0) ? -runcnt[i] : runcnt[i]); - if (next < num && count > 0 && - runcnt[next] < 0 && runcnt[next] > -127) { - count--; - next--; - runcnt[next] = runcnt[next+1]-1; + } else { /* flush row */ + if (cnt) { + inrow[num++] = out; + out = cnt = 0; } - outrow[start++] = count; - if (count >= 0) { - while (count-- >= 0) - outrow[start++] = inrow[from++]; - } else - outrow[start++] = inrow[from]; - } - if (start < num) { - num = start; - if (!pack) { - printf("2m"); - pack = 1; + for (; num > 0 && inrow[num-1] == 0; --num); + /* remove trailing zeros */ + printf("\033*b"); + if (num && !nopack) { /* TIFF 4.0 packbits encoding */ + size_t outSize; + pm_rlenc_compressbyte( + (unsigned char *)inrow, (unsigned char *)outrow, + PM_RLE_PACKBITS, num, &outSize); + if (outSize < num) { + num = outSize; + if (!pack) { + printf("2m"); + pack = true; + } + } else { + if (pack) { + printf("0m"); + pack = false; + } + } } - } else { - if (pack) { - printf("0m"); - pack = 0; + printf("%dW", num); + { + unsigned int i; + for (i = 0; i < num; ++i) + putchar(pack ? outrow[i] : inrow[i]); } - } - } - printf("%dW", num); - for (i = 0; i < num; i++) - putchar(pack ? outrow[i] : inrow[i]); - num = 0; /* new row */ - } + num = 0; /* new row */ + } } diff --git a/converter/ppm/ppmtorgb3.c b/converter/ppm/ppmtorgb3.c index b1ac8087..3d2f1c21 100644 --- a/converter/ppm/ppmtorgb3.c +++ b/converter/ppm/ppmtorgb3.c @@ -51,11 +51,11 @@ openComponentOut(const char * const suffix, const char * fileName; - asprintfN(&fileName, "%s.%s", baseName, suffix); + pm_asprintf(&fileName, "%s.%s", baseName, suffix); *fpP = pm_openw(fileName); - strfree(fileName); + pm_strfree(fileName); } @@ -90,7 +90,7 @@ main(int argc, const char ** argv) { ifP = pm_openr(cmdline.inputFileName); if (streq(cmdline.inputFileName, "-")) - asprintfN(&baseFileName, "noname"); + baseFileName = strdup("noname"); else baseFileName = strippedOfExtension(cmdline.inputFileName); @@ -131,7 +131,7 @@ main(int argc, const char ** argv) { pgm_freerow(grayrow); ppm_freerow(pixelrow); - strfree(baseFileName); + pm_strfree(baseFileName); pm_close(ifP); pm_close(blufP); pm_close(grnfP); diff --git a/converter/ppm/ppmtospu.c b/converter/ppm/ppmtospu.c new file mode 100644 index 00000000..b558c1fe --- /dev/null +++ b/converter/ppm/ppmtospu.c @@ -0,0 +1,593 @@ +/* + * ppmtpspu.c - Read a raw PPM file on stdin and write an uncompressed + * Spectrum file on stdout. + * + * Copyright (C) 1990, Steve Belczyk + */ + +#include <assert.h> +#include <stdio.h> + +#include "pm_c_util.h" +#include "mallocvar.h" +#include "shhopt.h" +#include "pam.h" + +#define SPU_WIDTH 320 +#define SPU_HEIGHT 200 + + +struct CmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileName; /* Name of input file */ + unsigned int dithflag; + /* dithering flag */ +}; + + +static void +parseCommandLine(int argc, const char ** argv, + struct CmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Parse the program arguments (given by argc and argv) into a form + the program can deal with more easily -- a cmdline_info structure. + If the syntax is invalid, issue a message and exit the program via + pm_error(). + + Note that the file spec array we return is stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optEntry * option_def; /* malloc'ed */ + optStruct3 opt; /* set by OPTENT3 */ + unsigned int option_def_index; + + unsigned int d0Spec, d2Spec, d4Spec; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "d0", OPT_FLAG, + NULL, &d0Spec, 0); + OPTENT3(0, "d2", OPT_FLAG, + NULL, &d2Spec, 0); + OPTENT3(0, "d4", OPT_FLAG, + NULL, &d4Spec, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + + if (d4Spec) + cmdlineP->dithflag = 4; + else if (d2Spec) + cmdlineP->dithflag = 2; + else if (d0Spec) + cmdlineP->dithflag = 0; + else + cmdlineP->dithflag = 2; + + if (argc-1 < 1) + cmdlineP->inputFileName = "-"; + else { + cmdlineP->inputFileName = argv[1]; + + if (argc-1 > 1) + pm_error("Program takes zero or one argument (filename). You " + "specified %u", argc-1); + } +} + + + +/* This is the stuff to remember about each pixel */ +struct PixelType { + unsigned int index4; /* 4-bit color, used in bitmap */ + unsigned int x; /* Pixel's original x-position */ + unsigned int popularity; /* Popularity of this pixel's color */ + unsigned int color9; /* 9-bit color this pixel actually got */ +}; + + +typedef struct { + int index[SPU_WIDTH][16]; /* Indices into the 48 color entries */ +} Index48; + +typedef struct { +/* These are the palettes, 3 16-color palettes per each of 200 scan lines */ + int pal[SPU_HEIGHT][48]; /* -1 means free */ +} Pal; + + + +static void +initializePalette(Pal * const palP) { +/*---------------------------------------------------------------------------- + Set palettes to zero +-----------------------------------------------------------------------------*/ + unsigned int row; + + for (row = 0; row < SPU_HEIGHT; ++row) { + unsigned int j; + for (j = 0; j < 48; ++j) + palP->pal[row][j] = 0; + } +} + + + +static int +findIndex(unsigned int const col, + unsigned int const index) { +/*---------------------------------------------------------------------------- + Given an x-coordinate and a color index, return the corresponding + Spectrum palette index. +-----------------------------------------------------------------------------*/ + int r, x1; + + x1 = 10 * index; /* initial value */ + if (index & 0x1) + x1 -= 5; + else + ++x1; + + r = index; /* initial value */ + + if ((col >= x1) && (col < (x1+160))) + r += 16; + + if (col >= (x1+160)) + r += 32; + + return r; +} + + + +static void +setup48(Index48 * const index48P) { +/*---------------------------------------------------------------------------- + For each pixel position, set up the indices into the 48-color + palette +-----------------------------------------------------------------------------*/ + unsigned int col; + + for (col = 0; col < SPU_WIDTH; ++col) { + unsigned int i; + for (i = 0; i < 16; ++i) + index48P->index[col][i] = findIndex(col, i); + } +} + + + +static void +dither(unsigned int const row, + tuple * const tuplerow, + unsigned int const dithflag, + struct PixelType * const pixelType) { + + static int const dith4[4][4] = { + { 0, 8, 2, 10 }, + { 12, 4, 14, 6 }, + { 3, 11, 1, 9 }, + { 15, 7, 13, 5 } + }; + + static int const dith2[2][2] = { + { 0, 2 }, + { 3, 1 } + }; + + unsigned int c[3]; /* An element for each plane */ + unsigned int col; + + for (col = 0; col < SPU_WIDTH; ++col) { + unsigned int plane; + + for (plane = 0; plane < 3; ++plane) { + unsigned int t; + + c[plane] = ((tuplerow[col][plane] & 0xe0) >> 5) & 0x7; + /* initial value */ + + switch (dithflag) { + case 0: + break; + + case 2: + t = (tuplerow[col][plane] & 0x18 ) >> 3; + if (t > dith2[col%2][row%2]) + ++c[plane]; + break; + + case 4: + t = (tuplerow[col][plane] & 0x1e) >> 1; + if (t > dith4[col%4][row%4]) + ++c[plane]; + break; + } + c[plane] = MIN(7, c[plane]); + } + pixelType[col].color9 = (c[0] << 6) | (c[1] << 3) | c[2]; + pixelType[col].x = col; + } +} + + + +static void +swapPixelType(struct PixelType * const pixelType, + unsigned int const i, + unsigned int const j) { + + struct PixelType const w = pixelType[i]; + + pixelType[i] = pixelType[j]; + pixelType[j] = w; +} + + + +static void +sort(struct PixelType * const pixelType, + unsigned int const left, + unsigned int const right) { +/*---------------------------------------------------------------------------- + Sort pixelType[] from element 'left' to (not including) element 'right' in + increasing popularity. + + Good ol' Quicksort. +-----------------------------------------------------------------------------*/ + unsigned int const pivot = pixelType[(left+right-1)/2].popularity; + + unsigned int i, j; + + /* Rearrange so that everything less than 'pivot' is on the left side of + the subject array slice and everything greater than is on the right + side and elements equal could be on either side (we won't know until + we're done where the dividing line between the sides is), then sort + those two sides. + */ + + assert(left < right); + + for (i = left, j = right; i < j; ) { + while (pixelType[i].popularity < pivot) + ++i; + while (pixelType[j-1].popularity > pivot) + --j; + + if (i < j) { + /* An element not less popular than pivot is to the left of a + pixel not more popular than pivot, so swap them. Note that we + could be swapping equal (pivot-valued) elements. Though the + swap isn't necessary, moving 'i' and 'j' is. + */ + swapPixelType(pixelType, i, j-1); + ++i; + --j; + } + } + + if (j - left > 1) + sort(pixelType, left, j); + if (right - i > 1) + sort(pixelType, i, right); +} + + + +static void +computePalette(struct PixelType * const pixelType) { + + unsigned int hist[512]; /* Count for each color */ + unsigned int col; + unsigned int i; + + /* Uses popularity algorithm */ + + /* Count the occurences of each color */ + + for (i = 0; i < 512; ++i) + hist[i] = 0; + + for (col = 0; col < SPU_WIDTH; ++col) + ++hist[pixelType[col].color9]; + + /* Set the popularity of each pixel's color */ + for (col = 0; col < SPU_WIDTH; ++col) + pixelType[col].popularity = hist[pixelType[col].color9]; + + /* Sort to find the most popular colors */ + sort(pixelType, 0, SPU_WIDTH); +} + + + +static int +dist9(unsigned int const x, + unsigned int const y) { +/*---------------------------------------------------------------------------- + Return the distance between two 9-bit colors. +-----------------------------------------------------------------------------*/ + unsigned int i; + unsigned int d; + int x0[3], y0[3]; + + x0[0] = (x & 0x007); + x0[1] = (x & 0x038) >> 3; + x0[2] = (x & 0x1c0) >> 6; + + y0[0] = (y & 0x007); + y0[1] = (y & 0x038) >> 3; + y0[2] = (y & 0x1c0) >> 6; + + for (i = 0, d = 0; i < 3; ++i) { + unsigned int const t = x0[i] - y0[i]; + d += t * t; + } + + return d; +} + + + +static void +convertPixel(unsigned int const col, + unsigned int const row, + struct PixelType * const pixelType, + Pal * const palP, + const Index48 * const index48P) { + + int ifree; + + unsigned int const x = pixelType[col].x; + unsigned int const c = pixelType[col].color9; + + ifree = -1; /* Set if free slot found */ + + /* Handle each possible case, from easiest to hardest, in the hopes the + easy ones are more frequent. + */ + + /* If it wants black, it gets it */ + if (c == 0) + pixelType[col].index4 = 0; + else { + /* If another pixel is using this color, it gets it */ + unsigned int i; + for (i = 1; i < 15; ++i) { + /* Check for free slots while we're here */ + if ((ifree < 0) && + (palP->pal[row][index48P->index[x][i]] == -1)) + ifree = i; + else if (c == palP->pal[row][index48P->index[x][i]]) { + pixelType[col].index4 = i; + return; + } + } + + /* If there are no free slots, we must use the closest entry in use so + far + */ + if (ifree < 0) { + unsigned int i; + unsigned int d; + unsigned int b; + + for (i = 1, d = 1000; i < 15; ++i) { + unsigned int const t = + dist9(c, palP->pal[row][index48P->index[x][i]]); + if (t < d) { + d = t; + b = i; + } + } + + /* See if it would be better off with black */ + if (d > dist9(c, 0)) + b = 0; + + pixelType[col].index4 = b; + } else { + /* Use up a slot and give it what it wants */ + palP->pal[row][index48P->index[x][ifree]] = c; + pixelType[col].index4 = ifree; + } + } +} + + + +static void +setPixel(unsigned int const col, + unsigned int const row, + unsigned int const c, + short * const screen) { + + unsigned int index, bit, plane; + + /* In the next few statements, the bit operations are a little + quicker, but the arithmetic versions are easier to read and + maybe more portable. Please try swapping them if you have + trouble on your machine. + */ + + /* index = (80 * row) + 4 * (col / 16); */ + index = (row << 6) + (row << 4) + ((col >> 4) << 2); + + /* bit = 0x8000 >> (col % 16); */ + bit = 0x8000 >> (col & 0x0f); + + for (plane=0; plane<4; ++plane) { + if (c & (1 << plane)) + screen[index + plane] |= bit; + } +} + + + +static void +convertRow(unsigned int const row, + struct PixelType * const pixelType, + Pal * const palP, + const Index48 * const index48P, + short * const screen) { + + unsigned int i; + + /* Mark palette entries as all free */ + for (i = 0; i < 48; ++i) + palP->pal[row][i] = -1; + + /* Mark reserved palette entries */ + palP->pal[row][0] = palP->pal[row][15] = palP->pal[row][16] = 0; + palP->pal[row][31] = palP->pal[row][32] = palP->pal[row][47] = 0; + + /* Convert each pixel */ + + { + /* Process the pixels in order of the popularity of the desired + color + */ + int col; + for (col = SPU_WIDTH-1; col >= 0; --col) { + convertPixel(col, row, pixelType, palP, index48P); + setPixel(pixelType[col].x, row, pixelType[col].index4, screen); + } + } +} + + + +static void +doRow(unsigned int const row, + tuple * const tuplerow, + unsigned int const dithflag, + const Index48 * const index48P, + Pal * const palP, + short * const screen) { + + struct PixelType pixelType[SPU_WIDTH]; + + /* Dither and reduce to 9 bits */ + dither(row, tuplerow, dithflag, pixelType); + + /* Compute the best colors for this row */ + computePalette(pixelType); + + /* Convert this row */ + convertRow(row, pixelType, palP, index48P, screen); +} + + + +static void +writeScreen(const short * const screen) { + + /* Write the bitmap */ + + unsigned int i; + + for (i = 0; i < 16000; ++i) { + char const c0 = 0xff & (screen[i] >> 8); + char const c1 = 0xff & screen[i]; + putchar(c0); + putchar(c1); + } +} + + + +static void +writePalettes(const Pal * const palP) { + + unsigned int row; + + for (row = 1; row < SPU_HEIGHT; ++row) { + unsigned int i; + for (i = 0; i < 48; ++i) { + int const p = palP->pal[row][i]; + unsigned int const q = + ((p & 0x1c0) << 2) + + ((p & 0x038) << 1) + + ((p & 0x007) << 0); + + putchar((q >> 8) & 0xff); + putchar((q >> 0) & 0xff); + } + } +} + + + +static void +writeSpu(const short * const screen, + const Pal * const palP ) { + + writeScreen(screen); + + writePalettes(palP); +} + + + +int +main (int argc, const char ** argv) { + + struct pam pam; + struct CmdlineInfo cmdline; + FILE * ifP; + tuple ** tuples; + Pal pal; + Index48 index48; + short screen[16000]; /* This is the ST's video RAM */ + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFileName); + + tuples = pnm_readpam(ifP, &pam, PAM_STRUCT_SIZE(tuple_type)); + + if (pam.depth < 3) + pm_error("Image must be RGB, so at least 3 deep. This image is " + "only %u deep", pam.depth); + + if ((pam.width != SPU_WIDTH) || (pam.height != SPU_HEIGHT)) + pm_error("Image size must be %ux%u. This one is %u x %u", + SPU_WIDTH, SPU_HEIGHT, pam.width, pam.height); + + { + unsigned int i; + for (i = 0; i < 16000; screen[i++] = 0); + } + setup48(&index48); + + initializePalette(&pal); + + { + /* Set first row of screen data to black */ + unsigned int i; + for (i = 0; i < 80; ++i) + screen[i] = 0; + } + { + unsigned int row; + for (row = 0; row < SPU_HEIGHT; ++row) + doRow(row, tuples[row], cmdline.dithflag, &index48, &pal, screen); + } + writeSpu(screen, &pal); + + return 0; +} + + + diff --git a/converter/ppm/ppmtoterm.c b/converter/ppm/ppmtoterm.c index 81df614e..d388f77d 100644 --- a/converter/ppm/ppmtoterm.c +++ b/converter/ppm/ppmtoterm.c @@ -19,32 +19,37 @@ ** */ +#include <assert.h> #include <string.h> #include "pm_c_util.h" -#include "ppm.h" +#include "mallocvar.h" #include "shhopt.h" +#include "ppm.h" struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char *inputFilespec; /* Filespec of input file */ + const char * inputFileName; /* Name of input file */ unsigned int verbose; }; static void -parseCommandLine(int argc, char **argv, - struct cmdlineInfo *cmdlineP) { - optEntry *option_def = malloc(100*sizeof(optEntry)); +parseCommandLine(int argc, const char ** argv, + struct cmdlineInfo * const cmdlineP) { + + optEntry * option_def; /* Instructions to OptParseOptions3 on how to parse our options */ optStruct3 opt; unsigned int option_def_index; + MALLOCARRAY_NOFAIL(option_def, 100); + option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); @@ -52,123 +57,176 @@ parseCommandLine(int argc, char **argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - switch (argc-1) { - case 0: - cmdlineP->inputFilespec = "-"; - break; - case 1: - cmdlineP->inputFilespec = argv[1]; - break; - case 2: - break; + if (argc-1 < 1) + cmdlineP->inputFileName = "-"; + else { + cmdlineP->inputFileName = argv[1]; + + if (argc-1 > 1) + pm_error("Too many arguments: %u. The only possible argument " + "is the input file name", argc-1); } } -#define ESC "\x1B\x5B" -#define NUM_COLORS 128 -#define MAX_ANSI_STR_LEN 16 +#define ESC "\x1B\x5B" +#define ANSI_BRIGHT_CMD_PAT ESC "%dm" +#define ANSI_FGCOLOR_CMD_PAT ESC "3%dm" +#define ANSI_BGCOLOR_CMD_PAT ESC "4%dm" +#define MAX_ANSI_STR_LEN 16 +#define NUM_COLORS 128 + /* 1 bit each RGB = 8 colors. + 8 BG colors * 8 FG colors * 2 brightnesses + */ -static int __inline__ sqr(const int x) { - return x*x; -} -/* - Generates some sort of color palette mixing the available - colors as different values of background, foreground & brightness. -*/ -static int -generate_palette(unsigned char rgb[NUM_COLORS][3], - char ansi_code[NUM_COLORS][MAX_ANSI_STR_LEN]) { - int code, col=0, cd2=0; - - memset((void *)rgb, 0, NUM_COLORS*3); - memset((void *)ansi_code, 0, NUM_COLORS*MAX_ANSI_STR_LEN); - - for(col=cd2=0; cd2<8; cd2++) { - unsigned int b; - for(b=0;b<2;b++) { - for(code=0; code<8; code++) { - unsigned int c; - for(c=0;c<3;c++) { - if(code&(1<<c)) { - rgb[col][c]=(192|(b?63:0)); - } - if(cd2&(1<<c)) { - rgb[col][c]|=(128); + +static void +generatePalette(unsigned char rgb[NUM_COLORS][3], + char ansiCode[NUM_COLORS][MAX_ANSI_STR_LEN], + unsigned int * const paletteSizeP) { +/*---------------------------------------------------------------------------- + Generate some sort of color palette mixing the available colors as different + values of background, foreground & brightness. + + We return as rgb[I] the RGB triple for the color with palette index I. + Component intensities are in the range 0..255. rgb[I][0] is red; + rgb[I][1] is green; rgb[I][2] is blue. + + We return as ansiCode[I] the sequence you send to a terminal to generate + the color with palette index I. +-----------------------------------------------------------------------------*/ + unsigned int idx; + /* palette index of the color being considered */ + unsigned int bgColorCode; + /* This is the ANSI color code for the background. An ANSI color code + is a 3 bit code in which LSB means red; middle bit means green, and + MSB means blue. + */ + + /* We develop the palette backwards: consider every permutation of the + three terminal controls -- background, foreground, and brightness -- + and for each figure out what RGB color it represents and fill in + that element of RGB[][] + */ + + for (bgColorCode = 0, idx = 0; bgColorCode < 8; ++bgColorCode) { + unsigned int brightness; /* 0 = dim; 1 = bright */ + for (brightness = 0; brightness < 2; ++brightness) { + unsigned int fgColorCode; + /* ANSI color code for the foreground. See bgColorCode. */ + for (fgColorCode = 0; fgColorCode < 8; ++fgColorCode) { + unsigned int rgbComp; + /* 0 = red; 1 = green; 2 = blue */ + for (rgbComp = 0; rgbComp < 3; ++rgbComp) { + assert (idx < NUM_COLORS); + rgb[idx][rgbComp] = 0x00; /* initial value */ + if ((fgColorCode & (0x1 << rgbComp)) != 0) { + rgb[idx][rgbComp] |= 0xC0; + if (brightness == 1) + rgb[idx][rgbComp] |= 0x3F; } + if ((bgColorCode & (0x1 << rgbComp)) != 0) + rgb[idx][rgbComp] |= 0x80; } - sprintf(ansi_code[col], - ESC"%dm"ESC"3%dm"ESC"4%dm", - b, code, cd2); - col++; + sprintf(ansiCode[idx], + ANSI_BRIGHT_CMD_PAT + ANSI_FGCOLOR_CMD_PAT + ANSI_BGCOLOR_CMD_PAT, + brightness, fgColorCode, bgColorCode); + ++idx; } } } - return col; + *paletteSizeP = idx; +} + + + +static void +lookupInPalette(pixel const pixel, + pixval const maxval, + unsigned char rgb[NUM_COLORS][3], + unsigned int const palLen, + unsigned int * const paletteIdxP) { +/*---------------------------------------------------------------------------- + Look up the color 'pixel' (which has maxval 'maxval') in the palette + palette[], which has 'palLen' elements and uses maxval 255. Return the + index into palette[] of the color that is closes to 'pixel' as + *paletteIdxP. +-----------------------------------------------------------------------------*/ + pixval const r = PPM_GETR(pixel) * 255 / maxval; + pixval const g = PPM_GETG(pixel) * 255 / maxval; + pixval const b = PPM_GETB(pixel) * 255 / maxval; + + unsigned int paletteIdxSoFar; + unsigned int dist; + unsigned int i; + + /* The following loop calculates the index that corresponds to the + minimum color distance between the given RGB values and the + values available in the palette. + */ + for (i = 0, dist = SQR(255)*3, paletteIdxSoFar = 0; i < palLen; ++i) { + pixval const pr=rgb[i][0]; + pixval const pg=rgb[i][1]; + pixval const pb=rgb[i][2]; + unsigned int const j = SQR(r-pr) + SQR(b-pb) + SQR(g-pg); + + if (j < dist) { + dist = j; + paletteIdxSoFar = i; + } + } + *paletteIdxP = paletteIdxSoFar; } -int main(int argc, char **argv) -{ - FILE *ifp; - pixel **pixels; - int rows, row, cols, col, - pal_len, i; +int +main(int argc, const char ** argv) { + + FILE * ifP; + pixel ** pixels; + int rows, cols; + unsigned int row; + unsigned int palLen; pixval maxval; - struct cmdlineInfo - cmdline; + struct cmdlineInfo cmdline; unsigned char rgb[NUM_COLORS][3]; - char ansi_code[NUM_COLORS][MAX_ANSI_STR_LEN]; + char ansiCode[NUM_COLORS][MAX_ANSI_STR_LEN]; - - ppm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); - ifp = pm_openr(cmdline.inputFilespec); + ifP = pm_openr(cmdline.inputFileName); - pixels = ppm_readppm(ifp, &cols, &rows, &maxval); + pixels = ppm_readppm(ifP, &cols, &rows, &maxval); - pm_close(ifp); + pm_close(ifP); - pal_len=generate_palette(rgb, ansi_code); + generatePalette(rgb, ansiCode, &palLen); for (row = 0; row < rows; ++row) { - for (col = 0; col < cols; col++) { - pixval const r=(int)PPM_GETR(pixels[row][col])*255/maxval; - pixval const g=(int)PPM_GETG(pixels[row][col])*255/maxval; - pixval const b=(int)PPM_GETB(pixels[row][col])*255/maxval; - int val, dist; - - /* - The following loop calculates the index that - corresponds to the minimum color distance - between the given RGB values and the values - available in the palette. - */ - for(i=0, dist=sqr(255)*3, val=0; i<pal_len; i++) { - pixval const pr=rgb[i][0]; - pixval const pg=rgb[i][1]; - pixval const pb=rgb[i][2]; - unsigned int j; - if( (j=sqr(r-pr)+sqr(b-pb)+sqr(g-pg))<dist ) { - dist=j; - val=i; - } - } - printf("%s%c", ansi_code[val],0xB1); + unsigned int col; + for (col = 0; col < cols; ++col) { + unsigned int paletteIdx; + + lookupInPalette(pixels[row][col], maxval, rgb, palLen, + &paletteIdx); + + printf("%s\xB1", ansiCode[paletteIdx]); } - printf(ESC"\x30m\n"); + printf(ESC "\x30m\n"); } - printf(ESC"\x30m"); + printf(ESC "\x30m"); ppm_freearray(pixels, rows); - exit(0); + return 0; } diff --git a/converter/ppm/ppmtowinicon.c b/converter/ppm/ppmtowinicon.c index a96840a1..c673798f 100644 --- a/converter/ppm/ppmtowinicon.c +++ b/converter/ppm/ppmtowinicon.c @@ -58,7 +58,7 @@ parseCommandLine(int argc, was passed to us as the argv array. We also trash *argv. -----------------------------------------------------------------------------*/ optEntry *option_def; - /* Instructions to optParseOptions3 on how to parse our options. + /* Instructions to pm_optParseOptions3 on how to parse our options. */ optStruct3 opt; @@ -82,7 +82,7 @@ parseCommandLine(int argc, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3( &argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (!outputSpec) @@ -524,9 +524,9 @@ makePalette(pixel ** const xorPPMarray, xorChv = ppm_computecolorhist(xorPPMarray, xorCols, xorRows, MAXCOLORS, &colors); if (xorChv == NULL) - asprintfN(errorP, - "image has too many colors - try doing a 'pnmquant %d'", - MAXCOLORS); + pm_asprintf(errorP, + "image has too many colors - try doing a 'pnmquant %d'", + MAXCOLORS); else { *errorP = NULL; @@ -584,10 +584,10 @@ getOrFakeAndMap(const char * const andPgmFname, pm_close(andfile); if ((andCols != xorCols) || (andRows != xorRows)) { - asprintfN(errorP, - "And mask and image have different dimensions " - "(%d x %d vs %d x %d). Aborting.", - andCols, xorCols, andRows, xorRows); + pm_asprintf(errorP, + "And mask and image have different dimensions " + "(%d x %d vs %d x %d). Aborting.", + andCols, xorCols, andRows, xorRows); } else *errorP = NULL; } @@ -670,7 +670,7 @@ addEntryToIcon(MS_Ico const MSIconData, * All the icons I found seemed to pad the palette to the max entries * for that bitdepth. * - * The spec indicates this isn't neccessary, but I'll follow this behaviour + * The spec indicates this isn't necessary, but I'll follow this behaviour * just in case. */ if (colors < 3) { diff --git a/converter/ppm/ppmtoxpm.c b/converter/ppm/ppmtoxpm.c index fc8ba9d7..38d99972 100644 --- a/converter/ppm/ppmtoxpm.c +++ b/converter/ppm/ppmtoxpm.c @@ -126,7 +126,7 @@ parseCommandLine(int argc, char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We may have parms that are negative numbers */ - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (argc-1 == 0) @@ -317,7 +317,7 @@ genCmap(colorhist_vector const chv, MALLOCARRAY(cmap, cmapSize); if (cmapP == NULL) pm_error("Out of memory allocating %u bytes for a color map.", - sizeof(cixel_map) * (ncolors+1)); + (unsigned)sizeof(cixel_map) * (ncolors+1)); xpmMaxval = xpmMaxvalFromMaxval(maxval); @@ -363,13 +363,13 @@ genCmap(colorhist_vector const chv, PPM_DEPTH(scaledColor, color, maxval, xpmMaxval); - asprintfN(&hexString, xpmMaxval == 0x000F ? "#%X%X%X" : - xpmMaxval == 0x00FF ? "#%02X%02X%02X" : - xpmMaxval == 0x0FFF ? "#%03X%03X%03X" : - "#%04X%04X%04X", - PPM_GETR(scaledColor), - PPM_GETG(scaledColor), - PPM_GETB(scaledColor) + pm_asprintf(&hexString, xpmMaxval == 0x000F ? "#%X%X%X" : + xpmMaxval == 0x00FF ? "#%02X%02X%02X" : + xpmMaxval == 0x0FFF ? "#%03X%03X%03X" : + "#%04X%04X%04X", + PPM_GETR(scaledColor), + PPM_GETG(scaledColor), + PPM_GETB(scaledColor) ); if (hexString == NULL) @@ -399,7 +399,7 @@ destroyCmap(cixel_map * const cmap, int i; /* Free the real color entries */ for (i = 0; i < cmapSize; i++) { - strfree(cmap[i].rgbname); + pm_strfree(cmap[i].rgbname); free(cmap[i].cixel); } free(cmap); diff --git a/converter/ppm/ppmtoyuv.c b/converter/ppm/ppmtoyuv.c index 7d843cc0..75f79c1e 100644 --- a/converter/ppm/ppmtoyuv.c +++ b/converter/ppm/ppmtoyuv.c @@ -19,79 +19,102 @@ #include "ppm.h" -int -main(argc, argv) -char **argv; -{ - FILE *ifp; - pixel *pixelrow; - register pixel *pP; - int rows, cols, format, row; - register int col; - pixval maxval; - unsigned long y1, y2=0, u=0, v=0, u0=0, u1, u2, v0=0, v1, v2; - unsigned char *yuvbuf; - - - ppm_init(&argc, argv); - if (argc > 2) pm_usage("[ppmfile]"); - if (argc == 2) ifp = pm_openr(argv[1]); - else ifp = stdin; - - ppm_readppminit(ifp, &cols, &rows, &maxval, &format); +static void +convertRow(const pixel * const pixelrow, + unsigned int const cols, + unsigned char * const yuvBuf, + unsigned long * const uP, + unsigned long * const vP, + unsigned long * const u0P, + unsigned long * const v0P, + unsigned long * const y2CarryP) { + + unsigned int col; + unsigned char * yuvptr; + + for (col = 0, yuvptr = &yuvBuf[0]; col < cols; col += 2) { + unsigned long y1, y2, u1, u2, v1, v2; + + { + /* first pixel gives Y and 0.5 of chroma */ + pixval const r = PPM_GETR(pixelrow[col]); + pixval const g = PPM_GETG(pixelrow[col]); + pixval const b = PPM_GETB(pixelrow[col]); + + y1 = 16829 * r + 33039 * g + 6416 * b + (*y2CarryP & 0xffff); + u1 = -4853 * r - 9530 * g + 14383 * b; + v1 = 14386 * r - 12046 * g - 2340 * b; + } + { + /* second pixel gives Y and 0.25 of chroma */ + pixval const r = PPM_GETR(pixelrow[col + 1]); + pixval const g = PPM_GETG(pixelrow[col + 1]); + pixval const b = PPM_GETB(pixelrow[col + 1]); + + y2 = 16829 * r + 33039 * g + 6416 * b + (y1 & 0xffff); + u2 = -2426 * r - 4765 * g + 7191 * b; + v2 = 7193 * r - 6023 * g - 1170 * b; + } + /* filter the chroma */ + *uP = *u0P + u1 + u2 + (*uP & 0xffff); + *vP = *v0P + v1 + v2 + (*vP & 0xffff); + + *u0P = u2; + *v0P = v2; + + *yuvptr++ = (*uP >> 16) + 128; + *yuvptr++ = (y1 >> 16) + 16; + *yuvptr++ = (*vP >> 16) + 128; + *yuvptr++ = (y2 >> 16) + 16; + + *y2CarryP = y2; + } +} - if (cols % 2 != 0) - pm_error("Image must have even number of columns.\n" - "This image is %d columns wide. Try Pnmcut.", cols); - pixelrow = ((pixel*) pm_allocrow( cols, sizeof(pixel) )); - yuvbuf = (unsigned char *) pm_allocrow( cols, 2 ); - for (row = 0; row < rows; ++row) { - unsigned char *yuvptr; +int +main(int argc, const char **argv) { - ppm_readppmrow(ifp, pixelrow, cols, maxval, format); + FILE * ifP; + pixel * pixelrow; + int rows, cols, format; + pixval maxval; + unsigned int row; + unsigned char * yuvBuf; + unsigned long u, v, u0, v0, y2Carry; - for (col = 0, pP = pixelrow, yuvptr=yuvbuf; col < cols; col += 2, ++pP) { - pixval r, g, b; + pm_proginit(&argc, argv); - /* first pixel gives Y and 0.5 of chroma */ - r = PPM_GETR(*pP); - g = PPM_GETG(*pP); - b = PPM_GETB(*pP); + if (argc-1 > 1) + pm_error("Too many arguments: %u. The only possible argument " + "is the name of the input file", argc-1); - y1 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y2); - u1 = -4853 * r - 9530 * g + 14383 * b; - v1 = 14386 * r - 12046 * g - 2340 * b; + if (argc-1 == 1) + ifP = pm_openr(argv[1]); + else + ifP = stdin; - pP++; - /* second pixel just yields a Y and 0.25 U, 0.25 V */ - r = PPM_GETR(*pP); - g = PPM_GETG(*pP); - b = PPM_GETB(*pP); + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); - y2 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y1); - u2 = -2426 * r - 4765 * g + 7191 * b; - v2 = 7193 * r - 6023 * g - 1170 * b; + if (cols % 2 != 0) + pm_error("Image must have even number of columns.\n" + "This image is %u columns wide. Try Pamcut.", cols); - /* filter the chroma */ - u = u0 + u1 + u2 + (0xffff & u); - v = v0 + v1 + v2 + (0xffff & v); + pixelrow = ppm_allocrow(cols); + yuvBuf = (unsigned char *) pm_allocrow(cols, 2); - u0 = u2; - v0 = v2; + for (row = 0, u = v = u0 = v0 = y2Carry = 0; row < rows; ++row) { + ppm_readppmrow(ifP, pixelrow, cols, maxval, format); - *yuvptr++ = (u >> 16) + 128; - *yuvptr++ = (y1 >> 16) + 16; - *yuvptr++ = (v >> 16) + 128; - *yuvptr++ = (y2 >> 16) + 16; - } - fwrite(yuvbuf, cols*2, 1, stdout); - } + convertRow(pixelrow, cols, yuvBuf, &u, &v, &u0, &v0, &y2Carry); + + fwrite(yuvBuf, cols*2, 1, stdout); + } - pm_close(ifp); + pm_close(ifP); - exit(0); + return 0; } diff --git a/converter/ppm/ppmtoyuvsplit.c b/converter/ppm/ppmtoyuvsplit.c index b5809d0b..eb89ad29 100644 --- a/converter/ppm/ppmtoyuvsplit.c +++ b/converter/ppm/ppmtoyuvsplit.c @@ -46,9 +46,9 @@ static void makeOutputFileName(const char * const baseName, struct FileNameSet * const fnameP) { - asprintfN(&fnameP->u, "%s.U", baseName); - asprintfN(&fnameP->v, "%s.V", baseName); - asprintfN(&fnameP->y, "%s.Y", baseName); + pm_asprintf(&fnameP->u, "%s.U", baseName); + pm_asprintf(&fnameP->v, "%s.V", baseName); + pm_asprintf(&fnameP->y, "%s.Y", baseName); } @@ -56,9 +56,9 @@ makeOutputFileName(const char * const baseName, static void termFileNameSet(struct FileNameSet const fname) { - strfree(fname.u); - strfree(fname.v); - strfree(fname.y); + pm_strfree(fname.u); + pm_strfree(fname.v); + pm_strfree(fname.y); } diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c index ad16a649..6ba4cb40 100644 --- a/converter/ppm/sldtoppm.c +++ b/converter/ppm/sldtoppm.c @@ -26,23 +26,20 @@ #include <string.h> #include <math.h> +#include "pm_c_util.h" #include "ppm.h" #include "ppmdraw.h" #include "nstring.h" -#ifdef DEBUG #include <assert.h> -#else -#define assert(x) -#endif + +#include "autocad.h" /* AutoCAD standard color assignments */ + /* Define a variable type accepting numbers -127 <= n <= 127. But note that we still expect it to act UNSIGNED. */ #define smallint unsigned char /* Small integers */ -#define TRUE 1 -#define FALSE 0 - #define EOS '\0' /* Screen point */ @@ -70,18 +67,17 @@ typedef void (slvecfn)(struct svector * vec, int color); typedef void (slfloodfn)(struct spolygon * poly, int color); +static unsigned long const pixmaxval = 255; /* Largest pixel value */ + static int ixdots, iydots; /* Screen size in dots */ -static FILE *slfile; /* Slide file descriptor */ -static int blither = FALSE; /* Dump slide file information ? */ -static int info = FALSE; /* Print header information */ +static FILE * slfile; /* Slide file descriptor */ +static bool blither; /* Dump slide file information ? */ +static bool info; /* Print header information */ static pixel **pixels; /* Pixel map */ -static int pixcols, pixrows; /* Pixel map size */ -#define pixmaxval 255 /* Largest pixel value */ +static int pixcols, pixrows; /* Pixel map size */ static double uscale = -1; /* Uniform scale factor */ static int sxsize = -1, sysize = -1; /* Scale to X, Y size ? */ -#include "autocad.h" /* AutoCAD standard color assignments */ - /* Local variables */ struct slhead { @@ -94,11 +90,11 @@ struct slhead { char spad; /* Pad to even byte length */ }; -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 bool adjust; /* Adjust to correct aspect ratio ? */ +static struct slhead slfrof; /* Slide file header */ +static long xfac, yfac; /* Aspect ratio scale factors */ -static int sdrawkcab; +static bool sdrawkcab; /* Slide drawing kinematic conversion of ass-backwards data flag */ @@ -108,7 +104,7 @@ static int sdrawkcab; */ static int -extend(smallint ch) { +extend(unsigned char const ch) { return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch)); } @@ -136,9 +132,9 @@ sli(void) { static int slib(void) { - smallint ch = 0; + unsigned char ch; - if (fread(&ch, sizeof ch, 1, slfile) != 1) { + if (fread(&ch, sizeof(ch), 1, slfile) != 1) { pm_error("error reading slide file"); } return extend(ch); @@ -171,22 +167,28 @@ slidefind(const char * const sname, char uname[32]; unsigned char libent[36]; long pos; + bool found; + bool eof; if (dironly) pm_message("Slides in library:"); else { - int i; + unsigned int i; const char * ip; ip = sname; /* initial value */ - for (i = 0; i < 31; i++) { - char ch = *ip++; + for (i = 0; i < 31; ++i) { + char const ch = *ip++; if (ch == EOS) break; - if (ucasen && ISLOWER(ch)) - ch = TOUPPER(ch); - uname[i] = ch; + + { + char const upperCh = + ucasen && islower(ch) ? toupper(ch) : ch; + + uname[i] = upperCh; + } } uname[i] = EOS; } @@ -199,31 +201,38 @@ slidefind(const char * const sname, } pos = 32; - /* Search for a slide with the requested name. */ + /* Search for a slide with the requested name or list the directory */ - while (TRUE) { - if ((fread(libent, 36, 1, slfile) != 1) || - (strlen((char *)libent) == 0)) { - if (dironly) { - return; - } - pm_error("slide %s not in library.", sname); - } + for (found = false, eof = false; !found && !eof; ) { + size_t readCt; + readCt = fread(libent, 36, 1, slfile); + if (readCt != 1) + eof = true; + else if (strlen((char *)libent) == 0) + eof = true; + } + if (!eof) { 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]; + long dpos; + + 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; + found = true; } } + + if (!found && !dironly) + pm_error("slide '%s' not in library.", sname); } @@ -329,7 +338,7 @@ slider(slvecfn slvec, /* Process the header of the slide file. */ - sdrawkcab = FALSE; /* Initially guess byte order is OK */ + sdrawkcab = false; /* Initially guess byte order is OK */ fread(slfrof.slh, 17, 1, slfile); fread(&slfrof.sntype, sizeof(char), 1, slfile); fread(&slfrof.slevel, sizeof(char), 1, slfile); @@ -364,12 +373,12 @@ slider(slvecfn slvec, */ if (btest != rtest) { - sdrawkcab = TRUE; -#define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8) + sdrawkcab = true; + #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8) rshort(slfrof.sxdots); rshort(slfrof.sydots); rshort(slfrof.shwfill); -#undef rshort + #undef rshort } /* Dump the header if we're blithering. */ @@ -413,7 +422,7 @@ slider(slvecfn slvec, 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. */ @@ -571,32 +580,42 @@ slider(slvecfn slvec, /* Main program. */ int -main(int argc, - char * argv[]) { +main(int argc, + const 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]"; - int scalespec = FALSE, widspec = FALSE, hgtspec = FALSE, dironly = FALSE, - ucasen; + bool dironly; + bool hgtspec; + bool widspec; + bool scalespec; + bool ucasen; const char * slobber; /* Slide library item */ + pm_proginit(&argc, argv); + argn = 1; slobber = NULL; - - ppm_init(&argc, argv); - argn = 1; + dironly = false; + hgtspec = false; + widspec = false; + scalespec = false; + ucasen = false; + blither = false; + info = false; + adjust = false; 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) pm_error("already specified a library item"); @@ -616,7 +635,7 @@ main(int argc, 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) { @@ -625,7 +644,7 @@ main(int argc, argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1)) pm_usage(usage); - widspec = TRUE; + widspec = true; } else if (pm_keymatch(argv[argn], "-ysize", 2) || pm_keymatch(argv[argn], "-height", 2)) { if (hgtspec) { @@ -634,7 +653,7 @@ main(int argc, argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) pm_usage(usage); - hgtspec = TRUE; + hgtspec = true; } else { pm_usage(usage); } @@ -665,7 +684,7 @@ main(int argc, if (!dironly) { slider(draw, flood); - ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE); + ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, 0); } pm_close(slfile); pm_close(stdout); diff --git a/converter/ppm/sputoppm.c b/converter/ppm/sputoppm.c index 2671bffa..acf61c1b 100644 --- a/converter/ppm/sputoppm.c +++ b/converter/ppm/sputoppm.c @@ -1,4 +1,4 @@ -/* sputoppm.c - read an uncompressed Spectrum file and produce a portable pixmap +/* sputoppm.c - read an uncompressed Spectrum file and produce a PPM ** ** Copyright (C) 1991 by Steve Belczyk and Jef Poskanzer ** @@ -16,93 +16,114 @@ #define COLS 320 #define MAXVAL 7 -static pixel pal[ROWS][48]; /* Spectrum palettes, three per row */ -static short screen[ROWS*COLS/4]; /* simulates the Atari's video RAM */ -int -main( argc, argv ) - int argc; - char* argv[]; +typedef struct { + pixel pal[ROWS][48]; /* Spectrum palettes, three per row */ +} Pal; + + + +static void +readPalettes(FILE * const ifP, + Pal * const palP) { + + unsigned int row; + + /* Clear the first palette line. */ { - FILE* ifp; - int i, j; - pixel* pixelrow; - register pixel* pP; - int row, col; + unsigned int j; + for (j = 0; j < 48; ++j) + PPM_ASSIGN(palP->pal[0][j], 0, 0, 0); + } + /* Read the palettes. */ + for (row = 1; row < ROWS; ++row) { + unsigned int j; + for (j = 0; j < 48; ++j) { + short k; + pm_readbigshort(ifP, &k); + PPM_ASSIGN(palP->pal[row][j], + (k & 0x700) >> 8, + (k & 0x070) >> 4, + (k & 0x007) >> 0); + } + } +} + + + +int +main(int argc, const char ** argv) { + FILE * ifP; + unsigned int i; + pixel * pixelrow; + unsigned int row; + Pal pal; + short screen[ROWS*COLS/4]; /* simulates the Atari's video RAM */ - ppm_init( &argc, argv ); + pm_proginit(&argc, argv); /* Check args. */ if ( argc > 2 ) pm_usage( "[spufile]" ); if ( argc == 2 ) - ifp = pm_openr( argv[1] ); + ifP = pm_openr( argv[1] ); else - ifp = stdin; + ifP = stdin; /* Read the SPU file */ /* Read the screen data. */ - for ( i = 0; i < ROWS*COLS/4; ++i ) - (void) pm_readbigshort( ifp, &screen[i] ); - - /* Clear the first palette line. */ - for ( j = 0; j < 48; ++j ) - PPM_ASSIGN( pal[0][j], 0, 0, 0 ); + for (i = 0; i < ROWS*COLS/4; ++i) + pm_readbigshort(ifP, &screen[i]); - /* Read the palettes. */ - for ( i = 1; i < ROWS; ++i ) - for ( j = 0; j < 48; ++j ) - { - short k; - (void) pm_readbigshort( ifp, &k ); - PPM_ASSIGN( pal[i][j], - ( k & 0x700 ) >> 8, - ( k & 0x070 ) >> 4, - ( k & 0x007 ) ); - } + readPalettes(ifP, &pal); - pm_close( ifp ); + pm_close(ifP); /* Ok, get set for writing PPM. */ - ppm_writeppminit( stdout, COLS, ROWS, (pixval) MAXVAL, 0 ); - pixelrow = ppm_allocrow( COLS ); + ppm_writeppminit(stdout, COLS, ROWS, MAXVAL, 0); + pixelrow = ppm_allocrow(COLS); /* Now do the conversion. */ - for ( row = 0; row < ROWS; ++row ) - { - for ( col = 0, pP = pixelrow; col < COLS; ++col, ++pP ) - { - int c, ind, b, plane, x1; - + for (row = 0; row < ROWS; ++row) { + unsigned int col; + for (col = 0; col < COLS; ++col) { /* Compute pixel value. */ - ind = 80 * row + ( ( col >> 4 ) << 2 ); - b = 0x8000 >> (col & 0xf); - c = 0; - for ( plane = 0; plane < 4; ++plane ) - if ( b & screen[ind+plane] ) + unsigned int const ind = 80 * row + ((col >> 4) << 2); + unsigned int const b = 0x8000 >> (col & 0xf); + unsigned int c; + unsigned int plane; + unsigned int x1; + + c = 0; /* initial value */ + for (plane = 0; plane < 4; ++plane) { + if (b & screen[ind + plane]) c |= (1 << plane); - + } /* Compute palette index. */ x1 = 10 * c; - if ( c & 1 ) + if ((c & 1) != 0) x1 -= 5; else ++x1; - if ( ( col >= x1 ) && ( col < ( x1 + 160 ) ) ) + if ((col >= x1 ) && (col < (x1 + 160))) c += 16; - if ( col >= ( x1 + 160 ) ) + if (col >= (x1 + 160)) c += 32; - /* Store the proper color. */ - *pP = pal[row][c]; - } - ppm_writeppmrow( stdout, pixelrow, COLS, (pixval) MAXVAL, 0 ); + /* Set the proper color. */ + pixelrow[col] = pal.pal[row][c]; } + ppm_writeppmrow(stdout, pixelrow, COLS, MAXVAL, 0); + } + + ppm_freerow(pixelrow); + pm_close(stdout); + + return 0; +} + - pm_close( stdout ); - exit( 0 ); - } diff --git a/converter/ppm/tgatoppm.c b/converter/ppm/tgatoppm.c index f8538214..95893089 100644 --- a/converter/ppm/tgatoppm.c +++ b/converter/ppm/tgatoppm.c @@ -71,7 +71,7 @@ parseCommandLine(int argc, char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (argc - 1 == 0) diff --git a/converter/ppm/winicontoppm.c b/converter/ppm/winicontoppm.c index ad859c94..6b1376b2 100644 --- a/converter/ppm/winicontoppm.c +++ b/converter/ppm/winicontoppm.c @@ -31,10 +31,9 @@ #define MAJVERSION 0 #define MINVERSION 4 -static int file_offset = 0; /* not actually used, but useful for debug */ +static int fileOffset = 0; /* not actually used, but useful for debug */ static const char er_read[] = "%s: read error"; static const char * infname; -static FILE * ifp; struct cmdlineInfo { /* All the information the user supplied in the command line, @@ -53,8 +52,8 @@ struct cmdlineInfo { static void -parseCommandLine ( int argc, char ** argv, - struct cmdlineInfo *cmdlineP ) { +parseCommandLine (int argc, const char ** argv, + struct cmdlineInfo *cmdlineP ) { /*---------------------------------------------------------------------------- parse program command line described in Unix standard form by argc and argv. Return the information in the options as *cmdlineP. @@ -65,13 +64,15 @@ parseCommandLine ( int argc, char ** argv, Note that the strings we return are stored in the storage that was passed to us as the argv array. We also trash *argv. -----------------------------------------------------------------------------*/ - optEntry *option_def = malloc(100*sizeof(optEntry)); - /* Instructions to optParseOptions3 on how to parse our options. + optEntry * option_def; + /* Instructions to pm_optParseOptions3 on how to parse our options. */ optStruct3 opt; unsigned int option_def_index; + MALLOCARRAY(option_def, 100); + option_def_index = 0; /* incremented by OPTENT3 */ OPTENT3(0, "allicons", OPT_FLAG, NULL, &cmdlineP->allicons, 0 ); @@ -88,10 +89,9 @@ parseCommandLine ( int argc, char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3( &argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - if (argc-1 < 1) cmdlineP->inputFilespec = "-"; else @@ -116,37 +116,37 @@ parseCommandLine ( int argc, char ** argv, static int -GetByte(void) { +GetByte(FILE * const ifP) { + int v; - if ((v = getc(ifp)) == EOF) - { + v = getc(ifP); + if (v == EOF) pm_error(er_read, infname); - } return v; } + + static short -GetShort(void) { +GetShort(FILE * const ifP) { + short v; - if (pm_readlittleshort(ifp, &v) == -1) - { - pm_error(er_read, infname); - } - + pm_readlittleshort(ifP, &v); + return v; } + + static long -GetLong(void) { +GetLong(FILE * const ifP) { + long v; - if (pm_readlittlelong(ifp, &v) == -1) - { - pm_error(er_read, infname); - } + pm_readlittlelong(ifP, &v); return v; } @@ -158,14 +158,18 @@ GetLong(void) { * functions. */ static u1 -readU1 (void) { - file_offset++; - return GetByte(); +readU1(FILE * const ifP) { + + ++fileOffset; + + return GetByte(ifP); } + + static u1 * -readU1String (int length) -{ +readU1String (FILE * const ifP, + unsigned int const length) { u1 * string; @@ -173,150 +177,173 @@ readU1String (int length) if (string == NULL) pm_error("out of memory"); - fread(string,sizeof(u1),length,ifp); + fread(string, sizeof(u1), length, ifP); string[length] = 0; - file_offset += length * sizeof(u1); + fileOffset += length * sizeof(u1); + return string; } + + static u2 -readU2 (void) { - file_offset +=2; - return GetShort(); +readU2 (FILE * const ifP) { + + fileOffset +=2; + + return GetShort(ifP); } + + static u4 -readU4 (void) { - file_offset += 4; - return GetLong(); +readU4 (FILE * const ifP) { + + fileOffset += 4; + + return GetLong(ifP); } + + static IC_Entry -readICEntry (void) -{ - IC_Entry entry; +readICEntry(FILE * const ifP) { + + IC_Entry entryP; - MALLOCVAR(entry); + MALLOCVAR(entryP); - if (entry == NULL) + if (entryP == NULL) pm_error("Unable to allcoate memory for IC entry"); - entry->width = readU1(); - entry->height = readU1(); - entry->color_count = readU1(); - entry->reserved = readU1(); - entry->planes = readU2(); - entry->bitcount = readU2(); - entry->size_in_bytes = readU4(); - entry->file_offset = readU4(); - entry->colors = NULL; - entry->ih = NULL; - entry->xorBitmap = NULL; - entry->andBitmap = NULL; + entryP->width = readU1(ifP); + entryP->height = readU1(ifP); + entryP->color_count = readU1(ifP); + entryP->reserved = readU1(ifP); + entryP->planes = readU2(ifP); + entryP->bitcount = readU2(ifP); + entryP->size_in_bytes = readU4(ifP); + entryP->file_offset = readU4(ifP); + entryP->colors = NULL; + entryP->ih = NULL; + entryP->xorBitmap = NULL; + entryP->andBitmap = NULL; - return entry; + return entryP; } static IC_InfoHeader -readInfoHeader (IC_Entry entry) -{ - IC_InfoHeader ih; +readInfoHeader (FILE * const ifP, + IC_Entry const entryP) { + + IC_InfoHeader ihP; - MALLOCVAR(ih); + MALLOCVAR(ihP); - if (ih == NULL) + if (ihP == NULL) pm_error("Unable to allocate memory for info header"); - ih->size = readU4(); - ih->width = readU4(); - ih->height = readU4(); - ih->planes = readU2(); - ih->bitcount = readU2(); - ih->compression = readU4(); - ih->imagesize = readU4(); - ih->x_pixels_per_m = readU4(); - ih->y_pixels_per_m = readU4(); - ih->colors_used = readU4(); - ih->colors_important = readU4(); + ihP->size = readU4(ifP); + ihP->width = readU4(ifP); + ihP->height = readU4(ifP); + ihP->planes = readU2(ifP); + ihP->bitcount = readU2(ifP); + ihP->compression = readU4(ifP); + ihP->imagesize = readU4(ifP); + ihP->x_pixels_per_m = readU4(ifP); + ihP->y_pixels_per_m = readU4(ifP); + ihP->colors_used = readU4(ifP); + ihP->colors_important = readU4(ifP); - if (!entry->bitcount) entry->bitcount = ih->bitcount; - if (entry->color_count == 0 && - entry->bitcount <= 8) entry->color_count = 256; - if (ih->compression) { + if (!entryP->bitcount) + entryP->bitcount = ihP->bitcount; + + if (entryP->color_count == 0 && entryP->bitcount <= 8) + entryP->color_count = 256; + + if (ihP->compression) { pm_error("Can't handle compressed icons"); } - return ih; + return ihP; } -/* - * I don't know why this isn't the same as the spec, it just <b>isn't</b> - * The colors honestly seem to be stored BGR. Bizarre. - * - * I've checked this in the BMP code for bmptoppm and the gimp. Guess the - * spec I have is just plain wrong. - */ + + static IC_Color -readICColor (void) -{ - IC_Color col; +readICColor(FILE * const ifP) { + + IC_Color colorP; - MALLOCVAR(col); + MALLOCVAR(colorP); - if (col == NULL) + if (colorP == NULL) pm_error("Unable to allocate memory for color"); - col->blue = readU1(); - col->green = readU1(); - col->red = readU1(); - col->reserved = readU1(); - return col; + /* I don't know why this isn't the same as the spec, it just isn't. + The colors honestly seem to be stored BGR. Bizarre. + + I've checked this in the BMP code for bmptoppm and the gimp. Guess the + spec I have is just plain wrong. + */ + + colorP->blue = readU1(ifP); + colorP->green = readU1(ifP); + colorP->red = readU1(ifP); + colorP->reserved = readU1(ifP); + + return colorP; } -/* - * Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the - * encoding mechanism is different. - * - * 8bpp => 1 byte/palette index. - * 4bpp => High Nibble, Low Nibble - * 1bpp => 1 palette value per bit, high bit 1st. - */ static u1 * -read1Bitmap (int width, int height) -{ - int tmp; - int xBytes; +read1Bitmap (FILE * const ifP, + unsigned int const width, + unsigned int const height) { + + unsigned int row; + unsigned int xByteCt; u1 * bitmap; - int wt = width; + unsigned int wt; MALLOCARRAY(bitmap, width * height); if (bitmap == NULL) pm_error("out of memory"); - wt >>= 3; - if (wt & 3) { - wt = (wt & ~3) + 4; + /* Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the + encoding mechanism is different. + + 8bpp => 1 byte/palette index. + 4bpp => High Nibble, Low Nibble + 1bpp => 1 palette value per bit, high bit 1st. + */ + + wt = width >> 3; + + if ((wt & 0x3) != 0) { + wt = (wt & ~0x3) + 4; } - xBytes = wt; - for (tmp = 0; tmp<height; tmp++ ) { - int x; - int rowByte = 0; - int xOrVal = 128; - u1 * row = readU1String(xBytes); - for (x = 0; x< width; x++) { - *(bitmap+((height-tmp-1)*width) + (x)) = - (row[rowByte] & xOrVal) / xOrVal; - if (xOrVal == 1) { - xOrVal = 128; - rowByte++; - } else { + xByteCt = wt; + + for (row = 0; row < height; ++row) { + u1 * const imgRow = readU1String(ifP, xByteCt); + + unsigned int col; + unsigned int rowByte; + unsigned int xOrVal; + + for (col = 0, rowByte = 0, xOrVal = 0x80; col < width; ++col) { + *(bitmap+((height - row - 1) * width) + col) = + (imgRow[rowByte] & xOrVal) / xOrVal; + if (xOrVal == 0x01) { + xOrVal = 0x80; + ++rowByte; + } else xOrVal >>= 1; - } } - free(row); + free(imgRow); } return bitmap; } @@ -324,43 +351,46 @@ read1Bitmap (int width, int height) static u1 * -read4Bitmap (int width, int height) -{ - int tmp; +read4Bitmap (FILE * const ifP, + unsigned int const width, + unsigned int const height) { + + unsigned int row; u1 * bitmap; - int wt = width; - int xBytes; + unsigned int wt; + unsigned int xByteCt; MALLOCARRAY(bitmap, width * height); if (bitmap == NULL) pm_error("out of memory"); + wt = width >> 1; - wt >>= 1; - if (wt & 3) { - wt = (wt & ~3) + 4; + if (wt & 0x3) { + wt = (wt & ~0x3) + 4; } - xBytes = wt; - for (tmp = 0; tmp<height ; tmp++ ) { - int rowByte = 0; - int bottom = 1; - int x; - u1 * row = readU1String(xBytes); - for (x = 0; x< width; x++) { - /* - * 2 nibbles, 2 values. - */ + xByteCt = wt; + + for (row = 0; row < height; ++row) { + u1 * const imgRow = readU1String(ifP, xByteCt); + + unsigned int rowByte; + bool bottom; + unsigned int col; + for (col = 0, rowByte = 0, bottom = true; col < width; ++col) { + /* 2 nibbles, 2 values */ if (bottom) { - *(bitmap+((height-tmp-1)*width) + (x)) = - (row[rowByte] & 0xF0) >> 4; + *(bitmap + ((height - row - 1) * width) + col) = + (imgRow[rowByte] & 0xF0) >> 4; } else { - *(bitmap+((height-tmp-1)*width) + (x)) = (row[rowByte] & 0xF); - rowByte++; + *(bitmap + ((height - row -1) * width) + col) = + (imgRow[rowByte] & 0xF); + ++rowByte; } bottom = !bottom; } - free(row); + free(imgRow); } return bitmap; } @@ -368,52 +398,57 @@ read4Bitmap (int width, int height) static u1 * -read8Bitmap (int width, int height) -{ - int tmp; - unsigned int xBytes; - unsigned int wt = width; +read8Bitmap (FILE * const ifP, + unsigned int const width, + unsigned int const height) { + + unsigned int row; + unsigned int xByteCt; + unsigned int wt; u1 * bitmap; MALLOCARRAY(bitmap, width * height); if (bitmap == NULL) pm_error("out of memory"); - if (wt & 3) { - wt = (wt & ~3) + 4; + wt = width; + if (wt & 0x3) { + wt = (wt & ~0x3) + 4; } - xBytes = wt; - for (tmp = 0; tmp<height ; tmp++ ) { - int rowByte = 0; - int x; - u1 * row = readU1String(xBytes); - for ( x = 0; x< width; x++) { - *(bitmap+((height-tmp-1)*width) + (x)) = row[rowByte]; - rowByte++; - } - free(row); + xByteCt = wt; + + for (row = 0; row < height; ++row) { + u1 * imgRow = readU1String(ifP, xByteCt); + + unsigned int rowByte; + unsigned int col; + for (col = 0, rowByte = 0; col < width; ++col) + *(bitmap + ((height - row - 1) * width) + col) = imgRow[rowByte++]; + + free(imgRow); } return bitmap; } -/* - * Read a true color bitmap. (24/32 bits) - * - * The output routine deplanarizes it for us, we keep it flat here. - */ static u1 * -readXBitmap (int const width, - int const height, - int const bpp) { - int const bytes = bpp >> 3; - unsigned int const xBytes = width * bytes; +readXBitmap (FILE * const ifP, + unsigned int const width, + unsigned int const height, + unsigned int const bpp) { +/*---------------------------------------------------------------------------- + Read a true color bitmap. (24/32 bits) + + The output routine deplanarizes it for us, we keep it flat here. +-----------------------------------------------------------------------------*/ + unsigned int const byteCt = bpp >> 3; + unsigned int const xByteCt = width * byteCt; u1 * bitmap; /* remember - bmp (dib) stored upside down, so reverse */ - MALLOCARRAY(bitmap, bytes * width * height); + MALLOCARRAY(bitmap, byteCt * width * height); if (bitmap == NULL) pm_error("out of memory allocating bitmap array"); @@ -421,12 +456,12 @@ readXBitmap (int const width, unsigned int i; u1 * bitcurptr; - for (i = 0, bitcurptr = &bitmap[bytes * width * (height-1)]; + for (i = 0, bitcurptr = &bitmap[byteCt * width * (height-1)]; i < height; - ++i, bitcurptr -= xBytes) { + ++i, bitcurptr -= xByteCt) { - u1 * const row = readU1String(xBytes); - memcpy(bitcurptr, row, xBytes); + u1 * const row = readU1String(ifP, xByteCt); + memcpy(bitcurptr, row, xByteCt); free(row); } } @@ -436,80 +471,70 @@ readXBitmap (int const width, static MS_Ico -readIconFile (bool const verbose) { - int iter,iter2; +readIconFile(FILE * const ifP, + bool const verbose) { + + unsigned int i; MS_Ico MSIconData; MALLOCVAR(MSIconData); - /* - * reserved - should equal 0. - */ - MSIconData->reserved = readU2(); - /* - * Type - should equal 1 - */ - MSIconData->type = readU2(); - /* - * count - no of icons in file.. - */ - MSIconData->count = readU2(); - /* - * Allocate "count" array of entries. - */ + MSIconData->reserved = readU2(ifP); /* should be 0 */ + MSIconData->type = readU2(ifP); /* should be 1 */ + MSIconData->count = readU2(ifP); /* # icons in file */ + if (verbose) pm_message("Icon file contains %d icons.", MSIconData->count); MALLOCARRAY(MSIconData->entries, MSIconData->count); if (MSIconData->entries == NULL) pm_error("out of memory"); - /* - * Read in each of the entries - */ - for (iter = 0;iter < MSIconData->count ; iter++ ) { - MSIconData->entries[iter] = readICEntry(); - } - /* After that, we have to read in the infoheader, color map (if - * any) and the actual bit/pix maps for the icons. - */ + + /* Read in each of the entries */ + for (i = 0; i < MSIconData->count; ++i) + MSIconData->entries[i] = readICEntry(ifP); + + /* Read in the infoheader, color map (if any) and the actual bit/pix maps + for the icons. + */ if (verbose) - fprintf (stderr,"#\tColors\tBPP\tWidth\tHeight\n"); - for (iter = 0;iter < MSIconData->count ; iter++ ) { - int bpp; - MSIconData->entries[iter]->ih = - readInfoHeader (MSIconData->entries[iter]); + pm_message("#\tColors\tBPP\tWidth\tHeight\n"); + + for (i = 0; i < MSIconData->count; ++i) { + unsigned int bpp; /* bits per pixel */ + + MSIconData->entries[i]->ih = + readInfoHeader(ifP, MSIconData->entries[i]); - /* What's the bits per pixel? */ - bpp = MSIconData->entries[iter]->bitcount; + bpp = MSIconData->entries[i]->bitcount; + /* Read the palette, if appropriate */ switch (bpp) { case 24: case 32: /* 24/32 bpp icon has no palette */ break; - default: - MALLOCARRAY(MSIconData->entries[iter]->colors, - MSIconData->entries[iter]->color_count); - if (MSIconData->entries[iter]->colors == NULL) + default: { + unsigned int j; + + MALLOCARRAY(MSIconData->entries[i]->colors, + MSIconData->entries[i]->color_count); + if (MSIconData->entries[i]->colors == NULL) pm_error("out of memory"); - for (iter2 = 0; - iter2 < MSIconData->entries[iter]->color_count ; - iter2++ ) { - MSIconData->entries[iter]->colors[iter2] = readICColor(); - } - break; + for (j = 0; j < MSIconData->entries[i]->color_count; ++j) + MSIconData->entries[i]->colors[j] = readICColor(ifP); + } } if (verbose) { - char cols_text[10]; - sprintf (cols_text, "%d", MSIconData->entries[iter]->color_count); - fprintf (stderr, - "%d\t%s\t%d\t%d\t%d\n", iter, - MSIconData->entries[iter]->color_count ? - cols_text : "TRUE", - bpp, MSIconData->entries[iter]->width, - MSIconData->entries[iter]->height); + char colsText[10]; + sprintf (colsText, "%d", MSIconData->entries[i]->color_count); + pm_message("%d\t%s\t%d\t%d\t%d\n", i, + MSIconData->entries[i]->color_count ? + colsText : "TRUE", + bpp, MSIconData->entries[i]->width, + MSIconData->entries[i]->height); } /* Pixels are stored bottom-up, left-to-right. Pixel lines are * padded with zeros to end on a 32bit (4byte) boundary. Every @@ -528,35 +553,40 @@ readIconFile (bool const verbose) { */ switch (bpp) { case 1: - MSIconData->entries[iter]->xorBitmap = - read1Bitmap(MSIconData->entries[iter]->width, - MSIconData->entries[iter]->height); + MSIconData->entries[i]->xorBitmap = + read1Bitmap(ifP, + MSIconData->entries[i]->width, + MSIconData->entries[i]->height); break; case 4: - MSIconData->entries[iter]->xorBitmap = - read4Bitmap(MSIconData->entries[iter]->width, - MSIconData->entries[iter]->height); + MSIconData->entries[i]->xorBitmap = + read4Bitmap(ifP, + MSIconData->entries[i]->width, + MSIconData->entries[i]->height); break; case 8: - MSIconData->entries[iter]->xorBitmap = - read8Bitmap(MSIconData->entries[iter]->width, - MSIconData->entries[iter]->height); + MSIconData->entries[i]->xorBitmap = + read8Bitmap(ifP, + MSIconData->entries[i]->width, + MSIconData->entries[i]->height); break; case 24: case 32: - MSIconData->entries[iter]->xorBitmap = - readXBitmap(MSIconData->entries[iter]->width, - MSIconData->entries[iter]->height,bpp); + MSIconData->entries[i]->xorBitmap = + readXBitmap(ifP, + MSIconData->entries[i]->width, + MSIconData->entries[i]->height,bpp); break; default: - pm_error("Uncatered bit depth %d",bpp); + pm_error("Uncatered bit depth %u", bpp); } /* * Read AND Bitmap */ - MSIconData->entries[iter]->andBitmap = - read1Bitmap(MSIconData->entries[iter]->width, - MSIconData->entries[iter]->height); + MSIconData->entries[i]->andBitmap = + read1Bitmap(ifP, + MSIconData->entries[i]->width, + MSIconData->entries[i]->height); } } @@ -566,15 +596,14 @@ readIconFile (bool const verbose) { static char * -trimOutputName(const char inputName[]) -{ +trimmedOutputName(const char inputName[]) { /* * Just trim off the final ".ppm", if there is one, else return as is. * oh, for =~ ... :) */ - char * outFile = strdup(inputName); - if (streq(outFile + (strlen (outFile) - 4), ".ppm")) { - *(outFile + (strlen (outFile) - 4)) = 0; + char * const outFile = strdup(inputName); + if (streq(outFile + (strlen(outFile) - 4), ".ppm")) { + *(outFile + (strlen(outFile) - 4)) = 0; } return outFile; @@ -585,29 +614,34 @@ trimOutputName(const char inputName[]) static int getBestQualityIcon(MS_Ico MSIconData) { - int x,best,best_size,best_bpp,bpp,size; - IC_Entry entry; - - best_size = best_bpp = 0; - for (x = 0; x < MSIconData->count; x++) { - entry = MSIconData->entries[x]; - size = entry->width * entry->height; - bpp = entry->bitcount ? entry->bitcount : entry->ih->bitcount; - if (size > best_size) { - best = x; - best_size = size; - } else if (size == best_size && bpp > best_bpp) { - best = x; - best_bpp = bpp; + unsigned int i; + unsigned int best; + unsigned int bestSize; + unsigned int bestBpp; + + for (i = 0, bestSize = 0, bestBpp = 0; i < MSIconData->count; ++i) { + IC_Entry const entryP = MSIconData->entries[i]; + unsigned int const size = entryP->width * entryP->height; + unsigned int const bpp = + entryP->bitcount ? entryP->bitcount : entryP->ih->bitcount; + + if (size > bestSize) { + best = i; + bestSize = size; + } else if (size == bestSize && bpp > bestBpp) { + best = i; + bestBpp = bpp; } } return best; } + + static void writeXors(FILE * const multiOutF, - char outputFileBase[], - IC_Entry const entry, + char * const outputFileBase, + IC_Entry const entryP, int const entryNum, bool const multiple, bool const xor) { @@ -625,85 +659,79 @@ writeXors(FILE * const multiOutF, we are to open a file using outputFileBase[] and 'entryNum' and 'xor' to derive its name, and close it afterward. -----------------------------------------------------------------------------*/ - FILE * outF; - pixel ** ppm_array; - int row; - int pel_size; - const char *outputFile; - int maxval; - int forcetext; + FILE * ofP; + pixel ** pixArray; + unsigned int row; + const char * outputFileName; if (multiOutF) { - outF = multiOutF; - outputFile = strdup(""); + ofP = multiOutF; + outputFileName = strdup(""); } else { if (outputFileBase) { if (multiple) { - asprintfN(&outputFile, "%s%s_%d.ppm", - outputFileBase,(xor ? "_xor" : ""), entryNum); + pm_asprintf(&outputFileName, "%s%s_%d.ppm", + outputFileBase,(xor ? "_xor" : ""), entryNum); } else { - asprintfN(&outputFile, "%s%s.ppm", - outputFileBase,(xor ? "_xor" : "")); + pm_asprintf(&outputFileName, "%s%s.ppm", + outputFileBase,(xor ? "_xor" : "")); } } else - outputFile = strdup("-"); + outputFileName = strdup("-"); - outF = pm_openw(outputFile); + ofP = pm_openw(outputFileName); } /* - * allocate an array to save the bmp data into. - * note that entry->height will be 1/2 entry->ih->height, - * as the latter adds "and" and "xor" height. - */ - ppm_array = ppm_allocarray(entry->width, entry->height); - for (row=0; row < entry->height; row++) { - u1 * xorRow; - int col; - switch (entry->bitcount) { + Allocate an array to save the bmp data into. + note that entry->height will be 1/2 entry->ih->height, + as the latter adds "and" and "xor" height. + */ + pixArray = ppm_allocarray(entryP->width, entryP->height); + for (row = 0; row < entryP->height; ++row) { + switch (entryP->bitcount) { case 24: - case 32: - pel_size = entry->bitcount >> 3; - xorRow = entry->xorBitmap + row * entry->width * pel_size; - for (col=0; col < entry->width*pel_size;col+=pel_size) { - PPM_ASSIGN(ppm_array[row][col/pel_size], - xorRow[col+2],xorRow[col+1],xorRow[col]); - } - break; - default: - xorRow = entry->xorBitmap + row * entry->width; - for (col=0; col < entry->width; col++) { - int colorIndex; - IC_Color color; - colorIndex = xorRow[col]; - color = entry->colors[colorIndex]; - PPM_ASSIGN(ppm_array[row][col], - color->red,color->green,color->blue); + case 32: { + unsigned int const pixelSize = entryP->bitcount >> 3; + u1 * const xorRow = + entryP->xorBitmap + row * entryP->width * pixelSize; + unsigned int col; + for (col = 0; col < entryP->width * pixelSize; col += pixelSize) + PPM_ASSIGN(pixArray[row][col/pixelSize], + xorRow[col+2], xorRow[col+1], xorRow[col]); + } break; + default: { + u1 * const xorRow = entryP->xorBitmap + row * entryP->width; + unsigned int col; + for (col = 0; col < entryP->width; ++col) { + unsigned int const colorIndex = xorRow[col]; + IC_Color const colorP = entryP->colors[colorIndex]; + PPM_ASSIGN(pixArray[row][col], + colorP->red, colorP->green, colorP->blue); } - break; + } break; } } - maxval = 255; - forcetext = 0; - - ppm_writeppm(outF,ppm_array,entry->width, entry->height, - (pixval) maxval, forcetext); - ppm_freearray(ppm_array,entry->height); + ppm_writeppm(ofP, pixArray, entryP->width, entryP->height, + 255 /* maxval */, false /* text */); + ppm_freearray(pixArray, entryP->height); - strfree(outputFile); + pm_strfree(outputFileName); if (!multiOutF) - pm_close(outF); + pm_close(ofP); } static void -writeAnds(FILE * const multiOutF, - char outputFileBase[], IC_Entry const entry, int const entryNum, - bool multiple) { +writeAnds(FILE * const multiOutF, + char const outputFileBase[], + IC_Entry const entryP, + unsigned int const entryNum, + bool const multiple) { /*---------------------------------------------------------------------------- - Write the "and" image (i.e. the alpha mask) of the image 'IC_Entry' out. + Write the "and" image (i.e. the alpha mask) of the image *entryP out. 'multiple' means this is one of multiple images that are being written. 'entryNum' is the sequence number within the winicon file of the image @@ -714,114 +742,122 @@ writeAnds(FILE * const multiOutF, we are to open a file using outputFileBase[] and 'entryNum' and 'xor' to derive its name, and close it afterward. -----------------------------------------------------------------------------*/ - FILE * outF; - bit ** pbm_array; - u1 * andRow; - int row; + FILE * ofP; + bit ** bitArray; + unsigned int row; if (multiOutF) - outF = multiOutF; + ofP = multiOutF; else { - const char *outputFile; + const char * outputFileName; assert(outputFileBase); if (multiple) - asprintfN(&outputFile, "%s_and_%d.pbm", outputFileBase, entryNum); + pm_asprintf(&outputFileName, "%s_and_%u.pbm", + outputFileBase, entryNum); else - asprintfN(&outputFile, "%s_and.pbm", outputFileBase); - outF = pm_openw(outputFile); - strfree(outputFile); + pm_asprintf(&outputFileName, "%s_and.pbm", outputFileBase); + ofP = pm_openw(outputFileName); + pm_strfree(outputFileName); } - pbm_array = pbm_allocarray(entry->width, entry->height); - for (row=0; row < entry->height; row++) { - int col; - andRow = entry->andBitmap + row * entry->width; - for (col=0; col < entry->width; col++) { + bitArray = pbm_allocarray(entryP->width, entryP->height); + for (row = 0; row < entryP->height; ++row) { + u1 * const andRow = entryP->andBitmap + row * entryP->width; + unsigned int col; + for (col = 0; col < entryP->width; ++col) { /* Note: black is transparent in a Netpbm alpha mask */ - pbm_array[row][col] = andRow[col] ? PBM_BLACK: PBM_WHITE; + bitArray[row][col] = andRow[col] ? PBM_BLACK: PBM_WHITE; } } - pbm_writepbm(outF, pbm_array, entry->width, entry->height, 0); + pbm_writepbm(ofP, bitArray, entryP->width, entryP->height, 0); - pbm_freearray(pbm_array, entry->height); + pbm_freearray(bitArray, entryP->height); if (!multiOutF) - pm_close (outF); + pm_close(ofP); } static void -openMultiXor(char outputFileBase[], +openMultiXor(char const outputFileBase[], bool const writeands, FILE ** const multiOutFP) { - const char *outputFile; + const char * outputFileName; if (outputFileBase) { - asprintfN(&outputFile, "%s%s.ppm", - outputFileBase, (writeands ? "_xor" : "")); + pm_asprintf(&outputFileName, "%s%s.ppm", + outputFileBase, (writeands ? "_xor" : "")); } else - outputFile = strdup("-"); + outputFileName = strdup("-"); - /* - * Open the output file now, it'll stay open the whole time. - */ - *multiOutFP = pm_openw(outputFile); + *multiOutFP = pm_openw(outputFileName); - strfree(outputFile); + pm_strfree(outputFileName); } static void -openMultiAnd(char outputFileBase[], FILE ** const multiAndOutFP) { +openMultiAnd(char const outputFileBase[], + FILE ** const multiAndOutFP) { - const char *outputFile; + const char * outputFileName; assert(outputFileBase); - asprintfN(&outputFile, "%s_and.pbm", outputFileBase); + pm_asprintf(&outputFileName, "%s_and.pbm", outputFileBase); - *multiAndOutFP = pm_openw(outputFile); + *multiAndOutFP = pm_openw(outputFileName); - strfree(outputFile); + pm_strfree(outputFileName); } -static void free_iconentry(IC_Entry entry) { - int x; - if (entry->colors && entry->color_count) { - for (x=0;x<entry->color_count;x++) free(entry->colors[x]); - free(entry->colors); + + +static void +freeIconentry(IC_Entry const entryP) { + + if (entryP->colors && entryP->color_count) { + unsigned int i; + for (i = 0; i <entryP->color_count; ++i) + free(entryP->colors[i]); + free(entryP->colors); } - if (entry->andBitmap) free(entry->andBitmap); - if (entry->xorBitmap) free(entry->xorBitmap); - if (entry->ih) free(entry->ih); - free(entry); + if (entryP->andBitmap) free(entryP->andBitmap); + if (entryP->xorBitmap) free(entryP->xorBitmap); + if (entryP->ih) free(entryP->ih); + free(entryP); } -static void free_icondata(MS_Ico MSIconData) -{ - int x; - for (x=0;x<MSIconData->count;x++) { - free_iconentry(MSIconData->entries[x]); - } - free(MSIconData); + + +static void +freeIcondata(MS_Ico const MSIconDataP) { + + unsigned int i; + for (i = 0; i < MSIconDataP->count; ++i) + freeIconentry(MSIconDataP->entries[i]); + + free(MSIconDataP); } + int -main(int argc, char *argv[]) { +main(int argc, const char *argv[]) { struct cmdlineInfo cmdline; - int startEntry, endEntry; - MS_Ico MSIconData; + FILE * ifP; + unsigned int startEntry, endEntry; + MS_Ico MSIconDataP; char * outputFileBase; FILE * multiOutF; FILE * multiAndOutF; - ppm_init (&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -832,13 +868,13 @@ main(int argc, char *argv[]) { if (streq(cmdline.outputFilespec, "-")) outputFileBase = NULL; else - outputFileBase = trimOutputName(cmdline.outputFilespec); + outputFileBase = trimmedOutputName(cmdline.outputFilespec); - ifp = pm_openr(cmdline.inputFilespec); + ifP = pm_openr(cmdline.inputFilespec); infname = cmdline.inputFilespec; - MSIconData = readIconFile(cmdline.verbose); + MSIconDataP = readIconFile(ifP, cmdline.verbose); /* * Now we've read the icon file in (Hopefully! :) * Go through each of the entries, and write out files of the @@ -852,18 +888,15 @@ main(int argc, char *argv[]) { /* * If allicons is set, we want everything, if not, just go through once. */ - startEntry = 0; - if (cmdline.allicons) { - endEntry = MSIconData->count; - } else { - endEntry = 1; - } - /* - * If bestqual is set, find the icon with highest size & bpp. - */ if (cmdline.bestqual) { - startEntry = getBestQualityIcon(MSIconData); + startEntry = getBestQualityIcon(MSIconDataP); endEntry = startEntry+1; + } else { + startEntry = 0; + if (cmdline.allicons) + endEntry = MSIconDataP->count; + else + endEntry = 1; } if (cmdline.multippm) @@ -877,24 +910,25 @@ main(int argc, char *argv[]) { multiAndOutF = NULL; { - int entryNum; + unsigned int entryNum; - for (entryNum = startEntry ; entryNum < endEntry ; entryNum++ ) { - IC_Entry const entry = MSIconData->entries[entryNum]; + for (entryNum = startEntry; entryNum < endEntry; ++entryNum) { + IC_Entry const entryP = MSIconDataP->entries[entryNum]; - writeXors(multiOutF, outputFileBase, entry, entryNum, + writeXors(multiOutF, outputFileBase, entryP, entryNum, cmdline.allicons, cmdline.writeands); if (cmdline.writeands) writeAnds(multiAndOutF, outputFileBase, - entry, entryNum, cmdline.allicons); + entryP, entryNum, cmdline.allicons); } } if (multiOutF) - pm_close (multiOutF); + pm_close(multiOutF); if (multiAndOutF) pm_close(multiAndOutF); /* free up the image data here. */ - free_icondata(MSIconData); + freeIcondata(MSIconDataP); + return 0; } diff --git a/converter/ppm/xim.h b/converter/ppm/xim.h index ffe60fb6..27556b30 100644 --- a/converter/ppm/xim.h +++ b/converter/ppm/xim.h @@ -112,7 +112,7 @@ typedef struct XimAsciiHeader { /* Note: * - All data is in char's in order to maintain easily portability * across machines, and some human readibility. -* - Images may be stored as pixmaps (8 bits/pixel) or as seperate +* - Images may be stored as pixmaps (8 bits/pixel) or as separate * red, green, blue channel data (24+ bits/pixel). * - An alpha channel is optional and is found after every num_channels * of data. diff --git a/converter/ppm/ximtoppm.c b/converter/ppm/ximtoppm.c index 15589c16..ce5e6396 100644 --- a/converter/ppm/ximtoppm.c +++ b/converter/ppm/ximtoppm.c @@ -56,7 +56,7 @@ parseCommandLine(int argc, char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and all of *cmdlineP. */ if (!alphaoutSpec) @@ -208,7 +208,7 @@ ReadImageChannel(FILE * const infp, } marker += i; } - /* return to the begining of the next image's bufffer */ + /* return to the beginning of the next image's bufffer */ if (fseek(infp, marker, 0) == -1) { pm_message("ReadImageChannel: can't fseek to location in image buffer" ); return(0); diff --git a/converter/ppm/xpmtoppm.c b/converter/ppm/xpmtoppm.c index 235c3867..27f17931 100644 --- a/converter/ppm/xpmtoppm.c +++ b/converter/ppm/xpmtoppm.c @@ -1,43 +1,19 @@ -/* xpmtoppm.c - read an X11 pixmap file and produce a portable pixmap -** -** Copyright (C) 1991 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. -** -** Upgraded to handle XPM version 3 by -** Arnaud Le Hors (lehors@mirsa.inria.fr) -** Tue Apr 9 1991 -** -** Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91: -** - Bug fix, no advance of read ptr, would not read -** colors like "ac c black" because it would find -** the "c" of "ac" and then had problems with "c" -** as color. -** -** - Now understands multiword X11 color names -** -** - Now reads multiple color keys. Takes the color -** of the hightest available key. Lines no longer need -** to begin with key 'c'. -** -** - expanded line buffer to from 500 to 2048 for bigger files +/* xpmtoppm.c - convert XPM file (X11 pixmap) to PPM + + Copyright and history information is at end of file */ #define _BSD_SOURCE /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ +#include <assert.h> #include <string.h> #include "pm_c_util.h" -#include "ppm.h" +#include "mallocvar.h" #include "shhopt.h" #include "nstring.h" -#include "mallocvar.h" +#include "ppm.h" #define MAX_LINE (8 * 1024) /* The maximum size XPM input line we can handle. */ @@ -47,72 +23,321 @@ const char *xpmColorKeys[] = { - "s", /* key #1: symbol */ - "m", /* key #2: mono visual */ - "g4", /* key #3: 4 grays visual */ - "g", /* key #4: gray visual */ - "c", /* key #5: color visual */ + "s", /* key #1: symbol */ + "m", /* key #2: mono visual */ + "g4", /* key #3: 4 grays visual */ + "g", /* key #4: gray visual */ + "c", /* key #5: color visual */ }; -struct cmdline_info { +struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - char *input_filespec; /* Filespecs of input files */ - char *alpha_filename; + const char * input_filespec; /* Filespecs of input files */ + const char * alpha_filename; int alpha_stdout; int verbose; }; -static int verbose; +static bool verbose; + static void -parse_command_line(int argc, char ** argv, - struct cmdline_info *cmdline_p) { +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo *cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. -----------------------------------------------------------------------------*/ - optStruct *option_def = malloc(100*sizeof(optStruct)); + optEntry * option_def; /* Instructions to OptParseOptions2 on how to parse our options. */ - optStruct2 opt; + optStruct3 opt; unsigned int option_def_index; - option_def_index = 0; /* incremented by OPTENTRY */ - OPTENTRY(0, "alphaout", OPT_STRING, &cmdline_p->alpha_filename, 0); - OPTENTRY(0, "verbose", OPT_FLAG, &cmdline_p->verbose, 0); + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "alphaout", OPT_STRING, &cmdlineP->alpha_filename, + NULL, 0); + OPTENT3(0, "verbose", OPT_FLAG, &cmdlineP->verbose, + NULL, 0); - cmdline_p->alpha_filename = NULL; - cmdline_p->verbose = FALSE; + cmdlineP->alpha_filename = NULL; + cmdlineP->verbose = FALSE; opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = TRUE; /* We may have parms that are negative numbers */ - optParseOptions2(&argc, argv, opt, 0); - /* Uses and sets argc, argv, and some of *cmdline_p and others. */ + pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (argc - 1 == 0) - cmdline_p->input_filespec = NULL; /* he wants stdin */ + cmdlineP->input_filespec = NULL; /* he wants stdin */ else if (argc - 1 == 1) - cmdline_p->input_filespec = strdup(argv[1]); + cmdlineP->input_filespec = strdup(argv[1]); else pm_error("Too many arguments. The only argument accepted\n" "is the input file specification"); - if (cmdline_p->alpha_filename && - streq(cmdline_p->alpha_filename, "-")) - cmdline_p->alpha_stdout = TRUE; + if (cmdlineP->alpha_filename && + streq(cmdlineP->alpha_filename, "-")) + cmdlineP->alpha_stdout = TRUE; else - cmdline_p->alpha_stdout = FALSE; + cmdlineP->alpha_stdout = FALSE; + +} + + + +struct ColorNameHashTableEntry { +/*---------------------------------------------------------------------------- + An entry in the color name hash table. It maps a color name to a + color, or is empty. +-----------------------------------------------------------------------------*/ + bool empty; + char colorName[3]; + /* Actual length 0-3. NOT NUL-terminated */ + pixel color; +}; + + + +typedef struct { +/*---------------------------------------------------------------------------- + This is a color map which is primarily a hash table that maps an XPM + color name to a color. An XPM color name is a 0-3 character name that + appears in the raster of an XPM image to uniquely identify a color. + The header of the XPM contains a listing of all the color names that + appear in the raster, identifying a color for each. + + We represent a color as a 'pixel'. +-----------------------------------------------------------------------------*/ + unsigned int nameSize; + /* Size of color names in this hash. 0-3 */ + struct ColorNameHashTableEntry * transparentP; + /* The element of 'table' that is for the transparent color. + NULL if there is none. + */ + + /* This is an internally chained hash table, i.e. there are no linked + lists. You use the hash function to get an index into the hash table. + If the entry indexed by that is not for the color name you're looking + for, you look at the next entry down, and keep going down until you + either find the color name you're looking for or hit an empty entry. + + So that we never run out of space for new color names, we make the + creator of the hash table tell us the maximum number of colors there + will be. We allocate twice that size in order to reduce average hash + chain length. + */ + unsigned int size; + struct ColorNameHashTableEntry * table; +} ColorNameHash; + + + +static ColorNameHash * +hash_create(unsigned int const nColors, + unsigned int const nameSize) { + + ColorNameHash * hashP; + + MALLOCVAR_NOFAIL(hashP); + + hashP->nameSize = nameSize; + + hashP->size = nColors * 2; + + MALLOCARRAY(hashP->table, hashP->size); + + if (!hashP->table) + pm_error("Failed to allocate memory for a %u-entry " + "color name hash table.", hashP->size); + + { + unsigned int i; + for (i = 0; i < hashP->size; ++i) + hashP->table[i].empty = true; + } + + hashP->transparentP = NULL; + + return hashP; +} + + + +static void +hash_destroy(ColorNameHash * const hashP) { + + free(hashP->table); + + free(hashP); +} + + + +static unsigned int +hashColorName(const char * const name, + unsigned int const size, + unsigned int const hashTableSize) { +/*---------------------------------------------------------------------------- + Return the hash value (initial index into the color name hash table) + for the color name 'name', which is 'size' characters long. The hash + is to be in the range [0, hashTableSize). +-----------------------------------------------------------------------------*/ + /* I have no idea if this is an appropriate hash function. I borrowed + it from pnm_hashTuple() + */ + + unsigned int const hash_factor[] = {1, 33, 33*33}; + + unsigned int i; + unsigned int hash; + hash = 0; /* initial value */ + for (i = 0; i < size; ++i) { + hash += name[i] * hash_factor[i]; + } + hash %= hashTableSize; + return hash; +} + + + +static bool +entryMatch(struct ColorNameHashTableEntry const entry, + const char * const name, + unsigned int const size) { + + if (entry.empty) + return true; + + assert(size <= ARRAY_SIZE(entry.colorName)); + + { + unsigned int i; + + for (i = 0; i < size; ++i) { + if (name[i] != entry.colorName[i]) + return false; + } + } + + return true; +} + + + +static void +bumpIndex(unsigned int * const indexP, + unsigned int const tableSize, + unsigned int const limit) { +/*---------------------------------------------------------------------------- + Bump *indexP to the next entry in a table of size 'tableSize', in a + circular fashion. But abort the program if this would take us to + 'limit'. +-----------------------------------------------------------------------------*/ + *indexP += 1; + if (*indexP >= tableSize) + *indexP = 0; + + if (*indexP == limit) + pm_error("INTERNAL ERROR: color name hash table is full"); +} + + + +static void +hash_find(const ColorNameHash * const hashP, + const char * const name, + struct ColorNameHashTableEntry ** const entryPP) { +/*---------------------------------------------------------------------------- + Find the entry in the color hash table *hashP for the color + named 'name' in the lexicon of this XPM file. If the color is in the + table, this is where it is. If it isn't, this is where it should go. +-----------------------------------------------------------------------------*/ + unsigned int const initialIndex = + hashColorName(name, hashP->nameSize, hashP->size); + + unsigned int i; + + for (i = initialIndex; + !entryMatch(hashP->table[i], name, hashP->nameSize); + bumpIndex(&i, hashP->size, initialIndex)); + + *entryPP = &hashP->table[i]; } + +static void +hash_add(ColorNameHash * const hashP, + const char * const name, + pixel const color, + bool const isTransparent) { + + struct ColorNameHashTableEntry * entryP; + + hash_find(hashP, name, &entryP); + + if (!entryP->empty) + pm_error("Color name appears multiple times in color map"); + + entryP->empty = false; + { + unsigned int i; + for (i = 0; i < hashP->nameSize; ++i) + entryP->colorName[i] = name[i]; + } + entryP->color = color; + + if (isTransparent) { + if (hashP->transparentP) + pm_error("There are multiple NONE (transparent) entries in " + "the XPM color map"); + else + hashP->transparentP = entryP; + } +} + + + +static pixel +hash_color(const ColorNameHash * const hashP, + const char * const name) { + + struct ColorNameHashTableEntry * entryP; + + hash_find(hashP, name, &entryP); + + if (entryP->empty) + pm_error("Color name in raster is not in color map"); + + return entryP->color; +} + + + +static bool +hash_isTransparent(const ColorNameHash * const hashP, + const char * const name) { + + struct ColorNameHashTableEntry * entryP; + + hash_find(hashP, name, &entryP); + + return (entryP == hashP->transparentP); +} + + + static char lastInputLine[MAX_LINE+1]; /* contents of line most recently read from input */ static bool backup; @@ -121,6 +346,7 @@ static bool backup; */ + static void getLine(char * const line, size_t const size, @@ -158,21 +384,6 @@ getLine(char * const line, -static unsigned int -getNumber(char * const p, unsigned int const size) { - - unsigned int retval; - unsigned char * q; - - retval = 0; - for (q = p; q < p+size; ++q) - retval = (retval << 8) + *q; - - return retval; -} - - - static void getword(char * const output, char ** const cursorP) { @@ -191,90 +402,97 @@ getword(char * const output, char ** const cursorP) { static void -addToColorMap(unsigned int const seqNum, - unsigned int const colorNumber, - pixel * const colors, int * const ptab, - char colorspec[], int const isTransparent, - int * const transparentP) { +addToColorMap(ColorNameHash * const hashP, + const char * const colorName, + char const colorspec[], + bool const isTransparent) { /*---------------------------------------------------------------------------- - Add the color named by colorspec[] to the colormap contained in - 'colors' and 'ptab', as the color associated with XPM color number - 'colorNumber', which is the seqNum'th color in the XPM color map. + Add the color named by colorspec[] to the colormap represented by *hashP, + as the color associated with XPM color name 'colorNumber'. - Iff 'transparent', set *transparentP to the colormap index that - corresponds to this color. + Note that *hashP determines how long 'colorName' is. -----------------------------------------------------------------------------*/ - if (ptab == NULL) { - /* Index into table. */ - colors[colorNumber] = ppm_parsecolor(colorspec, - (pixval) PPM_MAXMAXVAL); - if (isTransparent) - *transparentP = colorNumber; - } else { - /* Set up linear search table. */ - colors[seqNum] = ppm_parsecolor(colorspec, - (pixval) PPM_MAXMAXVAL); - ptab[seqNum] = colorNumber; - if (isTransparent) - *transparentP = seqNum; + hash_add(hashP, colorName, ppm_parsecolor(colorspec, PPM_MAXMAXVAL), + isTransparent); +} + + + +static void +validateColorName(const char * const name, + unsigned int const charsPerPixel) { + + unsigned int i; + + for (i = 0; i < charsPerPixel; ++i) { + if (name[i] == '"') + pm_error("A color map entry ends in the middle of the colormap " + "index"); + else if (name[i] == '\0') + pm_error("The XPM file ends in the middle of a color map entry"); } } static void -interpretXpm3ColorTableLine(char line[], int const seqNum, - int const chars_per_pixel, - pixel * const colors, int * const ptab, - int * const transparentP) { +interpretXpm3ColorTableLine(char const line[], + unsigned int const seqNum, + unsigned int const charsPerPixel, + ColorNameHash * const hashP) { /*---------------------------------------------------------------------------- - Interpret one line of the color table in the XPM header. 'line' is - the line from the XPM file. It is the seqNum'th color table entry in - the file. The file uses 'chars_per_pixel' characters per pixel. + Interpret one line of the color table in the XPM header. 'line' is the + line from the XPM file. It is the seqNum'th color table entry in the file. + The raster in the file uses 'charsPerPixel' characters per pixel (i.e. + a an XPM color name is 'charsPerPixel' characters). - Add the information from this color table entry to the color table - 'colors' and, if it isn't NULL, the corresponding lookup shadow table - 'ptab' (see readXpm3ColorTable for a description of these data - structures). + Add the information from this color table entry to the color name hash + *hashP. The line may include values for multiple kinds of color (grayscale, color, etc.). We take the highest of these (e.g. color over grayscale). If a color table entry indicates transparency, set *transparentP - to the colormap index that corresponds to the indicated color. + to indicate the XPM color name. -----------------------------------------------------------------------------*/ /* Note: this code seems to allow for multi-word color specifications, but I'm not aware that such are legal. Ultimately, ppm_parsecolor() - interprets the name, and I believe it only takes single word + interprets the name, and I believe it takes only single word color specifications. -Bryan 2001.05.06. */ char str2[MAX_LINE+1]; - char *t1; - char *t2; + char * t1; + char * t2; int endOfEntry; /* boolean */ - unsigned int curkey, key, highkey; /* current color key */ - unsigned int lastwaskey; + unsigned int curkey, key, highkey; /* current color key */ + bool lastwaskey; /* The last token we processes was a key, and we have processed at least one token. */ - char curbuf[BUFSIZ]; /* current buffer */ - int isTransparent; + char curbuf[BUFSIZ]; /* current buffer */ + bool isTransparent; - int colorNumber; - /* A color number that appears in the raster */ + const char * colorName; + /* The 0-3 character name this color map line gives the color + (i.e. the name that the raster uses). This is NOT NUL-terminated. + It's length is bytesPerPixel. + */ + /* read the chars */ t1 = strchr(line, '"'); if (t1 == NULL) pm_error("A line that is supposed to be an entry in the color " "table does not start with a quote. The line is '%s'. " - "It is the %dth entry in the color table.", + "It is the %uth entry in the color table.", line, seqNum); else - t1++; /* Points now to first color number character */ + ++t1; /* Points now to first color number character */ + + validateColorName(t1, charsPerPixel); + colorName = t1; - colorNumber = getNumber(t1, chars_per_pixel); - t1 += chars_per_pixel; + t1 += charsPerPixel; /* * read color keys and values @@ -306,30 +524,30 @@ interpretXpm3ColorTableLine(char line[], int const seqNum, pm_error("Missing color key token in color table line " "'%s' before '%s'.", line, str2); if (!lastwaskey) - strcat(curbuf, " "); /* append space */ - if ( (strncmp(str2, "None", 4) == 0) - || (strncmp(str2, "none", 4) == 0) ) { + strcat(curbuf, " "); /* append space */ + if ( (strneq(str2, "None", 4)) + || (strneq(str2, "none", 4)) ) { /* This entry identifies the transparent color number */ strcat(curbuf, "#000000"); /* Make it black */ isTransparent = TRUE; } else - strcat(curbuf, str2); /* append buf */ - lastwaskey = 0; + strcat(curbuf, str2); /* append buf */ + lastwaskey = FALSE; } else { /* This word is a key. So we've seen the last of the info for the previous key, and we must either put it in the color map or ignore it if we already have a higher color form in the colormap for this colormap entry. */ - if (curkey > highkey) { /* flush string */ - addToColorMap(seqNum, colorNumber, colors, ptab, curbuf, - isTransparent, transparentP); + if (curkey > highkey) { /* flush string */ + addToColorMap(hashP, colorName, curbuf, isTransparent); highkey = curkey; } - curkey = key; /* set new key */ - curbuf[0] = '\0'; /* reset curbuf */ + /* intialize state to process this new key */ + curkey = key; + curbuf[0] = '\0'; isTransparent = FALSE; - lastwaskey = 1; + lastwaskey = TRUE; } if (*t2 == '"') break; } @@ -339,8 +557,7 @@ interpretXpm3ColorTableLine(char line[], int const seqNum, entry in it) */ if (curkey > highkey) { - addToColorMap(seqNum, colorNumber, colors, ptab, curbuf, - isTransparent, transparentP); + addToColorMap(hashP, colorName, curbuf, isTransparent); highkey = curkey; } if (highkey == 1) @@ -350,152 +567,208 @@ interpretXpm3ColorTableLine(char line[], int const seqNum, static void -readXpm3Header(FILE * const stream, int * const widthP, int * const heightP, - int * const chars_per_pixelP, int * const ncolorsP, - pixel ** const colorsP, int ** const ptabP, - int * const transparentP) { +readV3ColorTable(FILE * const ifP, + ColorNameHash ** const colorNameHashPP, + unsigned int const nColors, + unsigned int const charsPerPixel) { /*---------------------------------------------------------------------------- - Read the header of the XPM file on stream 'stream'. Assume the + Read the color table from the XPM Version 3 header. + + Assume *ifP is positioned to the color table; leave it positioned after. +-----------------------------------------------------------------------------*/ + ColorNameHash * const colorNameHashP = hash_create(nColors, charsPerPixel); + + unsigned int seqNum; + /* Sequence number of entry within color table in XPM header */ + + for (seqNum = 0; seqNum < nColors; ++seqNum) { + char line[MAX_LINE+1]; + getLine(line, sizeof(line), ifP); + /* skip the comment line if any */ + if (strneq(line, "/*", 2)) + getLine(line, sizeof(line), ifP); + + interpretXpm3ColorTableLine(line, seqNum, charsPerPixel, + colorNameHashP); + + } + *colorNameHashPP = colorNameHashP; +} + + + +static void +readXpm3Header(FILE * const ifP, + unsigned int * const widthP, + unsigned int * const heightP, + unsigned int * const charsPerPixelP, + ColorNameHash ** const colorNameHashPP) { +/*---------------------------------------------------------------------------- + Read the header of the XPM file on stream *ifP. Assume the getLine() stream is presently positioned to the beginning of the file and it is a Version 3 XPM file. Leave the stream positioned after the header. - We have two ways to return the colormap, depending on the number of - characters per pixel in the XPM: - - If it is 1 or 2 characters per pixel, we return the colormap as a - Netpbm 'pixel' array *colorsP (in newly malloc'ed storage), such - that if a color in the raster is identified by index N, then - (*colorsP)[N] is that color. So this array is either 256 or 64K - pixels. In this case, we return *ptabP = NULL. - - If it is more than 2 characters per pixel, we return the colormap as - both a Netpbm 'pixel' array *colorsP and a lookup table *ptabP (both - in newly malloc'ed storage). - - If a color in the raster is identified by index N, then for some I, - (*ptabP)[I] is N and (*colorsP)[I] is the color in question. So - you iterate through *ptabP looking for N and then look at the - corresponding entry in *colorsP to get the color. - - Return as *transColorNumberP the value of the XPM color number that - represents a transparent pixel, or -1 if no color number does. + Return as *widthP and *heightP the dimensions of the image indicated + by the header. + + Return as *charsPerPixelP the number of characters the header says the + raster uses for each pixel, i.e. the XPM color name length. + + Return the color map as *colorNameHashPP. -----------------------------------------------------------------------------*/ char line[MAX_LINE+1]; const char * xpm3_signature = "/* XPM */"; - *widthP = *heightP = *ncolorsP = *chars_per_pixelP = -1; + unsigned int width, height; + unsigned int nColors; + unsigned int charsPerPixel; /* Read the XPM signature comment */ - getLine(line, sizeof(line), stream); - if (strncmp(line, xpm3_signature, strlen(xpm3_signature)) != 0) + getLine(line, sizeof(line), ifP); + if (!strneq(line, xpm3_signature, strlen(xpm3_signature))) pm_error("Apparent XPM 3 file does not start with '/* XPM */'. " "First line is '%s'", xpm3_signature); /* Read the assignment line */ - getLine(line, sizeof(line), stream); - if (strncmp(line, "static char", 11) != 0) + getLine(line, sizeof(line), ifP); + if (!strneq(line, "static char", 11)) pm_error("Cannot find data structure declaration. Expected a " "line starting with 'static char', but found the line " "'%s'.", line); - /* Read the hints line */ - getLine(line, sizeof(line), stream); - /* skip the comment line if any */ - if (!strncmp(line, "/*", 2)) { + getLine(line, sizeof(line), ifP); + + /* Skip the comment block, if one starts here */ + if (strneq(line, "/*", 2)) { while (!strstr(line, "*/")) - getLine(line, sizeof(line), stream); - getLine(line, sizeof(line), stream); + getLine(line, sizeof(line), ifP); + getLine(line, sizeof(line), ifP); } - if (sscanf(line, "\"%d %d %d %d\",", widthP, heightP, - ncolorsP, chars_per_pixelP) != 4) + + /* Parse the hints line */ + if (sscanf(line, "\"%u %u %u %u\",", &width, &height, + &nColors, &charsPerPixel) != 4) pm_error("error scanning hints line"); - if (verbose == 1) - { - pm_message("Width x Height: %d x %d", *widthP, *heightP); - pm_message("no. of colors: %d", *ncolorsP); - pm_message("chars per pixel: %d", *chars_per_pixelP); + if (verbose) { + pm_message("Width x Height: %u x %u", width, height); + pm_message("no. of colors: %u", nColors); + pm_message("chars per pixel: %u", charsPerPixel); } - /* Allocate space for color table. */ - if (*chars_per_pixelP <= 2) { - /* Set up direct index (see above) */ - *colorsP = ppm_allocrow(*chars_per_pixelP == 1 ? 256 : 256*256); - *ptabP = NULL; - } else { - /* Set up lookup table (see above) */ - *colorsP = ppm_allocrow(*ncolorsP); - MALLOCARRAY(*ptabP, *ncolorsP); - if (*ptabP == NULL) - pm_error("Unable to allocate memory for %d colors", *ncolorsP); - } - - { - /* Read the color table */ - int seqNum; - /* Sequence number of entry within color table in XPM header */ - - *transparentP = -1; /* initial value */ - - for (seqNum = 0; seqNum < *ncolorsP; seqNum++) { - getLine(line, sizeof(line), stream); - /* skip the comment line if any */ - if (!strncmp(line, "/*", 2)) - getLine(line, sizeof(line), stream); - - interpretXpm3ColorTableLine(line, seqNum, *chars_per_pixelP, - *colorsP, *ptabP, transparentP); - } + readV3ColorTable(ifP, colorNameHashPP, nColors, charsPerPixel); + + *widthP = width; + *heightP = height; + *charsPerPixelP = charsPerPixel; +} + + + +static void +readV1ColorTable(FILE * const ifP, + ColorNameHash ** const colorNameHashPP, + unsigned int const nColors, + unsigned int const charsPerPixel) { +/*---------------------------------------------------------------------------- + Read the color table from the XPM Version 1 header. + + Assume *ifP is positioned to the color table; leave it positioned after. +-----------------------------------------------------------------------------*/ + ColorNameHash * const colorNameHashP = hash_create(nColors, charsPerPixel); + + unsigned int i; + + for (i = 0; i < nColors; ++i) { + char line[MAX_LINE+1]; + char str1[MAX_LINE+1]; + char str2[MAX_LINE+1]; + char * t1; + char * t2; + + getLine(line, sizeof(line), ifP); + + if ((t1 = strchr(line, '"')) == NULL) + pm_error("D error scanning color table"); + if ((t2 = strchr(t1 + 1, '"')) == NULL) + pm_error("E error scanning color table"); + if (t2 - t1 - 1 != charsPerPixel) + pm_error("wrong number of chars per pixel in color table"); + strncpy(str1, t1 + 1, t2 - t1 - 1); + str1[t2 - t1 - 1] = '\0'; + + if ((t1 = strchr(t2 + 1, '"')) == NULL) + pm_error("F error scanning color table"); + if ((t2 = strchr(t1 + 1, '"')) == NULL) + pm_error("G error scanning color table"); + strncpy(str2, t1 + 1, t2 - t1 - 1); + str2[t2 - t1 - 1] = '\0'; + + addToColorMap(colorNameHashP, str1, str2, false); } + *colorNameHashPP = colorNameHashP; } + static void -readXpm1Header(FILE * const stream, int * const widthP, int * const heightP, - int * const chars_per_pixelP, int * const ncolorsP, - pixel ** const colorsP, int ** const ptabP) { +readXpm1Header(FILE * const ifP, + unsigned int * const widthP, + unsigned int * const heightP, + unsigned int * const charsPerPixelP, + ColorNameHash ** const colorNameHashPP) { /*---------------------------------------------------------------------------- - Read the header of the XPM file on stream 'stream'. Assume the + Read the header of the XPM file on stream *ifP. Assume the getLine() stream is presently positioned to the beginning of the file and it is a Version 1 XPM file. Leave the stream positioned after the header. Return the information from the header the same as for readXpm3Header. -----------------------------------------------------------------------------*/ - char line[MAX_LINE+1], str1[MAX_LINE+1], str2[MAX_LINE+1]; - char *t1; - char *t2; - int format; - unsigned int v; - int i, j; + int format, v; bool processedStaticChar; /* We have read up to and interpreted the "static char..." line */ + char * t1; + unsigned int nColors; + bool gotPixel, gotNColors, gotWidth, gotHeight, gotFormat; - *widthP = *heightP = *ncolorsP = *chars_per_pixelP = format = -1; + gotNColors = false; + gotWidth = false; + gotHeight = false; + gotFormat = false; + gotPixel = false; /* Read the initial defines. */ processedStaticChar = FALSE; while (!processedStaticChar) { - getLine(line, sizeof(line), stream); + char line[MAX_LINE+1]; + char str1[MAX_LINE+1]; + + getLine(line, sizeof(line), ifP); if (sscanf(line, "#define %s %d", str1, &v) == 2) { - char *t1; if ((t1 = strrchr(str1, '_')) == NULL) t1 = str1; else ++t1; - if (streq(t1, "format")) + if (streq(t1, "format")) { + gotFormat = true; format = v; - else if (streq(t1, "width")) + } else if (streq(t1, "width")) { + gotWidth = true; *widthP = v; - else if (streq(t1, "height")) + } else if (streq(t1, "height")) { + gotHeight = true; *heightP = v; - else if (streq(t1, "ncolors")) - *ncolorsP = v; - else if (streq(t1, "pixel")) - *chars_per_pixelP = v; - } else if (!strncmp(line, "static char", 11)) { + } else if (streq(t1, "nColors")) { + gotNColors = true; + nColors = v; + } else if (streq(t1, "pixel")) { + gotPixel = TRUE; + *charsPerPixelP = v; + } + } else if (strneq(line, "static char", 11)) { if ((t1 = strrchr(line, '_')) == NULL) t1 = line; else @@ -507,85 +780,40 @@ readXpm1Header(FILE * const stream, int * const widthP, int * const heightP, t1 points to position of last "_" in the line, or the beginning of the line if there is no "_" */ - if (format == -1) + if (!gotPixel) + pm_error("No 'pixel' value (characters per pixel)"); + if (!gotFormat) pm_error("missing or invalid format"); if (format != 1) pm_error("can't handle XPM version %d", format); - if (*widthP == -1) + if (!gotWidth) pm_error("missing or invalid width"); - if (*heightP == -1) + if (!gotHeight) pm_error("missing or invalid height"); - if (*ncolorsP == -1) - pm_error("missing or invalid ncolors"); - if (*chars_per_pixelP == -1) - pm_error("missing or invalid *chars_per_pixelP"); - if (*chars_per_pixelP > 2) - pm_message("WARNING: *chars_per_pixelP > 2 uses a lot of memory"); + if (!gotNColors) + pm_error("missing or invalid nColors"); + + if (*charsPerPixelP > 2) + pm_message("WARNING: > 2 characters per pixel uses a lot of memory"); /* If there's a monochrome color table, skip it. */ - if (!strncmp(t1, "mono", 4)) { + if (strneq(t1, "mono", 4)) { for (;;) { - getLine(line, sizeof(line), stream); - if (!strncmp(line, "static char", 11)) + char line[MAX_LINE+1]; + getLine(line, sizeof(line), ifP); + if (strneq(line, "static char", 11)) break; } } - /* Allocate space for color table. */ - if (*chars_per_pixelP <= 2) { - /* Up to two chars per pixel, we can use an indexed table. */ - v = 1; - for (i = 0; i < *chars_per_pixelP; ++i) - v *= 256; - *colorsP = ppm_allocrow(v); - *ptabP = NULL; - } else { - /* Over two chars per pixel, we fall back on linear search. */ - *colorsP = ppm_allocrow(*ncolorsP); - MALLOCARRAY(*ptabP, *ncolorsP); - if (*ptabP == NULL) - pm_error("Unable to allocate memory for %d colors", *ncolorsP); - } - - /* Read color table. */ - for (i = 0; i < *ncolorsP; ++i) { - getLine(line, sizeof(line), stream); + readV1ColorTable(ifP, colorNameHashPP, nColors, *charsPerPixelP); - if ((t1 = strchr(line, '"')) == NULL) - pm_error("D error scanning color table"); - if ((t2 = strchr(t1 + 1, '"')) == NULL) - pm_error("E error scanning color table"); - if (t2 - t1 - 1 != *chars_per_pixelP) - pm_error("wrong number of chars per pixel in color table"); - strncpy(str1, t1 + 1, t2 - t1 - 1); - str1[t2 - t1 - 1] = '\0'; - - if ((t1 = strchr(t2 + 1, '"')) == NULL) - pm_error("F error scanning color table"); - if ((t2 = strchr(t1 + 1, '"')) == NULL) - pm_error("G error scanning color table"); - strncpy(str2, t1 + 1, t2 - t1 - 1); - str2[t2 - t1 - 1] = '\0'; - - v = 0; - for (j = 0; j < *chars_per_pixelP; ++j) - v = (v << 8) + str1[j]; - if (*chars_per_pixelP <= 2) - /* Index into table. */ - (*colorsP)[v] = ppm_parsecolor(str2, - (pixval) PPM_MAXMAXVAL); - else { - /* Set up linear search table. */ - (*colorsP)[i] = ppm_parsecolor(str2, - (pixval) PPM_MAXMAXVAL); - (*ptabP)[i] = v; - } - } /* Position to first line of raster (which is the line after "static char ..."). */ for (;;) { - getLine(line, sizeof(line), stream); - if (strncmp(line, "static char", 11) == 0) + char line[MAX_LINE+1]; + getLine(line, sizeof(line), ifP); + if (strneq(line, "static char", 11)) break; } } @@ -593,29 +821,49 @@ readXpm1Header(FILE * const stream, int * const widthP, int * const heightP, static void -interpretXpmLine(char const line[], - int const chars_per_pixel, - int const ncolors, - int * const ptab, - int ** const cursorP, - int * const maxCursor) { +validateRasterPixel(const char * const pixelChars, + unsigned int const charsPerPixel) { + + unsigned int i; + + for (i = 0; i < charsPerPixel; ++i) { + if (pixelChars[i] == '\0') + pm_error("XPM input file ends in the middle of a string " + "that represents a raster line"); + else if (pixelChars[i] == '"') + pm_error("A string that represents a raster line in the " + "XPM input file is too short to contain all the " + "pixels (%u characters each)", + charsPerPixel); + } +} + + + +static void +convertRow(char const line[], + unsigned int const width, + unsigned int const charsPerPixel, + const ColorNameHash * const colorNameHashP, + pixel * const pixrow, + bit * const alpharow) { /*---------------------------------------------------------------------------- - Interpret one line of XPM input. The line is in 'line', and its - format is 'chars_per_pixel' characters per pixel. 'ptab' is the - color table that applies to the line, which table has 'ncolors' - colors. + Convert one row from XPM input, which describes one raster line of the + image, to PPM. The XPM line is in 'line', and its format is 'width' pixel, + 'charsPerPixel' characters per pixel. *colorNameHashP is the color table + that applies to the line. + + Put the PPM pixels in 'pixrow'. - Put the colormap indexes for the pixels represented in 'line' at - *cursorP, lined up in the order they are in 'line', and return - *cursorP positioned just after the last one. + Also produce PBM row 'alpharow' with the transparency information from the + row. If the line doesn't start with a quote (e.g. it is empty), we issue a warning and just treat the line as one that describes no pixels. - Stop processing the line either at the end of the line or when - the output would go beyond maxCursor, whichever comes first. + Abort program if there aren't exactly 'width' pixels in the line. -----------------------------------------------------------------------------*/ - char * lineCursor; + const char * lineCursor; lineCursor = strchr(line, '"'); /* position to 1st quote in line */ if (lineCursor == NULL) { @@ -626,209 +874,208 @@ interpretXpmLine(char const line[], "line which is supposed to be a line of raster data: " "'%s'. Ignoring this line.", line); } else { + unsigned int col; + ++lineCursor; /* Skip to first character after quote */ /* Handle pixels until a close quote, eol, or we've returned all the pixels Caller wants. */ - while (*lineCursor && *lineCursor != '"' && *cursorP <= maxCursor) { - int colorNumber; - int i; - colorNumber = 0; /* initial value */ - for (i = 0; i < chars_per_pixel; ++i) - colorNumber = (colorNumber << 8) + *(lineCursor++); - if (ptab == NULL) - /* colormap is indexed directly by XPM color number */ - *(*cursorP)++ = colorNumber; - else { - /* colormap shadows ptab[]. Find this color # in ptab[] */ - int i; - for (i = 0; i < ncolors && ptab[i] != colorNumber; ++i); - if (i < ncolors) - *(*cursorP)++ = i; - else - pm_error("Color number %d is in raster, but not in " - "colormap. Line it's in: '%s'", - colorNumber, line); - } + for (col = 0; col < width; ++col) { + + validateRasterPixel(lineCursor, charsPerPixel); + + pixrow[col] = hash_color(colorNameHashP, lineCursor); + + alpharow[col] = hash_isTransparent(colorNameHashP, lineCursor) ? + PBM_BLACK : PBM_WHITE; + + lineCursor += charsPerPixel; } + if (*lineCursor != '"') + pm_error("A raster line continues past width of image"); } } static void -ReadXPMFile(FILE * const stream, int * const widthP, int * const heightP, - pixel ** const colorsP, int ** const dataP, - int * const transparentP) { +convertRaster(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, + unsigned int const charsPerPixel, + const ColorNameHash * const colorNameHashP, + FILE * const imageOutFileP, + FILE * const alphaOutFileP) { /*---------------------------------------------------------------------------- - Read the XPM file from stream 'stream'. + Read the XPM raster from *ifP and write the PPM raster to *imageOutFileP + and the alpha channel to *alphaOutFileP (where those are, respectively, + non-null). - Return the dimensions of the image as *widthP and *heightP. - Return the color map as *colorsP, which is an array of *ncolorsP - colors. + The dimensions are 'cols' by 'rows' and the color map for the XPM + raster is *colorNameHashP. +-----------------------------------------------------------------------------*/ + char line[MAX_LINE+1]; + pixel * pixrow; + bit * alpharow; + unsigned int row; - Return the raster in newly malloced storage, an array of *widthP by - *heightP integers, each of which is an index into the colormap - *colorsP (and therefore less than *ncolorsP). Return the address - of the array as *dataP. + pixrow = ppm_allocrow(cols); + alpharow = pbm_allocrow(cols); - In the colormap, put black for the transparent color, if the XPM - image contains one. ------------------------------------------------------------------------------*/ - char line[MAX_LINE+1], str1[MAX_LINE+1]; - int totalpixels; - int *cursor; /* cursor into *dataP */ - int *maxcursor; /* value of above cursor for last pixel in image */ - int *ptab; /* colormap - malloc'ed */ - int rc; - int ncolors; - int chars_per_pixel; + for (row = 0; row < rows; ++row) { + bool haveLine; - backup = FALSE; + for (haveLine = false; !haveLine; ) { + getLine(line, sizeof(line), ifP); - /* Read the header line */ - getLine(line, sizeof(line), stream); - backup = TRUE; /* back up so next read reads this line again */ - - rc = sscanf(line, "/* %s */", str1); - if (rc == 1 && strncmp(str1, "XPM", 3) == 0) { - /* It's an XPM version 3 file */ - readXpm3Header(stream, widthP, heightP, &chars_per_pixel, - &ncolors, colorsP, &ptab, transparentP); - } else { /* try as an XPM version 1 file */ - /* Assume it's an XPM version 1 file */ - readXpm1Header(stream, widthP, heightP, &chars_per_pixel, - &ncolors, colorsP, &ptab); - *transparentP = -1; /* No transparency in version 1 */ - } - totalpixels = *widthP * *heightP; - MALLOCARRAY(*dataP, totalpixels); - if (*dataP == NULL) - pm_error("Could not get %d bytes of memory for image", totalpixels); - cursor = *dataP; - maxcursor = *dataP + totalpixels - 1; - getLine(line, sizeof(line), stream); - /* read next line (first line may not always start with comment) */ - while (cursor <= maxcursor) { - if (strncmp(line, "/*", 2) == 0) { - /* It's a comment. Ignore it. */ - } else { - interpretXpmLine(line, chars_per_pixel, - ncolors, ptab, &cursor, maxcursor); + if (strneq(line, "/*", 2)) { + /* It's a comment. Ignore it. */ + } else + haveLine = true; } - if (cursor <= maxcursor) - getLine(line, sizeof(line), stream); + convertRow(line, cols, charsPerPixel, colorNameHashP, + pixrow, alpharow); + + if (imageOutFileP) + ppm_writeppmrow(imageOutFileP, + pixrow, cols, PPM_MAXMAXVAL, 0); + if (alphaOutFileP) + pbm_writepbmrow(alphaOutFileP, alpharow, cols, 0); } - if (ptab) free(ptab); + + pbm_freerow(alpharow); + ppm_freerow(pixrow); } static void -writeOutput(FILE * const imageout_file, - FILE * const alpha_file, - int const cols, int const rows, - pixel * const colors, int * const data, - int transparent) { +readXpmHeader(FILE * const ifP, + unsigned int * const widthP, + unsigned int * const heightP, + unsigned int * const charsPerPixelP, + ColorNameHash ** const colorNameHashPP) { /*---------------------------------------------------------------------------- - Write the image in 'data' to open PPM file stream 'imageout_file', - and the alpha mask for it to open PBM file stream 'alpha_file', - except if either is NULL, skip it. + Read the XPM header, including color map. - 'data' is an array of cols * rows integers, each one being an index - into the colormap 'colors'. - - Where the index 'transparent' occurs in 'data', the pixel is supposed - to be transparent. If 'transparent' < 0, no pixels are transparent. + In the colormap, put black for the transparent color, if the XPM image + contains one. -----------------------------------------------------------------------------*/ - int row; - pixel *pixrow; - bit * alpharow; - - if (imageout_file) - ppm_writeppminit(imageout_file, cols, rows, PPM_MAXMAXVAL, 0); - if (alpha_file) - pbm_writepbminit(alpha_file, cols, rows, 0); - - pixrow = ppm_allocrow(cols); - alpharow = pbm_allocrow(cols); + char line[MAX_LINE+1]; + char str1[MAX_LINE+1]; + int rc; + unsigned int charsPerPixel; + unsigned int width, height; - for (row = 0; row < rows; ++row ) { - int col; - int * const datarow = data+(row*cols); + backup = FALSE; - for (col = 0; col < cols; ++col) { - pixrow[col] = colors[datarow[col]]; - if (datarow[col] == transparent) - alpharow[col] = PBM_BLACK; - else - alpharow[col] = PBM_WHITE; - } - if (imageout_file) - ppm_writeppmrow(imageout_file, - pixrow, cols, (pixval) PPM_MAXMAXVAL, 0); - if (alpha_file) - pbm_writepbmrow(alpha_file, alpharow, cols, 0); + /* Read the header line */ + getLine(line, sizeof(line), ifP); + backup = TRUE; /* back up so next read reads this line again */ + + rc = sscanf(line, "/* %s */", str1); + if (rc == 1 && strneq(str1, "XPM", 3)) { + /* It's an XPM version 3 file */ + readXpm3Header(ifP, &width, &height, &charsPerPixel, colorNameHashPP); + } else { + /* Assume it's an XPM version 1 file */ + readXpm1Header(ifP, &width, &height, &charsPerPixel, colorNameHashPP); } - ppm_freerow(pixrow); - pbm_freerow(alpharow); - - if (imageout_file) - pm_close(imageout_file); - if (alpha_file) - pm_close(alpha_file); -} - + *widthP = width; + *heightP = height; + *charsPerPixelP = charsPerPixel; +} + int main(int argc, char *argv[]) { - FILE *ifp; - FILE *alpha_file, *imageout_file; - pixel *colormap; - int cols, rows; - int transparent; /* value of 'data' that means transparent */ - int *data; - /* The image as an array of width * height integers, each one - being an index int colormap[]. - */ + FILE * ifP; + FILE * alphaOutFileP; + FILE * imageOutFileP; + unsigned int cols, rows; + unsigned int charsPerPixel; + ColorNameHash * colorNameHashP; - struct cmdline_info cmdline; + struct cmdlineInfo cmdline; ppm_init(&argc, argv); - parse_command_line(argc, argv, &cmdline); + parseCommandLine(argc, argv, &cmdline); verbose = cmdline.verbose; if ( cmdline.input_filespec != NULL ) - ifp = pm_openr( cmdline.input_filespec); + ifP = pm_openr( cmdline.input_filespec); else - ifp = stdin; + ifP = stdin; if (cmdline.alpha_stdout) - alpha_file = stdout; + alphaOutFileP = stdout; else if (cmdline.alpha_filename == NULL) - alpha_file = NULL; + alphaOutFileP = NULL; else { - alpha_file = pm_openw(cmdline.alpha_filename); + alphaOutFileP = pm_openw(cmdline.alpha_filename); } if (cmdline.alpha_stdout) - imageout_file = NULL; + imageOutFileP = NULL; else - imageout_file = stdout; + imageOutFileP = stdout; - ReadXPMFile(ifp, &cols, &rows, &colormap, &data, &transparent); - - pm_close(ifp); + readXpmHeader(ifP, &cols, &rows, &charsPerPixel, &colorNameHashP); - writeOutput(imageout_file, alpha_file, cols, rows, colormap, data, - transparent); + if (imageOutFileP) + ppm_writeppminit(imageOutFileP, cols, rows, PPM_MAXMAXVAL, 0); + if (alphaOutFileP) + pbm_writepbminit(alphaOutFileP, cols, rows, 0); - free(colormap); + + convertRaster(ifP, cols, rows, charsPerPixel, colorNameHashP, + imageOutFileP, alphaOutFileP); + + pm_close(ifP); + if (imageOutFileP) + pm_close(imageOutFileP); + if (alphaOutFileP) + pm_close(alphaOutFileP); + + hash_destroy(colorNameHashP); return 0; } + + + +/* +** +** Copyright (C) 1991 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. +** +** Upgraded to handle XPM version 3 by +** Arnaud Le Hors (lehors@mirsa.inria.fr) +** Tue Apr 9 1991 +** +** Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91: +** - Bug fix, no advance of read ptr, would not read +** colors like "ac c black" because it would find +** the "c" of "ac" and then had problems with "c" +** as color. +** +** - Now understands multiword X11 color names +** +** - Now reads multiple color keys. Takes the color +** of the hightest available key. Lines no longer need +** to begin with key 'c'. +** +** - expanded line buffer to from 500 to 2048 for bigger files +*/ + diff --git a/converter/ppm/yuvsplittoppm.c b/converter/ppm/yuvsplittoppm.c index b3088812..5343a21e 100644 --- a/converter/ppm/yuvsplittoppm.c +++ b/converter/ppm/yuvsplittoppm.c @@ -57,7 +57,7 @@ parseCommandLine(int argc, was passed to us as the argv array. We also trash *argv. -----------------------------------------------------------------------------*/ optEntry *option_def = malloc(100*sizeof(optEntry)); - /* Instructions to optParseOptions3 on how to parse our options. + /* Instructions to pm_optParseOptions3 on how to parse our options. */ optStruct3 opt; @@ -71,7 +71,7 @@ parseCommandLine(int argc, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3( &argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ @@ -196,9 +196,9 @@ main(int argc, char **argv) { parseCommandLine(argc, argv, &cmdline); - asprintfN(&ufname, "%s.U", cmdline.filenameBase); - asprintfN(&vfname, "%s.V", cmdline.filenameBase); - asprintfN(&yfname, "%s.Y", cmdline.filenameBase); + pm_asprintf(&ufname, "%s.U", cmdline.filenameBase); + pm_asprintf(&vfname, "%s.V", cmdline.filenameBase); + pm_asprintf(&yfname, "%s.Y", cmdline.filenameBase); uf = pm_openr(ufname); vf = pm_openr(vfname); @@ -241,9 +241,9 @@ main(int argc, char **argv) { } pm_close(stdout); - strfree(yfname); - strfree(vfname); - strfree(ufname); + pm_strfree(yfname); + pm_strfree(vfname); + pm_strfree(ufname); pm_close(yf); pm_close(uf); diff --git a/converter/ppm/yuvtoppm.c b/converter/ppm/yuvtoppm.c index 2b44c65f..151ff9f9 100644 --- a/converter/ppm/yuvtoppm.c +++ b/converter/ppm/yuvtoppm.c @@ -20,96 +20,201 @@ ** implied warranty. */ -#include "ppm.h" +#include "pm_c_util.h" #include "mallocvar.h" +#include "shhopt.h" +#include "ppm.h" -/* x must be signed for the following to work correctly */ -#define limit(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16) -int -main(argc, argv) - char **argv; -{ - FILE *ifp; - pixel *pixrow; - int argn, rows, cols, row; - const char * const usage = "<width> <height> [yuvfile]"; - struct yuv { - /* This is an element of a YUV file. It describes two - side-by-side pixels. - */ - unsigned char u; - unsigned char y1; - unsigned char v; - unsigned char y2; - } *yuvbuf; - - ppm_init(&argc, argv); - - argn = 1; - - if (argn + 2 > argc) - pm_usage(usage); - - cols = atoi(argv[argn++]); - rows = atoi(argv[argn++]); - if (cols <= 0 || rows <= 0) - pm_usage(usage); - - if (argn < argc) { - ifp = pm_openr(argv[argn]); - ++argn; - } else - ifp = stdin; - - if (argn != argc) - pm_usage(usage); - - if (cols % 2 != 0) { - pm_error("Number of columns (%d) is odd. A YUV image must have an " - "even number of columns.", cols); + +struct CmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + unsigned int cols; + unsigned int rows; + const char * inputFileName; /* Name of input file */ +}; + + + +static void +parseCommandLine(int argc, const char ** argv, + struct CmdlineInfo * const cmdlineP) { + + optEntry * option_def; + /* Instructions to OptParseOptions3 on how to parse our options */ + optStruct3 opt; + + MALLOCARRAY_NOFAIL(option_def, 100); + + OPTENTINIT; + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (argc-1 < 2) + pm_error("You need at least two arguments: width and height in " + "pixels. You specified %u", argc-1); + else { + int const widthArg = atoi(argv[1]); + int const heightArg = atoi(argv[2]); + + if (widthArg < 0) + pm_error("Negative number for width: %d", widthArg); + if (heightArg < 0) + pm_error("Negative number for height: %d", heightArg); + + cmdlineP->cols = widthArg; + cmdlineP->rows = heightArg; + + if (cmdlineP->cols % 2 != 0) + pm_error("Number of columns (%u) is odd. " + "A YUV image must have an " + "even number of columns.", cmdlineP->cols); + + if (argc-1 < 3) + cmdlineP->inputFileName = "-"; + else { + cmdlineP->inputFileName = argv[3]; + + if (argc-1 > 3) + pm_error("Too many arguments: %u. " + "The only possible arguments are " + "width, height, and input file name", argc-1); + } } +} - ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0); - pixrow = ppm_allocrow(cols); - MALLOCARRAY(yuvbuf, (cols+1)/2); - if (yuvbuf == NULL) - pm_error("Unable to allocate YUV buffer for %d columns.", cols); - for (row = 0; row < rows; ++row) { - int col; - fread(yuvbuf, cols * 2, 1, ifp); +static int +limit(int const x) { - for (col = 0; col < cols; col += 2) { - /* Produce two pixels in pixrow[] */ - int y1, u, v, y2, r, g, b; + if (x > 0xffffff) + return 0xff; + else if (x <= 0xffff) + return 0; + else + return ((x >> 16) & 0xff); +} + + + +static int +nonneg(int const x) { +/*---------------------------------------------------------------------------- + Raise 'x' to 0 if negative +-----------------------------------------------------------------------------*/ + return x < 0 ? 0 : x; +} + + + +struct Yuv { +/*---------------------------------------------------------------------------- + This is an element of a YUV file. It describes two side-by-side pixels. + + This is the actual layout of the data in the file (4 bytes). +-----------------------------------------------------------------------------*/ + unsigned char u; + unsigned char y1; + unsigned char v; + unsigned char y2; +}; - u = yuvbuf[col/2].u-128; - y1 = yuvbuf[col/2].y1 - 16; - if (y1 < 0) y1 = 0; - v = yuvbuf[col/2].v - 128; +static void +readYuv(FILE * const ifP, + struct Yuv * const yuvP) { - y2 = yuvbuf[col/2].y2 - 16; - if (y2 < 0) y2 = 0; + size_t readCt; - r = 104635 * v; - g = -25690 * u + -53294 * v; - b = 132278 * u; + readCt = fread(yuvP, sizeof(*yuvP), 1, ifP); - y1*=76310; y2*=76310; + if (readCt != 1) { + if (feof(ifP)) + pm_error("Premature end of input."); + else + pm_error("Error reading input."); + } +} + + + +static void +yuvtoppm(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, + FILE * const ofP) { + + pixval const maxval = 255; + + pixel * pixrow; + unsigned int row; + + ppm_writeppminit(ofP, cols, rows, maxval, 0); + + pixrow = ppm_allocrow(cols); + + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; col += 2) { + /* Produce two pixels in pixrow[] */ + struct Yuv yuv; + int y1, u, v, y2, r, g, b; + + readYuv(ifP, &yuv); + + u = yuv.u - 128; + y1 = nonneg (yuv.y1 - 16); + v = yuv.v - 128; + y2 = nonneg (yuv.y2 - 16); + + r = 104635 * v; + g = -25690 * u + -53294 * v; + b = 132278 * u; + + y1 *= 76310; + y2 *= 76310; + + PPM_ASSIGN(pixrow[col], + limit(r + y1), limit(g + y1), limit(b + y1)); + PPM_ASSIGN(pixrow[col + 1], + limit(r + y2), limit(g + y2), limit(b + y2)); + } + ppm_writeppmrow(ofP, pixrow, cols, maxval, 0); + } - PPM_ASSIGN(pixrow[col], limit(r+y1), limit(g+y1), limit(b+y1)); - PPM_ASSIGN(pixrow[col+1], limit(r+y2), limit(g+y2), limit(b+y2)); - } - ppm_writeppmrow(stdout, pixrow, cols, (pixval) 255, 0); - } - free(yuvbuf); ppm_freerow(pixrow); - pm_close(ifp); - pm_close(stdout); - exit(0); + if (fgetc(ifP) != EOF) + pm_message("Extraneous data at end of image."); +} + + + +int +main (int argc, const char ** argv) { + + FILE * ifP; + struct CmdlineInfo cmdline; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFileName); + + yuvtoppm(ifP, cmdline.cols, cmdline.rows, stdout); + + pm_close(ifP); + pm_close(stdout); + + return 0; } |