diff options
Diffstat (limited to 'converter/ppm')
65 files changed, 5389 insertions, 5251 deletions
diff --git a/converter/ppm/411toppm.c b/converter/ppm/411toppm.c index a5b25ac1..6ece4c4b 100644 --- a/converter/ppm/411toppm.c +++ b/converter/ppm/411toppm.c @@ -58,6 +58,7 @@ #include <stdio.h> #include <stdlib.h> +#include "pm_c_util.h" #include "ppm.h" #include "shhopt.h" #include "mallocvar.h" diff --git a/converter/ppm/Makefile b/converter/ppm/Makefile index 31ca826b..adc3a400 100644 --- a/converter/ppm/Makefile +++ b/converter/ppm/Makefile @@ -5,7 +5,7 @@ endif SUBDIR = converter/ppm VPATH=.:$(SRCDIR)/$(SUBDIR) -include $(BUILDDIR)/Makefile.config +include $(BUILDDIR)/config.mk SUBDIRS = hpcdtoppm ppmtompeg @@ -42,7 +42,7 @@ MERGE_OBJECTS = $(BINARIES:%=%.o2) .PHONY: all all: $(BINARIES) $(SUBDIRS:%=%/all) -include $(SRCDIR)/Makefile.common +include $(SRCDIR)/common.mk ppmtobmp.o ppmtobmp.o2: bmp.h diff --git a/converter/ppm/eyuvtoppm.c b/converter/ppm/eyuvtoppm.c index dcbb9547..33d57409 100644 --- a/converter/ppm/eyuvtoppm.c +++ b/converter/ppm/eyuvtoppm.c @@ -34,6 +34,8 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> + +#include "pm_c_util.h" #include "ppm.h" #include "shhopt.h" #include "mallocvar.h" diff --git a/converter/ppm/hpcdtoppm/Makefile b/converter/ppm/hpcdtoppm/Makefile index 9a7c67d0..91aefc5b 100644 --- a/converter/ppm/hpcdtoppm/Makefile +++ b/converter/ppm/hpcdtoppm/Makefile @@ -5,14 +5,14 @@ endif SUBDIR = converter/ppm/hpcdtoppm VPATH=.:$(SRCDIR)/$(SUBDIR) -include $(BUILDDIR)/Makefile.config +include $(BUILDDIR)/config.mk all: hpcdtoppm SCRIPTS = hpcdtoppm pcdovtoppm MERGE_OBJECTS = -include $(SRCDIR)/Makefile.common +include $(SRCDIR)/common.mk install: install.bin.local .PHONY: install.bin.local diff --git a/converter/ppm/ilbmtoppm.c b/converter/ppm/ilbmtoppm.c index c88cdfb2..0c365834 100644 --- a/converter/ppm/ilbmtoppm.c +++ b/converter/ppm/ilbmtoppm.c @@ -1,4 +1,4 @@ -/* ilbmtoppm.c - read an IFF ILBM file and produce a portable pixmap +/* ilbmtoppm.c - read an IFF ILBM file and produce a PPM ** ** Copyright (C) 1989 by Jef Poskanzer. ** @@ -43,11 +43,10 @@ #include <string.h> #include "pm_c_util.h" -#include "ppm.h" -#include "ilbm.h" #include "mallocvar.h" - -/*#define DEBUG*/ +#include "intcode.h" +#include "ilbm.h" +#include "ppm.h" typedef struct { int reg; /* color register to change */ @@ -765,10 +764,15 @@ multi_free(cmap) ****************************************************************************/ static void -check_cmap(bmhd, cmap) - BitMapHeader *bmhd; - ColorMap *cmap; -{ +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. + +-----------------------------------------------------------------------------*/ pixval colmaxval = 0; int shifted = 1; int i, r, g, b; @@ -987,6 +991,8 @@ std_to_ppm(FILE * const ifp, ColorMap * const cmap, long const viewportmodes); + + static void ham_to_ppm(FILE * const ifp, long const chunksize, @@ -1252,7 +1258,7 @@ dcol_to_ppm(FILE * const ifP, unsigned int const greenplanes = dcol->g; unsigned int const blueplanes = dcol->b; - int col, row, i; + int col, row; rawtype *Rrow, *Grow, *Brow; pixval maxval, redmaxval, greenmaxval, bluemaxval; pixval *redtable, *greentable, *bluetable; @@ -1298,13 +1304,15 @@ dcol_to_ppm(FILE * const ifP, MALLOCARRAY_NOFAIL(greentable, greenmaxval +1); MALLOCARRAY_NOFAIL(bluetable, bluemaxval +1); - for( i = 0; i <= redmaxval; i++ ) - redtable[i] = (i * maxval + redmaxval/2)/redmaxval; - for( i = 0; i <= greenmaxval; i++ ) - greentable[i] = (i * maxval + greenmaxval/2)/greenmaxval; - for( i = 0; i <= bluemaxval; i++ ) - bluetable[i] = (i * maxval + bluemaxval/2)/bluemaxval; - + { + unsigned int i; + for (i = 0; i <= redmaxval; ++i) + redtable[i] = ROUNDDIV(i * maxval, redmaxval); + for (i = 0; i <= greenmaxval; ++i) + greentable[i] = ROUNDDIV(i * maxval, greenmaxval); + for (i = 0; i <= bluemaxval; ++i) + bluetable[i] = ROUNDDIV(i * maxval, bluemaxval); + } if( transpName ) { MALLOCVAR_NOFAIL(transpColor); *transpColor = ppm_parsecolor(transpName, maxval); @@ -1340,16 +1348,10 @@ dcol_to_ppm(FILE * const ifP, static void -cmap_to_ppm(cmap) - ColorMap *cmap; -{ - ppm_colorrowtomapfile(stdout, cmap->color, cmap->ncolors, MAXCOLVAL); -#if 0 - int i; - ppm_writeppminit(stdout, cmap->ncolors, 1, MAXCOLVAL, 1); - for( i = 0; i < cmap->ncolors; i++ ) - ppm_writeppmrow(stdout, &(cmap->color[i]), 1, MAXCOLVAL, 1); -#endif +cmapToPpm(FILE * const ofP, + ColorMap * const cmapP) { + + ppm_colorrowtomapfile(ofP, cmapP->color, cmapP->ncolors, MAXCOLVAL); } @@ -1654,39 +1656,41 @@ PCHG_DecompHuff(src, dest, tree, origsize) } + static void -PCHG_Decompress(PCHG, CompHdr, compdata, compsize, comptree, data) - PCHGHeader *PCHG; - PCHGCompHeader *CompHdr; - unsigned char *compdata; - unsigned long compsize; - unsigned char *comptree; - unsigned char *data; -{ - short *hufftree; - unsigned long huffsize, i; - unsigned long treesize = CompHdr->CompInfoSize; +PCHG_Decompress(PCHGHeader * const PCHG, + PCHGCompHeader * const CompHdr, + unsigned char * const compdata, + unsigned long const compsize, + unsigned char * const comptree, + unsigned char * const data) { - switch( PCHG->Compression ) { - case PCHG_COMP_HUFFMAN: + switch(PCHG->Compression) { + case PCHG_COMP_HUFFMAN: { + unsigned long const treesize = CompHdr->CompInfoSize; + unsigned long const huffsize = treesize / 2; + const bigend16 * const bigendComptree = (const void *)comptree; -#ifdef DEBUG - pm_message("PCHG Huffman compression"); -#endif - /* turn big-endian 2-byte shorts into native format */ - huffsize = treesize/2; - MALLOCARRAY_NOFAIL(hufftree, huffsize); - for( i = 0; i < huffsize; i++ ) { - hufftree[i] = (short)BIG_WORD(comptree); - comptree += 2; - } + short * hufftree; + unsigned long i; - /* decompress the change structure data */ - PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1], - CompHdr->OriginalDataSize); + /* Convert big-endian 2-byte shorts to C shorts */ - free(hufftree); - break; + MALLOCARRAY(hufftree, huffsize); + + if (!hufftree) + pm_error("Couldn't get memory for %lu-byte Huffman tree", + huffsize); + + for (i = 0; i < huffsize; ++i) + hufftree[i] = pm_uintFromBigend16(bigendComptree[i]); + + /* decompress the change structure data */ + PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1], + CompHdr->OriginalDataSize); + + free(hufftree); + } break; default: pm_error("unknown PCHG compression type %d", PCHG->Compression); } @@ -1795,94 +1799,119 @@ fail2: } + static void -PCHG_ConvertBig(PCHG, cmap, mask, datasize) - PCHGHeader *PCHG; - ColorMap *cmap; - unsigned char *mask; - unsigned long datasize; -{ - unsigned char *data; +PCHG_ConvertBig(PCHGHeader * const PCHG, + ColorMap * const cmap, + unsigned char * const maskStart, + unsigned long const datasize) { + + unsigned char * data; unsigned char thismask; - int bits, row, i, changes, masklen, reg; - unsigned long totalchanges = 0; - int changedlines = PCHG->ChangedLines; + int bits; + unsigned int row; + int changes; + int masklen; + int reg; + unsigned long totalchanges; + int changedlines; + unsigned long dataRemaining; + unsigned char * mask; + + mask = maskStart; /* initial value */ + dataRemaining = datasize; /* initial value */ + changedlines = PCHG->ChangedLines; /* initial value */ + totalchanges = 0; /* initial value */ masklen = 4 * MaskLongWords(PCHG->LineCount); - data = mask + masklen; datasize -= masklen; + data = mask + masklen; dataRemaining -= masklen; - bits = 0; - for( row = PCHG->StartLine; changedlines && row < 0; row++ ) { - if( bits == 0 ) { - if( masklen == 0 ) goto fail2; + for (row = PCHG->StartLine, bits = 0; changedlines && row < 0; ++row) { + if (bits == 0) { + if (masklen == 0) + pm_error("insufficient data in line mask"); thismask = *mask++; --masklen; bits = 8; } - if( thismask & (1<<7) ) { - if( datasize < 2 ) goto fail; - changes = BIG_WORD(data); data += 2; datasize -= 2; + if (thismask & (1<<7)) { + unsigned int i; + + if (dataRemaining < 2) + pm_error("insufficient data in BigLineChanges structures"); + + changes = BIG_WORD(data); data += 2; dataRemaining -= 2; + + for (i = 0; i < changes; ++i) { + if (totalchanges >= PCHG->TotalChanges) + pm_error("insufficient data in BigLineChanges structures"); + + if (dataRemaining < 6) + pm_error("insufficient data in BigLineChanges structures"); - for( i = 0; i < changes; i++ ) { - if( totalchanges >= PCHG->TotalChanges ) goto fail; - if( datasize < 6 ) goto fail; reg = BIG_WORD(data); data += 2; cmap->mp_init[reg - PCHG->MinReg].reg = reg; ++data; /* skip alpha */ cmap->mp_init[reg - PCHG->MinReg].r = *data++; cmap->mp_init[reg - PCHG->MinReg].b = *data++; /* yes, RBG */ cmap->mp_init[reg - PCHG->MinReg].g = *data++; - datasize -= 6; + dataRemaining -= 6; ++totalchanges; } --changedlines; } thismask <<= 1; - bits--; + --bits; } - for( row = PCHG->StartLine; changedlines && row < cmap->mp_rows; row++ ) { - if( bits == 0 ) { - if( masklen == 0 ) goto fail2; + for (row = PCHG->StartLine; changedlines && row < cmap->mp_rows; ++row) { + if (bits == 0) { + if (masklen == 0) + pm_error("insufficient data in line mask"); + thismask = *mask++; --masklen; bits = 8; } - if( thismask & (1<<7) ) { - if( datasize < 2 ) goto fail; - changes = BIG_WORD(data); data += 2; datasize -= 2; + if (thismask & (1<<7)) { + unsigned int i; + + if (dataRemaining < 2) + pm_error("insufficient data in BigLineChanges structures"); + + changes = BIG_WORD(data); data += 2; dataRemaining -= 2; MALLOCARRAY_NOFAIL(cmap->mp_change[row], changes + 1); - for( i = 0; i < changes; i++ ) { - if( totalchanges >= PCHG->TotalChanges ) goto fail; - if( datasize < 6 ) goto fail; + for (i = 0; i < changes; ++i) { + if (totalchanges >= PCHG->TotalChanges) + pm_error("insufficient data in BigLineChanges structures"); + + if (dataRemaining < 6) + pm_error("insufficient data in BigLineChanges structures"); + reg = BIG_WORD(data); data += 2; cmap->mp_change[row][i].reg = reg; ++data; /* skip alpha */ cmap->mp_change[row][i].r = *data++; cmap->mp_change[row][i].b = *data++; /* yes, RBG */ cmap->mp_change[row][i].g = *data++; - datasize -= 6; + dataRemaining -= 6; ++totalchanges; } cmap->mp_change[row][changes].reg = MP_REG_END; --changedlines; } thismask <<= 1; - bits--; + --bits; } - if( totalchanges != PCHG->TotalChanges ) + if (totalchanges != PCHG->TotalChanges) pm_message("warning - got %ld change structures, " "chunk header reports %ld", totalchanges, PCHG->TotalChanges); - return; -fail: - pm_error("insufficient data in BigLineChanges structures"); -fail2: - pm_error("insufficient data in line mask"); } + static void read_pchg(FILE * const ifp, IFF_ID const iffid, @@ -1936,7 +1965,7 @@ read_pchg(FILE * const ifp, read_bytes(ifp, treesize, comptree, iffid, &remainingChunksize); compsize = remainingChunksize; - MALLOCARRAY_NOFAIL(compdata, remainingChunksize); + MALLOCARRAY_NOFAIL(compdata, compsize); read_bytes(ifp, compsize, compdata, iffid, &remainingChunksize); datasize = CompHdr.OriginalDataSize; @@ -2030,7 +2059,7 @@ process_body( FILE * const ifp, pm_error("%s chunk without %s chunk", ID2string(ID_BODY), ID2string(ID_BMHD)); - check_cmap(bmhdP, cmap); + prepareCmap(bmhdP, cmap); pixelrow = ppm_allocrow(bmhdP->w); if( maskfile ) { @@ -2078,21 +2107,21 @@ process_body( FILE * const ifp, static void -process_chunk(FILE * const ifp, - long const formsize, - IFF_ID const ignorelist[], - unsigned int const ignorecount, - int const fakeviewport, - int const viewportmask, - int const isdeepopt, - bool const cmaponly, - bool * const bodyChunkProcessedP, - bool * const endchunkP, - BitMapHeader ** const bmhdP, - ColorMap * const cmap, - DirectColor ** const dcolP, - int * const viewportmodesP, - long * const bytesReadP +processChunk(FILE * const ifP, + long const formsize, + IFF_ID const ignorelist[], + unsigned int const ignorecount, + int const fakeviewport, + int const viewportmask, + int const isdeepopt, + bool const cmaponly, + bool * const bodyChunkProcessedP, + bool * const endchunkP, + BitMapHeader ** const bmhdP, + ColorMap * const cmap, + DirectColor ** const dcolP, + int * const viewportmodesP, + long * const bytesReadP ) { IFF_ID iffid; @@ -2101,129 +2130,168 @@ process_chunk(FILE * const ifp, bytesread = 0; - iffid = get_big_long(ifp, ID_FORM, NULL); - chunksize = get_big_long(ifp, iffid, NULL); + iffid = get_big_long(ifP, ID_FORM, NULL); + chunksize = get_big_long(ifP, iffid, NULL); bytesread += 8; if (debug) - pm_message("reading %s chunk: %ld bytes", - ID2string(iffid), chunksize); + pm_message("reading %s chunk: %ld bytes", ID2string(iffid), chunksize); - if( ignored_iffid(iffid, ignorelist, ignorecount) ) { + if (ignored_iffid(iffid, ignorelist, ignorecount)) { pm_message("ignoring %s chunk", ID2string(iffid)); - skip_chunk(ifp, iffid, chunksize); - } else if( iffid == ID_END ) { + skip_chunk(ifP, iffid, chunksize); + } else if (iffid == ID_END) { /* END chunks are not officially valid in IFF, but suggested as a future expansion for stream-writing, see Amiga RKM Devices, 3rd Ed, page 376 */ - if( chunksize != 0 ) { + if (chunksize != 0 ) { pm_message("warning - non-0 %s chunk", ID2string(iffid)); - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); } - if( formsize != 0xffffffff ) + if (formsize != 0xffffffff) pm_message("warning - %s chunk with FORM size 0x%08lx " "(should be 0x%08x)", ID2string(iffid), formsize, 0xffffffff); *endchunkP = 1; - } else if( *bodyChunkProcessedP ) { + } else if (*bodyChunkProcessedP) { pm_message("%s chunk found after %s chunk - skipping", ID2string(iffid), ID2string(ID_BODY)); - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); } else - switch( iffid ) { + switch (iffid) { case ID_BMHD: - *bmhdP = read_bmhd(ifp, iffid, chunksize); + *bmhdP = read_bmhd(ifP, iffid, chunksize); break; case ID_CMAP: - read_cmap(ifp, iffid, chunksize, cmap); + read_cmap(ifP, iffid, chunksize, cmap); break; case ID_CMYK: - read_cmyk(ifp, iffid, chunksize, cmap); + read_cmyk(ifP, iffid, chunksize, cmap); break; case ID_CLUT: - read_clut(ifp, iffid, chunksize, cmap); + read_clut(ifP, iffid, chunksize, cmap); break; case ID_CAMG: - if( chunksize != CAMGChunkSize ) + if (chunksize != CAMGChunkSize) pm_error("%s chunk size mismatch", ID2string(iffid)); - *viewportmodesP = get_big_long(ifp, ID_CAMG, NULL); + *viewportmodesP = get_big_long(ifP, ID_CAMG, NULL); *viewportmodesP &= viewportmask; /* -isnotham/-isnotehb */ break; case ID_PCHG: - read_pchg(ifp, iffid, chunksize, cmap); + read_pchg(ifP, iffid, chunksize, cmap); break; case ID_CTBL: case ID_SHAM: - read_4bit_mp(ifp, iffid, chunksize, cmap); + read_4bit_mp(ifP, iffid, chunksize, cmap); break; case ID_DCOL: - if( chunksize != DirectColorSize ) + if (chunksize != DirectColorSize) pm_error("%s chunk size mismatch", ID2string(iffid)); MALLOCVAR_NOFAIL(*dcolP); - (*dcolP)->r = get_byte(ifp, iffid, NULL); - (*dcolP)->g = get_byte(ifp, iffid, NULL); - (*dcolP)->b = get_byte(ifp, iffid, NULL); - (void)get_byte(ifp, iffid, NULL); /* skip pad byte */ + (*dcolP)->r = get_byte(ifP, iffid, NULL); + (*dcolP)->g = get_byte(ifP, iffid, NULL); + (*dcolP)->b = get_byte(ifP, iffid, NULL); + get_byte(ifP, iffid, NULL); /* skip pad byte */ break; case ID_BODY: - if( cmaponly || (*bmhdP && (*bmhdP)->nPlanes == 0 )) { - skip_chunk(ifp, ID_BODY, chunksize); - return; - } - - process_body(ifp, chunksize, *bmhdP, cmap, - maskfile, fakeviewport, isdeepopt, *dcolP, - viewportmodesP); - - *bodyChunkProcessedP = TRUE; + if (cmaponly || (*bmhdP && (*bmhdP)->nPlanes == 0)) + skip_chunk(ifP, ID_BODY, chunksize); + else { + process_body(ifP, chunksize, *bmhdP, cmap, + maskfile, fakeviewport, isdeepopt, *dcolP, + viewportmodesP); - break; + *bodyChunkProcessedP = TRUE; + } break; case ID_GRAB: case ID_DEST: case ID_SPRT: case ID_CRNG: case ID_CCRT: case ID_DYCP: case ID_DPPV: case ID_DRNG: case ID_EPSF: case ID_JUNK: case ID_CNAM: case ID_PRVW: case ID_TINY: case ID_DPPS: - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); break; case ID_copy: case ID_AUTH: case ID_NAME: case ID_ANNO: case ID_TEXT: case ID_FVER: - if( verbose ) - display_chunk(ifp, iffid, chunksize); + if (verbose) + display_chunk(ifP, iffid, chunksize); else - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); break; - case ID_DPI: - { + case ID_DPI: { int x, y; - x = get_big_short(ifp, ID_DPI, NULL); - y = get_big_short(ifp, ID_DPI, NULL); - if( verbose ) + x = get_big_short(ifP, ID_DPI, NULL); + y = get_big_short(ifP, ID_DPI, NULL); + if (verbose) pm_message("%s chunk: dpi_x = %d dpi_y = %d", ID2string(ID_DPI), x, y); - } - break; + } break; default: pm_message("unknown chunk type %s - skipping", ID2string(iffid)); - skip_chunk(ifp, iffid, chunksize); + skip_chunk(ifP, iffid, chunksize); break; } bytesread += chunksize; - if( ODD(chunksize) ) { - (void) get_byte(ifp, iffid, NULL); + if (ODD(chunksize)) { + get_byte(ifP, iffid, NULL); bytesread += 1; } *bytesReadP = bytesread; } + +static void +maybeWriteColorMap(FILE * const ofP, + const BitMapHeader * const bmhdP, + ColorMap * const cmapP, + bool const bodyChunkProcessed, + bool const cmaponly) { +/*---------------------------------------------------------------------------- + Write to file *ofP the color map *cmapP as a PPM, if appropriate. + + The logic (not just here -- in the program as a whole) for deciding whether + to write the image or the colormap is quite twisted. If I thought anyone + was actually using this program, I would take the time to straighten it + out. + + What's really sick about this subroutine is that in choosing to write + a color map, it has to know that Caller hasn't already written + the image. Huge modularity violation. +-----------------------------------------------------------------------------*/ + if (cmaponly) { + if (HAS_COLORMAP(cmapP)) { + prepareCmap(bmhdP, cmapP); + cmapToPpm(ofP, cmapP); + } else + pm_error("You specified -cmaponly, but the ILBM " + "has no colormap"); + } else if (bmhdP && bmhdP->nPlanes == 0) { + if (HAS_COLORMAP(cmapP)) { + prepareCmap(bmhdP, cmapP); + cmapToPpm(ofP, cmapP); + } else + pm_error("ILBM has neither a color map nor color planes"); + } else if (!bodyChunkProcessed) { + if (HAS_COLORMAP(cmapP)) { + pm_message("input is a colormap file"); + prepareCmap(bmhdP, cmapP); + cmapToPpm(ofP, cmapP); + } else + pm_error("ILBM has neither %s or %s chunk", + ID2string(ID_BODY), ID2string(ID_CMAP)); + } +} + + + int main(int argc, char *argv[]) { - FILE *ifp; + FILE * ifP; int argn; short cmaponly = 0, isdeepopt = 0; bool endchunk; @@ -2297,25 +2365,25 @@ main(int argc, char *argv[]) { } if( argn < argc ) { - ifp = pm_openr( argv[argn] ); + ifP = pm_openr( argv[argn] ); argn++; } else - ifp = stdin; + ifP = stdin; if( argn != argc ) pm_usage(usage); /* Read in the ILBM file. */ - firstIffid = get_big_long(ifp, ID_FORM, NULL); - if( firstIffid != ID_FORM ) + firstIffid = get_big_long(ifP, ID_FORM, NULL); + if (firstIffid != ID_FORM) pm_error("input is not a FORM type IFF file"); - formsize = get_big_long(ifp, ID_FORM, NULL); - typeid = get_big_long(ifp, ID_FORM, NULL); - if( typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 && - typeid != ID_PBM ) - pm_error( "input is not an ILBM, RGBN, RGB8 or PBM " - "type FORM IFF file" ); + formsize = get_big_long(ifP, ID_FORM, NULL); + typeid = get_big_long(ifP, ID_FORM, NULL); + if (typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 && + typeid != ID_PBM) + pm_error("input is not an ILBM, RGBN, RGB8 or PBM " + "type FORM IFF file"); bytesread = 4; /* FORM and formsize do not count */ cmap = alloc_cmap(); @@ -2323,55 +2391,41 @@ main(int argc, char *argv[]) { /* Main loop, parsing the IFF FORM. */ bodyChunkProcessed = FALSE; endchunk = FALSE; - while( !endchunk && formsize-bytesread >= 8 ) { - long bytes_read_for_chunk; + while (!endchunk && formsize-bytesread >= 8) { + long bytesReadForChunk; - process_chunk(ifp, formsize, ignorelist, ignorecount, - fakeviewport, viewportmask, - isdeepopt, cmaponly, - &bodyChunkProcessed, - &endchunk, &bmhdP, cmap, &dcol, - &viewportmodes, &bytes_read_for_chunk); + processChunk(ifP, formsize, ignorelist, ignorecount, + fakeviewport, viewportmask, + isdeepopt, cmaponly, + &bodyChunkProcessed, + &endchunk, &bmhdP, cmap, &dcol, + &viewportmodes, &bytesReadForChunk); - bytesread += bytes_read_for_chunk; + bytesread += bytesReadForChunk; } - if( maskfile ) { + if (maskfile) { pm_close(maskfile); - if( !wrotemask ) + if (!wrotemask) remove(maskname); pbm_freerow(maskrow); } - if( cmaponly || (bmhdP && bmhdP->nPlanes == 0 )) { - if( HAS_COLORMAP(cmap) ) { - check_cmap(bmhdP, cmap); - cmap_to_ppm(cmap); - } else - pm_error("no colormap"); - } else if( !bodyChunkProcessed ) { - if( HAS_COLORMAP(cmap) ) { - pm_message("input is a colormap file"); - check_cmap(bmhdP, cmap); - cmap_to_ppm(cmap); - } else - pm_error("no %s or %s chunk found", - ID2string(ID_BODY), ID2string(ID_CMAP)); - } + maybeWriteColorMap(stdout, bmhdP, cmap, bodyChunkProcessed, cmaponly); { unsigned int skipped; - for( skipped = 0; fgetc(ifp) != EOF; ++skipped ) - bytesread++; + for (skipped = 0; fgetc(ifP) != EOF; ++skipped) + ++bytesread; - if( skipped > 0 ) + if (skipped > 0) pm_message("skipped %u extraneous byte%s after last chunk", skipped, (skipped == 1 ? "" : "s")); } - pm_close(ifp); + pm_close(ifP); - if( !endchunk && bytesread != formsize ) { + if (!endchunk && bytesread != formsize) { pm_message("warning - file length/FORM size field mismatch " "(%ld != %ld+8)", bytesread+8 /* FORM+size */, formsize); diff --git a/converter/ppm/mitsu.h b/converter/ppm/mitsu.h index 8676a39d..bca4fbdf 100644 --- a/converter/ppm/mitsu.h +++ b/converter/ppm/mitsu.h @@ -1,7 +1,6 @@ #ifndef MITSU_H_INCLUDED #define MITSU_H_INCLUDED -/* static char SCCSid[] = "@(#)mitsu.h\t\t1.3\t(SPZ)\t3/11/92\n"; */ #define MAXLUTCOL 255 #define A4_MAXCOLS 1184 diff --git a/converter/ppm/pcxtoppm.c b/converter/ppm/pcxtoppm.c index 9f403538..25a81531 100644 --- a/converter/ppm/pcxtoppm.c +++ b/converter/ppm/pcxtoppm.c @@ -31,6 +31,7 @@ * - moved check of 16-color-palette into pcx_16col_to_ppm(), * now checks if it contains only a single color */ +#include "pm_c_util.h" #include "mallocvar.h" #include "shhopt.h" #include "ppm.h" diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c index d52963fc..9a7d8e7c 100644 --- a/converter/ppm/picttoppm.c +++ b/converter/ppm/picttoppm.c @@ -94,16 +94,16 @@ struct rgbPlanes { word * blu; }; +struct canvas { + struct rgbPlanes planes; +}; + typedef void (*transfer_func) (struct RGBColor* src, struct RGBColor* dst); -static const char* stage; +static const char * stage; static struct Rect picFrame; -static word* red; -static word* green; -static word* blue; static word rowlen; static word collen; -static longword planelen; static int verbose; static int fullres; static int recognize_comment; @@ -142,13 +142,6 @@ static int ps_cent_x; static int ps_cent_y; static int ps_cent_set; -struct opdef { - const char* name; - int len; - void (*impl) (int); - const char* description; -}; - struct raster { /*---------------------------------------------------------------------------- An image raster. May be either truecolor or paletted. @@ -178,13 +171,28 @@ struct raster { }; + static void allocateRaster(struct raster * const rasterP, unsigned int const width, unsigned int const height, unsigned int const bitsPerPixel) { +/*---------------------------------------------------------------------------- + Allocate storage for a raster that can contain a 'width' x 'height' + pixel rectangle read from a PICT image with 'bitsPerPixel' bits + per pixel. + + Make the space large enough to round the number of pixels up to a + multiple of 16, because we've seen many images in which the PICT raster + does contain that much padding on the right. I don't know why; I could + understand a multiple of 8, since in 1 bpp image, the smallest unit + expressable in PICT is 8 pixels. But why 16? The images we saw came + from Adobe Illustrator 10 in March 2007, supplied by + Guillermo Gómez Valcárcel. +-----------------------------------------------------------------------------*/ + unsigned int const allocWidth = ROUNDUP(width, 16); - if (width > UINT_MAX/4) + if (width > UINT_MAX/4 - 16) pm_error("Width %u pixels too large for arithmetic", width); rasterP->rowCount = height; @@ -209,16 +217,16 @@ allocateRaster(struct raster * const rasterP, We have yet to see if we can properly interpret the data. */ - rasterP->rowSize = width * 4; + rasterP->rowSize = allocWidth * 4; break; case 16: - rasterP->rowSize = width * 2; + rasterP->rowSize = allocWidth * 2; break; case 8: case 4: case 2: case 1: - rasterP->rowSize = width * 1; + rasterP->rowSize = allocWidth * 1; break; default: pm_error("INTERNAL ERROR: impossible bitsPerPixel value in " @@ -248,13 +256,30 @@ struct blit_info { struct raster srcplane; int pixSize; struct Rect dstRect; - struct RGBColor * color_map; + struct RGBColor * colorMap; int mode; struct blit_info * next; }; -static struct blit_info* blit_list = 0; -static struct blit_info** last_bl = &blit_list; +typedef struct { + struct blit_info * firstP; + struct blit_info ** connectorP; + bool unblittableText; + /* The image contains text opcodes, and we don't know how to put that + in a blit list (I really don't even know what a blit _is_), so + the image information here is incomplete. + */ +} blitList; + + +typedef void (drawFn)(struct canvas *, blitList *, int); + +struct opdef { + const char* name; + int len; + drawFn * impl; + const char* description; +}; #define WORD_LEN (-1) @@ -589,15 +614,25 @@ picComment(word const type, +static drawFn ShortComment; + static void -ShortComment(int const version) { +ShortComment(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + picComment(read_word(), 0); } +static drawFn LongComment; + static void -LongComment(int const version) { +LongComment(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + word type; type = read_word(); @@ -606,8 +641,13 @@ LongComment(int const version) { +static drawFn skip_poly_or_region; + static void -skip_poly_or_region(int const version) { +skip_poly_or_region(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + stage = "skipping polygon or region"; skip(read_word() - 2); } @@ -639,56 +679,98 @@ static struct fontinfo** fontlist_ins = &fontlist; +static void +tokenize(char * const s, + const char ** const vec, + unsigned int const vecSize, + unsigned int * const nTokenP) { + + unsigned int nToken; + char * p; + + p = &s[0]; /* start at beginning of string */ + nToken = 0; /* no tokens yet */ + + while (*p && nToken < vecSize - 1) { + if (ISSPACE(*p)) + *p++ = '\0'; + else { + vec[nToken++] = p; + /* Skip to next non-space character or end */ + while (*p && !ISSPACE(*p)) + ++p; + } + } + vec[nToken] = NULL; + + *nTokenP = nToken; +} + + + +static void +parseFontLine(const char ** const token, + struct fontinfo ** const fontinfoPP) { + + struct fontinfo * fontinfoP; + + MALLOCVAR(fontinfoP); + if (fontinfoP == NULL) + pm_error("out of memory for font information"); + MALLOCARRAY(fontinfoP->filename, strlen(token[3] + 1)); + if (fontinfoP->filename == NULL) + pm_error("out of memory for font information file name"); + + fontinfoP->font = atoi(token[0]); + fontinfoP->size = atoi(token[1]); + fontinfoP->style = atoi(token[2]); + strcpy(fontinfoP->filename, token[3]); + fontinfoP->loaded = 0; + + *fontinfoPP = fontinfoP; +} + + + static int load_fontdir(const char * const dirfile) { /*---------------------------------------------------------------------------- Load the font directory from file named 'dirfile'. Add its contents to the global list of fonts 'fontlist'. -----------------------------------------------------------------------------*/ - FILE* fp; - int n, nfont; - char* arg[5], line[1024]; - struct fontinfo* fontinfo; + FILE * ifP; + unsigned int nFont; + char line[1024]; - if (!(fp = fopen(dirfile, "rb"))) - return -1; - - nfont = 0; - while (fgets(line, 1024, fp)) { - if ((n = mk_argvn(line, arg, 5)) == 0 || arg[0][0] == '#') - continue; - if (n != 4) - continue; - MALLOCVAR(fontinfo); - if (fontinfo == NULL) - pm_error("out of memory for font information"); - MALLOCARRAY(fontinfo->filename, strlen(arg[3] + 1)); - if (fontinfo->filename == NULL) - pm_error("out of memory for font information file name"); + ifP = pm_openr(dirfile); - fontinfo->font = atoi(arg[0]); - fontinfo->size = atoi(arg[1]); - fontinfo->style = atoi(arg[2]); - strcpy(fontinfo->filename, arg[3]); - fontinfo->loaded = 0; + nFont = 0; + while (fgets(line, 1024, ifP) && nFont < INT_MAX) { + const char * token[10]; + unsigned int nToken; - fontinfo->next = 0; - *fontlist_ins = fontinfo; - fontlist_ins = &fontinfo->next; - nfont++; - } + tokenize(line, token, ARRAY_SIZE(token), &nToken); - return nfont; -} + if (nToken == 0) { + /* blank line - ignore */ + } else if (token[0][0] == '#') { + /* comment - ignore */ + } else if (nToken != 4) { + /* Unrecognized format - ignore */ + } else { + struct fontinfo * fontinfoP; + parseFontLine(token, &fontinfoP); + fontinfoP->next = 0; + *fontlist_ins = fontinfoP; + fontlist_ins = &fontinfoP->next; + ++nFont; + } + } + pm_close(ifP); -static void -read_rect(struct Rect * const r) { - r->top = read_word(); - r->left = read_word(); - r->bottom = read_word(); - r->right = read_word(); + return nFont; } @@ -705,6 +787,26 @@ dumpRect(const char * const label, +static void +read_rect(struct Rect * const r) { + + r->top = read_word(); + r->left = read_word(); + r->bottom = read_word(); + r->right = read_word(); + + if (r->top > r->bottom || r->right < r->left) + dumpRect("Invalid rectangle", *r); + + if (r->top > r->bottom) + pm_error("Invalid PICT: a rectangle has a top below its bottom"); + if (r->right < r->left) + pm_error("Invalid PICT: a rectangle has a right edge " + "left of its left edge"); +} + + + static int rectwidth(const struct Rect * const r) { return r->right - r->left; @@ -720,10 +822,10 @@ rectheight(const struct Rect * const r) { static bool -rectsamesize(const struct Rect * const r1, - const struct Rect * const r2) { - return r1->right - r1->left == r2->right - r2->left && - r1->bottom - r1->top == r2->bottom - r2->top ; +rectsamesize(struct Rect const r1, + struct Rect const r2) { + return r1.right - r1.left == r2.right - r2.left && + r1.bottom - r1.top == r2.bottom - r2.top ; } @@ -753,20 +855,45 @@ rectscale(struct Rect * const r, -static struct blit_info* -add_blit_list(void) { +static void + initBlitList(blitList * const blitListP) { - struct blit_info * bi; + blitListP->firstP = NULL; + blitListP->connectorP = &blitListP->firstP; + blitListP->unblittableText = false; +} + + + +static void +addBlitList(blitList * const blitListP, + struct Rect const srcRect, + struct Rect const srcBounds, + struct raster const srcplane, + int const pixSize, + struct Rect const dstRect, + struct RGBColor * const colorMap, + int const mode) { + + struct blit_info * biP; - MALLOCVAR(bi); - if (bi == NULL) + MALLOCVAR(biP); + if (biP == NULL) pm_error("out of memory for blit list"); - - bi->next = 0; - *last_bl = bi; - last_bl = &bi->next; - - return bi; + else { + biP->srcRect = srcRect; + biP->srcBounds = srcBounds; + biP->srcplane = srcplane; + biP->pixSize = pixSize; + biP->dstRect = dstRect; + biP->colorMap = colorMap; + biP->mode = mode; + + biP->next = NULL; + + *blitListP->connectorP = biP; + blitListP->connectorP = &biP->next; + } } @@ -1026,7 +1153,7 @@ static pixval redepth(pixval const c, pixval const oldMaxval) { - return (c * PPM_MAXMAXVAL + oldMaxval / 2) / oldMaxval; + return ROUNDDIV(c * PPM_MAXMAXVAL, oldMaxval); } @@ -1245,8 +1372,6 @@ doSameSize(transfer_func trf, struct rgbPlanes const dst, unsigned int const dstwid) { /*---------------------------------------------------------------------------- - Generalized (but slow) blit. - Transfer pixels from 'src' to 'dst', applying the transfer function 'trf'. @@ -1419,18 +1544,30 @@ blitIdempotent(unsigned int const pixSize, static void -generalBlit(struct Rect const srcRect, - struct Rect const srcBounds, - struct raster const srcplane, - int const pixSize, - struct Rect const dstRect, - struct Rect const dstBounds, - int const dstwid, - struct RGBColor * const color_map, - int const mode, - struct Rect const clipsrc, - struct Rect const clipdst) { - +doBlit(struct Rect const srcRect, + struct Rect const dstRect, + struct Rect const srcBounds, + struct raster const srcplane, + struct Rect const dstBounds, + struct rgbPlanes const canvasPlanes, + int const pixSize, + int const dstwid, + struct RGBColor * const color_map, + int const mode) { +/*---------------------------------------------------------------------------- + Transfer some pixels from 'srcplane' to 'canvasPlanes', applying the + transfer function 'trf'. + + 'srcplane' contains the rectangle 'srcBounds' of the image. + 'canvasPlanes' contains the rectangle 'dstRect' of the image. + + Take the rectangle 'srcRect' of the source image and copy it to the + rectangle 'dstRec' of the destination image. + + Each plane of 'canvasPlanes' is one word per pixel and contains actual + colors, never a palette index. It is an array in row-major order + with 'dstwid' words per row. +-----------------------------------------------------------------------------*/ unsigned char * src; struct rgbPlanes dst; int dstoff; @@ -1440,31 +1577,31 @@ generalBlit(struct Rect const srcRect, transfer_func trf; if (verbose) { - dumpRect("copying from:", clipsrc); - dumpRect("to: ", clipdst); + dumpRect("copying from:", srcRect); + dumpRect("to: ", dstRect); pm_message("a %u x %u area to a %u x %u area", - rectwidth(&clipsrc), rectheight(&clipsrc), - rectwidth(&clipdst), rectheight(&clipdst)); + rectwidth(&srcRect), rectheight(&srcRect), + rectwidth(&dstRect), rectheight(&dstRect)); } { unsigned int const pkpixsize = pixSize == 16 ? 2 : 1; - unsigned int const srcRowNumber = clipsrc.top - srcBounds.top; + unsigned int const srcRowNumber = srcRect.top - srcBounds.top; unsigned int const srcRowOffset = - (clipsrc.left - srcBounds.left) * pkpixsize; + (srcRect.left - srcBounds.left) * pkpixsize; assert(srcRowNumber < srcplane.rowCount); assert(srcRowOffset < srcplane.rowSize); src = srcplane.bytes + srcRowNumber * srcplane.rowSize + srcRowOffset; - xsize = clipsrc.right - clipsrc.left; - ysize = clipsrc.bottom - clipsrc.top; + xsize = rectwidth(&srcRect); + ysize = rectheight(&srcRect); srcadd = srcplane.rowSize - xsize * pkpixsize; } - dstoff = (clipdst.top - dstBounds.top) * dstwid + - (clipdst.left - dstBounds.left); - dst.red = red + dstoff; - dst.grn = green + dstoff; - dst.blu = blue + dstoff; + dstoff = (dstRect.top - dstBounds.top) * dstwid + + (dstRect.left - dstBounds.left); + dst.red = canvasPlanes.red + dstoff; + dst.grn = canvasPlanes.grn + dstoff; + dst.blu = canvasPlanes.blu + dstoff; /* get rid of Text mask mode bit, if (erroneously) set */ if ((mode & ~64) == 0) @@ -1472,8 +1609,8 @@ generalBlit(struct Rect const srcRect, else trf = transfer(mode & ~64); - if (!rectsamesize(&clipsrc, &clipdst)) - doDiffSize(clipsrc, clipdst, pixSize, xsize, ysize, + if (!rectsamesize(srcRect, dstRect)) + doDiffSize(srcRect, dstRect, pixSize, xsize, ysize, trf, color_map, src, srcplane.rowSize, dst, dstwid); else { if (trf == NULL) @@ -1491,12 +1628,22 @@ static int blit(struct Rect const srcRect, struct Rect const srcBounds, struct raster const srcplane, + struct canvas * const canvasP, + blitList * const blitListP, int const pixSize, struct Rect const dstRect, struct Rect const dstBounds, int const dstwid, struct RGBColor * const color_map, int const mode) { +/*---------------------------------------------------------------------------- + 'srcplane' contains the rectangle 'srcBounds' of the image. + + We transfer rectangle 'srcRect' from that. + + if 'blitListP' is non-null, we don't draw anything on 'canvasP'; instead, + we add to the list *blitlistP a description of what needs to be drawn. +-----------------------------------------------------------------------------*/ /* I can't tell what the result value of this function is supposed to mean, but I found several return statements that did not set it to anything, @@ -1511,9 +1658,7 @@ blit(struct Rect const srcRect, retval = 1; else { /* Almost got it. Clip source rect with source bounds. - clip dest rect with dest bounds. If source and - destination are not the same size, use Pnmscale - to get a nicely sized rectangle. + clip dest rect with dest bounds. */ struct Rect clipsrc; struct Rect clipdst; @@ -1521,22 +1666,16 @@ blit(struct Rect const srcRect, rectinter(srcBounds, srcRect, &clipsrc); rectinter(dstBounds, dstRect, &clipdst); - if (fullres) { - struct blit_info * bi; - bi = add_blit_list(); - bi->srcRect = clipsrc; - bi->srcBounds = srcBounds; - bi->srcplane = srcplane; - bi->pixSize = pixSize; - bi->dstRect = clipdst; - bi->color_map = color_map; - bi->mode = mode; + if (blitListP) { + addBlitList(blitListP, + clipsrc, srcBounds, srcplane, pixSize, + clipdst, color_map, mode); retval = 0; } else { - generalBlit(srcRect, srcBounds, srcplane, pixSize, - dstRect, dstBounds, dstwid, color_map, mode, - clipsrc, clipdst); + doBlit(clipsrc, clipdst, + srcBounds, srcplane, dstBounds, canvasP->planes, + pixSize, dstwid, color_map, mode); retval = 1; } @@ -1553,17 +1692,15 @@ blit(struct Rect const srcRect, */ static void -allocPlanes(struct rgbPlanes * const planesP) { - - struct rgbPlanes planes; +allocPlanes(unsigned int const width, + unsigned int const height, + struct rgbPlanes * const planesP) { - rowlen = picFrame.right - picFrame.left; - collen = picFrame.bottom - picFrame.top; + unsigned int const planelen = width * height; - clip_rect = picFrame; + struct rgbPlanes planes; - planelen = rowlen * collen; - MALLOCARRAY(planes.red, planelen); + MALLOCARRAY(planes.red, planelen); MALLOCARRAY(planes.grn, planelen); MALLOCARRAY(planes.blu, planelen); if (planes.red == NULL || planes.grn == NULL || planes.blu == NULL) @@ -1575,14 +1712,6 @@ allocPlanes(struct rgbPlanes * const planesP) { memset(planes.blu, 255, planelen * sizeof(word)); *planesP = planes; - - /* Until we wean this program off of global variables, we have to - set these: - */ - - red = planes.red; - green = planes.grn; - blue = planes.blu; } @@ -1606,9 +1735,31 @@ compact(word const input) { static void -do_blits(struct rgbPlanes * const planesP) { +reportBlitList(blitList * const blitListP) { + + if (verbose) { + unsigned int count; + struct blit_info * biP; + + for (count = 0, biP = blitListP->firstP; biP; biP = biP->next) + ++count; + + pm_message("# blits: %u", count); + } +} + + + +static void +doBlitList(struct canvas * const canvasP, + blitList * const blitListP) { +/*---------------------------------------------------------------------------- + Do the list of blits *blitListP, drawing on canvas *canvasP. - struct blit_info* bi; + We allocate new plane data structures in *canvasP. We assume it doesn't + have them already. +-----------------------------------------------------------------------------*/ + struct blit_info * bi; int srcwidth, dstwidth, srcheight, dstheight; double scale, scalelow, scalehigh; double xscale = 1.0; @@ -1616,9 +1767,11 @@ do_blits(struct rgbPlanes * const planesP) { double lowxscale, highxscale, lowyscale, highyscale; int xscalecalc = 0, yscalecalc = 0; + reportBlitList(blitListP); + fullres = 0; - for (bi = blit_list; bi; bi = bi->next) { + for (bi = blitListP->firstP; bi; bi = bi->next) { srcwidth = rectwidth(&bi->srcRect); dstwidth = rectwidth(&bi->dstRect); srcheight = rectheight(&bi->srcRect); @@ -1694,29 +1847,34 @@ do_blits(struct rgbPlanes * const planesP) { } if (xscale != 1.0 || yscale != 1.0) { - for (bi = blit_list; bi; bi = bi->next) - rectscale(&bi->dstRect, xscale, yscale); + struct blit_info * biP; + + for (biP = blitListP->firstP; biP; biP = biP->next) + rectscale(&biP->dstRect, xscale, yscale); - pm_message("Scaling output by %f in X and %f in Y", - xscale, yscale); + pm_message("Scaling output by %f in X and %f in Y", xscale, yscale); rectscale(&picFrame, xscale, yscale); } - allocPlanes(planesP); + rowlen = picFrame.right - picFrame.left; + collen = picFrame.bottom - picFrame.top; + + allocPlanes(rowlen, collen, &canvasP->planes); - for (bi = blit_list; bi; bi = bi->next) { - blit(bi->srcRect, bi->srcBounds, bi->srcplane, - bi->pixSize, - bi->dstRect, picFrame, rowlen, - bi->color_map, - bi->mode); + clip_rect = picFrame; + + for (bi = blitListP->firstP; bi; bi = bi->next) { + doBlit(bi->srcRect, bi->dstRect, + bi->srcBounds, bi->srcplane, picFrame, canvasP->planes, + bi->pixSize, rowlen, bi->colorMap, bi->mode); } } static void -outputPpm(struct rgbPlanes const planes) { +outputPpm(FILE * const ofP, + struct rgbPlanes const planes) { unsigned int width; unsigned int height; @@ -1732,7 +1890,7 @@ outputPpm(struct rgbPlanes const planes) { width = picFrame.right - picFrame.left; height = picFrame.bottom - picFrame.top; - ppm_writeppminit(stdout, width, height, PPM_MAXMAXVAL, 0); + ppm_writeppminit(ofP, width, height, PPM_MAXMAXVAL, 0); pixelrow = ppm_allocrow(width); srcCursor = 0; for (row = 0; row < height; ++row) { @@ -1745,9 +1903,8 @@ outputPpm(struct rgbPlanes const planes) { ); ++srcCursor; } - ppm_writeppmrow(stdout, pixelrow, width, PPM_MAXMAXVAL, 0); + ppm_writeppmrow(ofP, pixelrow, width, PPM_MAXMAXVAL, 0); } - pm_close(stdout); } @@ -1773,8 +1930,13 @@ get_op(int const version) { +static drawFn Clip; + static void -Clip(int const version) { +Clip(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + word len; len = read_word(); @@ -1791,8 +1953,13 @@ Clip(int const version) { +static drawFn OpColor; + static void -OpColor(int const version) { +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(); @@ -1806,17 +1973,17 @@ read_pixmap(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->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->pmTable = read_long(); p->pmReserved = read_long(); if (verbose) { @@ -1824,6 +1991,8 @@ read_pixmap(struct pixMap * const p) { pm_message("pixelSize: %d", p->pixelSize); pm_message("cmpCount: %d", p->cmpCount); pm_message("cmpSize: %d", p->cmpSize); + if (verbose) + dumpRect("Bounds:", p->Bounds); } if (p->pixelType != 0) @@ -1878,7 +2047,7 @@ read_color_table(void) { color_table[val].blu = read_word(); if (verbose > 1) - pm_message("%d: [%d,%d,%d]", val, + pm_message("Color %3u: [%u,%u,%u]", val, color_table[val].red, color_table[val].grn, color_table[val].blu); @@ -2084,6 +2253,42 @@ unpackUncompressedBits(FILE * const ifP, static void +reportValidateCompressedLineLen(unsigned int const row, + unsigned int const linelen, + unsigned int const rowSize) { +/*---------------------------------------------------------------------------- + 'row' is a row number in the raster. + + 'linelen' is the number of bytes of PICT that the PICT says hold the + compressed version of that row. + + 'rowSize' is the number of bytes we expect the uncompressed line to + be (includes pad pixels on the right). +-----------------------------------------------------------------------------*/ + if (verbose > 1) + pm_message("Row %u: %u-byte compressed line", row, linelen); + + /* When the line length value is garbage, it often causes the program to + try to read beyond EOF. To make that failure easier to diagnose, + we sanity check the line length now. + */ + + /* In the worst case, a pixel is represented by two bytes: a one byte + repeat count of one followed by a one byte pixel value (the byte could + be up to 8 pixels) or a one byte block length of one followed by the + pixel value. So expansion factor two. + */ + + if (linelen > rowSize * 2) + pm_error("Invalid PICT: compressed line of %u bytes for Row %u " + "is too big " + "to represent a %u-byte padded row, even with worse case " + "compression.", linelen, row, rowSize); +} + + + +static void expandRun(unsigned char * const block, unsigned int const blockLimit, unsigned int const bitsPerPixel, @@ -2099,6 +2304,9 @@ expandRun(unsigned char * const block, returned. -----------------------------------------------------------------------------*/ unsigned int const pkpixsize = bitsPerPixel == 16 ? 2 : 1; + /* The repetition unit size, in bytes. The run consists of this many + bytes of packed data repeated the specified number of times. + */ if (1 + pkpixsize > blockLimit) pm_error("PICT run block runs off the end of its line. " @@ -2114,14 +2322,28 @@ expandRun(unsigned char * const block, assert(block[0] & 0x80); /* It's a run */ if (verbose > 1) - pm_message("Block: run of %u pixels or plane samples", runLength); - + pm_message("Block: run of %u packed %u-byte units", + runLength, pkpixsize); + unpackBuf(&block[1], pkpixsize, bitsPerPixel, &bytePixels, &expandedByteCount); + + /* I assume in a legal PICT the run never has padding for the + case that the run is at the right edge of a row and the + remaining columns in the row don't fill whole bytes. + E.g. if there are 25 columns left in the row and 1 bit per + pixel, we won't see a run of 4 bytes and have to ignore the + last 7 pixels. Instead, we'll see a run of 3 bytes + followed by a non-run block for the remaining pixel. + + That is what I saw in a test image. + */ - if (expandedByteCount > expandedSize) + if (expandedByteCount * runLength > expandedSize) pm_error("Invalid PICT image. It contains a row with more pixels " - "than the width of the image"); + "than the width of the rectangle containing it, " + "even padded up to a " + "multiple of 16 pixels. Use -verbose to see details."); outputCursor = 0; for (i = 0; i < runLength; ++i) { @@ -2146,9 +2368,23 @@ copyPixelGroup(unsigned char * const block, unsigned int * const rasterBytesGeneratedP) { /*---------------------------------------------------------------------------- Copy a group of pixels (the data says, "take the following N pixels"). + + Copy them (unpacked) from block block[] to dest[]. + + block[] self-describes its length. Return that length as + *blockLengthP. + + block[] contains at most 'blockLimit' valid array elements, so if + the length information in block[] indicates the block is larger + than that, the block is corrupt. + + Return the number of pixels placed in dest[] as *rasterBytesGeneratedP. + + The output array dest[] has 'destSize' elements of space. Ignore + any pixels on the right that won't fit in that. -----------------------------------------------------------------------------*/ - unsigned int const pkpixsize = bitsPerPixel == 16 ? 2 : 1; - unsigned int const groupLen = block[0] + 1; + unsigned int const pkpixsize = bitsPerPixel == 16 ? 2 : 1; + unsigned int const groupLen = block[0] + 1; unsigned int const blockLength = 1 + groupLen * pkpixsize; if (blockLength > blockLimit) @@ -2159,22 +2395,35 @@ copyPixelGroup(unsigned char * const block, unsigned int i; unsigned char * bytePixels; /* Points to static storage */ unsigned int bytePixelLen; + unsigned int rasterBytesGenerated; assert(blockLimit >= 1); /* block[0] exists */ assert((block[0] & 0x80) == 0); /* It's not a run */ if (verbose > 1) - pm_message("Block: %u individual pixels or plane samples", - groupLen); + pm_message("Block: %u explicit packed %u-byte units", + groupLen, pkpixsize); unpackBuf(&block[1], groupLen * pkpixsize, bitsPerPixel, &bytePixels, &bytePixelLen); - - for (i = 0; i < MIN(bytePixelLen, destSize); ++i) + + /* It is normal for the above to return more pixels than there + are left in the row, because of padding. E.g. there is one + pixel left in the row, at one bit per pixel. But a block + contains full bytes, so it must contain at least 8 pixels. + 7 of them are padding, which we should ignore. + + BUT: I saw an image in which the block had _two_ data bytes + (16 pixels) when only 1 pixel remained in the row. I don't + understand why, but ignoring the 15 extra seemed to work. + */ + rasterBytesGenerated = MIN(bytePixelLen, destSize); + + for (i = 0; i < rasterBytesGenerated; ++i) dest[i] = bytePixels[i]; *blockLengthP = blockLength; - *rasterBytesGeneratedP = MIN(bytePixelLen, destSize); + *rasterBytesGeneratedP = rasterBytesGenerated; } } @@ -2218,12 +2467,83 @@ static unsigned int const maxPixelBytesPerBlock = 1024; static void +interpretCompressedLine(unsigned char * const linebuf, + unsigned int const linelen, + unsigned char * const rowRaster, + unsigned int const rowSize, + unsigned int const bitsPerPixel) { +/*---------------------------------------------------------------------------- + linebuf[] contains 'linelen' bytes from the PICT image that represents + one row of the image, in compressed format. Return the + uncompressed pixels of that row as rowRaster[]. + + rowRaster[] has 'rowSize' bytes of space. Caller ensures that + linebuf[] does not contain more pixels than that, unless the PICT + image from which it comes is corrupt. +-----------------------------------------------------------------------------*/ + unsigned int lineCursor; + /* Cursor into linebuf[] -- the compressed data */ + unsigned int rasterCursor; + /* Cursor into rowRaster[] -- the uncompressed data */ + + for (lineCursor = 0, rasterCursor = 0; lineCursor < linelen; ) { + unsigned int blockLength, rasterBytesGenerated; + + assert(lineCursor <= linelen); + + if (verbose > 2) + pm_message("At Byte %u of line, Column %u of row", + lineCursor, rasterCursor); + + interpretOneRasterBlock( + &linebuf[lineCursor], linelen - lineCursor, + bitsPerPixel, + &rowRaster[rasterCursor], rowSize - rasterCursor, + &blockLength, &rasterBytesGenerated); + + lineCursor += blockLength; + rasterCursor += rasterBytesGenerated; + assert(rasterCursor <= rowSize); + } + if (verbose > 1) + pm_message("Got %u pixels for row", rasterCursor); +} + + +/* There is some confusion about when, in PICT, a line length is one byte and + when it is two. An Apple document says it is two bytes when the number of + pixels in the row, padded, is > 250. Ppmtopict generated PICTs that way + until January 2009. Picttoppm assumed something similar until March 2004: + It assumed the line length is two bytes when the number of pixels > 250 _or_ + bits per pixel > 8. But in March 2004, Steve Summit did a bunch of + experiments on existing PICT files and found that they all worked with the + rule "pixels per row > 200 => 2 byte line length" and some did not work + with the original rule. + + So in March 2004, Picttoppm changed to pixels per row > 200. Ppmtopict + didn't catch up until January 2009. + + http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-460.html#HEADING460-0 + + Of course, neither 200 nor 250 make any logical sense. In the worst case, + you can represent 254 pixels of 8 bpp or less in a 255 byte line. + In the worst case, you can represent 127 16bpp pixels in a 255 byte line. + 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. + + Some day, we may have to make a user option for this. +*/ + + +static void unpackCompressedBits(FILE * const ifP, struct raster const raster, unsigned int const rowBytes, unsigned int const bitsPerPixel) { /*---------------------------------------------------------------------------- - Read the raster of on file *ifP and place it in 'raster'. + Read the raster on file *ifP and place it in 'raster'. The data in the file is compressed with run length encoding and possibly packed multiple pixels per byte as well. @@ -2232,11 +2552,13 @@ unpackCompressedBits(FILE * const ifP, "packing" and I don't know what packing is called. But we don't use that confusing terminology in this program, except when talking to the user. - - *boundsP describes the rectangle. -----------------------------------------------------------------------------*/ unsigned int const llsize = rowBytes > 200 ? 2 : 1; - unsigned int rowOfRect; + /* Width in bytes of the field at the beginning of a line that tells + how long (in bytes) the line is. See notes above about this + computation. + */ + unsigned int row; unsigned char * linebuf; unsigned int linebufSize; @@ -2245,20 +2567,17 @@ unpackCompressedBits(FILE * const ifP, if (linebuf == NULL) pm_error("can't allocate memory for line buffer"); - for (rowOfRect = 0; rowOfRect < raster.rowCount; ++rowOfRect) { + for (row = 0; row < raster.rowCount; ++row) { unsigned char * const rowRaster = - &raster.bytes[rowOfRect * raster.rowSize]; + &raster.bytes[row * raster.rowSize]; unsigned int linelen; - unsigned int lineCursor; - unsigned int rasterCursor; if (llsize == 2) linelen = read_word(); else linelen = read_byte(); - if (verbose > 1) - pm_message("linelen: %u", linelen); + reportValidateCompressedLineLen(row, linelen, raster.rowSize); if (linelen > linebufSize) { linebufSize = linelen; @@ -2268,23 +2587,8 @@ unpackCompressedBits(FILE * const ifP, } readBytes(ifP, linelen, linebuf); - for (lineCursor = 0, rasterCursor = 0; lineCursor < linelen; ) { - unsigned int blockLength, rasterBytesGenerated; - - assert(lineCursor <= linelen); - - interpretOneRasterBlock( - &linebuf[lineCursor], linelen - lineCursor, - bitsPerPixel, - &rowRaster[rasterCursor], raster.rowSize - rasterCursor, - &blockLength, &rasterBytesGenerated); - - lineCursor += blockLength; - rasterCursor += rasterBytesGenerated; - assert(rasterCursor <= raster.rowSize); - } - if (verbose > 1) - pm_message("row %u: got %u", rowOfRect, rasterCursor); + interpretCompressedLine(linebuf, linelen, rowRaster, raster.rowSize, + bitsPerPixel); } free(linebuf); } @@ -2386,21 +2690,42 @@ read_pattern(void) { /* these 3 do nothing but skip over their data! */ +static drawFn BkPixPat; + static void -BkPixPat(int const version) { +BkPixPat(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_pattern(); } + + +static drawFn PnPixPat; + static void -PnPixPat(int const version) { +PnPixPat(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_pattern(); } + + +static drawFn FillPixPat; + static void -FillPixPat(int const version) { +FillPixPat(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_pattern(); } + + static void read_8x8_pattern(struct Pattern * const pat) { unsigned char buf[8]; @@ -2424,29 +2749,49 @@ read_8x8_pattern(struct Pattern * const pat) { +static drawFn BkPat; + static void -BkPat(int const version) { +BkPat(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_8x8_pattern(&bkpat); } +static drawFn PnPat; + static void -PnPat(int const version) { +PnPat(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_8x8_pattern(&pen_pat); } +static drawFn FillPat; + static void -FillPat(int const version) { +FillPat(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_8x8_pattern(&fillpat); } +static drawFn PnSize; + static void -PnSize(int const version) { +PnSize(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + pen_height = read_word(); pen_width = read_word(); if (verbose) @@ -2455,8 +2800,12 @@ PnSize(int const version) { +static drawFn PnSize; + static void -PnMode(int const version) { +PnMode(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { pen_mode = read_word(); @@ -2480,8 +2829,13 @@ read_rgb(struct RGBColor * const rgb) { +static drawFn RGBFgCol; + static void -RGBFgCol(int const v) { +RGBFgCol(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_rgb(&foreground); if (verbose) pm_message("foreground now [%d,%d,%d]", @@ -2490,8 +2844,13 @@ RGBFgCol(int const v) { +static drawFn RGBBkCol; + static void -RGBBkCol(int const v) { +RGBBkCol(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_rgb(&background); if (verbose) pm_message("background now [%d,%d,%d]", @@ -2503,34 +2862,37 @@ RGBBkCol(int const v) { #define PIXEL_INDEX(x,y) ((y) - picFrame.top) * rowlen + (x) - picFrame.left static void -draw_pixel(int const x, - int const y, +draw_pixel(struct canvas * const canvasP, + int const x, + int const y, struct RGBColor * const clr, - transfer_func trf) { - - int i; - struct RGBColor dst; + transfer_func trf) { if (x < clip_rect.left || x >= clip_rect.right || - y < clip_rect.top || y >= clip_rect.bottom) - { - return; - } + y < clip_rect.top || y >= clip_rect.bottom) { + } else { + unsigned int const i = PIXEL_INDEX(x, y); + + struct RGBColor dst; + + dst.red = canvasP->planes.red[i]; + dst.grn = canvasP->planes.grn[i]; + dst.blu = canvasP->planes.blu[i]; + + (*trf)(clr, &dst); - i = PIXEL_INDEX(x, y); - dst.red = red[i]; - dst.grn = green[i]; - dst.blu = blue[i]; - (*trf)(clr, &dst); - red[i] = dst.red; - green[i] = dst.grn; - blue[i] = dst.blu; + canvasP->planes.red[i] = dst.red; + canvasP->planes.grn[i] = dst.grn; + canvasP->planes.blu[i] = dst.blu; + } } static void -draw_pen_rect(struct Rect * const r) { +draw_pen_rect(struct canvas * const canvasP, + struct Rect * const r) { + int const rowadd = rowlen - (r->right - r->left); int i; @@ -2541,16 +2903,18 @@ draw_pen_rect(struct Rect * const r) { for (y = r->top; y < r->bottom; y++) { for (x = r->left; x < r->right; x++) { - dst.red = red[i]; - dst.grn = green[i]; - dst.blu = blue[i]; + dst.red = canvasP->planes.red[i]; + dst.grn = canvasP->planes.grn[i]; + dst.blu = canvasP->planes.blu[i]; + if (pen_pat.pix[(x & 7) + (y & 7) * 8]) (*pen_trf)(&black, &dst); else (*pen_trf)(&white, &dst); - red[i] = dst.red; - green[i] = dst.grn; - blue[i] = dst.blu; + + canvasP->planes.red[i] = dst.red; + canvasP->planes.grn[i] = dst.grn; + canvasP->planes.blu[i] = dst.blu; i++; } @@ -2561,8 +2925,10 @@ draw_pen_rect(struct Rect * const r) { static void -draw_pen(int const x, - int const y) { +draw_pen(struct canvas * const canvasP, + int const x, + int const y) { + struct Rect penrect; penrect.left = x; @@ -2572,7 +2938,7 @@ draw_pen(int const x, rectinter(penrect, clip_rect, &penrect); - draw_pen_rect(&penrect); + draw_pen_rect(canvasP, &penrect); } /* @@ -2589,10 +2955,12 @@ draw_pen(int const x, * Paul Heckbert 3 Sep 85 */ static void -scan_line(short const x1, - short const y1, - short const x2, - short const y2) { +scan_line(struct canvas * const canvasP, + short const x1, + short const y1, + short const x2, + short const y2) { + int d, x, y, ax, ay, sx, sy, dx, dy; if (!(pen_width == 0 && pen_height == 0)) { @@ -2605,7 +2973,7 @@ scan_line(short const x1, if (ax>ay) { /* x dominant */ d = ay-(ax>>1); for (;;) { - draw_pen(x, y); + draw_pen(canvasP, x, y); if (x==x2) return; if ((x > rowlen) && (sx > 0)) return; if (d>=0) { @@ -2619,7 +2987,7 @@ scan_line(short const x1, else { /* y dominant */ d = ax-(ay>>1); for (;;) { - draw_pen(x, y); + draw_pen(canvasP, x, y); if (y==y2) return; if ((y > collen) && (sy > 0)) return; if (d>=0) { @@ -2635,137 +3003,178 @@ scan_line(short const x1, +static drawFn Line; + static void -Line(int const v) { +Line(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + struct Point p1; read_point(&p1); read_point(¤t); if (verbose) pm_message("(%d,%d) to (%d, %d)", p1.x,p1.y,current.x,current.y); - scan_line(p1.x,p1.y,current.x,current.y); + scan_line(canvasP, p1.x,p1.y,current.x,current.y); } +static drawFn LineFrom; + static void -LineFrom(int const v) { - struct Point p1; - read_point(&p1); - if (verbose) - pm_message("(%d,%d) to (%d, %d)", - current.x,current.y,p1.x,p1.y); +LineFrom(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + + struct Point p1; + read_point(&p1); + if (verbose) + pm_message("(%d,%d) to (%d, %d)", current.x, current.y, p1.x, p1.y); - if (!fullres) - scan_line(current.x,current.y,p1.x,p1.y); + if (!blitListP) + scan_line(canvasP, current.x, current.y, p1.x, p1.y); - current.x = p1.x; - current.y = p1.y; + current.x = p1.x; + current.y = p1.y; } +static drawFn ShortLine; + static void -ShortLine(int const v) { - struct Point p1; - read_point(&p1); - read_short_point(¤t); - if (verbose) - pm_message("(%d,%d) delta (%d, %d)", - p1.x,p1.y,current.x,current.y); - current.x += p1.x; - current.y += p1.y; +ShortLine(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { - if (!fullres) - scan_line(p1.x,p1.y,current.x,current.y); + struct Point p1; + read_point(&p1); + read_short_point(¤t); + if (verbose) + pm_message("(%d,%d) delta (%d, %d)", p1.x, p1.y, current.x, current.y); + current.x += p1.x; + current.y += p1.y; + + if (!blitListP) + scan_line(canvasP, p1.x, p1.y, current.x, current.y); } +static drawFn ShortLineFrom; + static void -ShortLineFrom(int const v) { - struct Point p1; - read_short_point(&p1); - if (verbose) - pm_message("(%d,%d) delta (%d, %d)", - current.x,current.y,p1.x,p1.y); - p1.x += current.x; - p1.y += current.y; - if (!fullres) - scan_line(current.x,current.y,p1.x,p1.y); - current.x = p1.x; - current.y = p1.y; +ShortLineFrom(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + + struct Point p1; + read_short_point(&p1); + if (verbose) + pm_message("(%d,%d) delta (%d, %d)", + current.x,current.y,p1.x,p1.y); + p1.x += current.x; + p1.y += current.y; + if (!blitListP) + scan_line(canvasP, current.x, current.y, p1.x, p1.y); + current.x = p1.x; + current.y = p1.y; } + + static void -do_paintRect(struct Rect const prect) { +do_paintRect(struct canvas * const canvasP, + struct Rect const prect) { + struct Rect rect; - if (fullres) - return; - if (verbose) dumpRect("painting", prect); rectinter(clip_rect, prect, &rect); - draw_pen_rect(&rect); + draw_pen_rect(canvasP, &rect); } +static drawFn paintRect; + static void -paintRect(int const v) { +paintRect(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_rect(&cur_rect); - do_paintRect(cur_rect); + if (!blitListP) + do_paintRect(canvasP, cur_rect); } +static drawFn paintSameRect; + static void -paintSameRect(int const v) { - do_paintRect(cur_rect); +paintSameRect(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + + if (!blitListP) + do_paintRect(canvasP, cur_rect); } static void -do_frameRect(struct Rect const rect) { - int x, y; +do_frameRect(struct canvas * const canvasP, + struct Rect const rect) { - if (fullres) - return; - if (verbose) dumpRect("framing", rect); - if (pen_width == 0 || pen_height == 0) - return; - - for (x = rect.left; x <= rect.right - pen_width; x += pen_width) { - draw_pen(x, rect.top); - draw_pen(x, rect.bottom - pen_height); - } + if (pen_width > 0 && pen_height > 0) { + unsigned int x, y; - for (y = rect.top; y <= rect.bottom - pen_height ; y += pen_height) { - draw_pen(rect.left, y); - draw_pen(rect.right - pen_width, y); + for (x = rect.left; x <= rect.right - pen_width; x += pen_width) { + draw_pen(canvasP, x, rect.top); + draw_pen(canvasP, x, rect.bottom - pen_height); + } + + for (y = rect.top; y <= rect.bottom - pen_height ; y += pen_height) { + draw_pen(canvasP, rect.left, y); + draw_pen(canvasP, rect.right - pen_width, y); + } } } +static drawFn frameRect; + static void -frameRect(int const v) { +frameRect(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + read_rect(&cur_rect); - do_frameRect(cur_rect); + if (!blitListP) + do_frameRect(canvasP, cur_rect); } +static drawFn frameSameRect; + static void -frameSameRect(int const v) { - do_frameRect(cur_rect); +frameSameRect(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + + if (!blitListP) + do_frameRect(canvasP, cur_rect); } @@ -2806,8 +3215,10 @@ poly_sort(int const sort_index, struct Point points[]) { /* Watch out for the lack of error checking in the next two functions ... */ static void -scan_poly(int const np, - struct Point pts[]) { +scan_poly(struct canvas * const canvasP, + int const np, + struct Point pts[]) { + int dx,dy,dxabs,dyabs,i,scan_index,j,k,px,py; int sdx,sdy,x,y,toggle,old_sdy,sy0; @@ -2860,7 +3271,7 @@ scan_poly(int const np, scan_index++; } px += sdx; - draw_pen(px, py); + draw_pen(canvasP, px, py); } } else @@ -2876,7 +3287,7 @@ scan_poly(int const np, old_sdy = sdy; if (sdy != 0) scan_index--; } - draw_pen(px,py); + draw_pen(canvasP, px,py); coord[scan_index].x = px; coord[scan_index].y = py; scan_index++; @@ -2896,7 +3307,7 @@ scan_poly(int const np, if ((coord[i].y == coord[i+1].y) && (toggle == 0)) { for (j = coord[i].x; j <= coord[i+1].x; j++) - draw_pen(j, coord[i].y); + draw_pen(canvasP, j, coord[i].y); toggle = 1; } else @@ -2905,9 +3316,14 @@ scan_poly(int const np, } + +static drawFn paintPoly; static void -paintPoly(int const v) { +paintPoly(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + struct Rect bb; struct Point pts[100]; int i, np = (read_word() - 10) >> 2; @@ -2917,14 +3333,19 @@ paintPoly(int const v) { read_point(&pts[i]); /* scan convert poly ... */ - if (!fullres) - scan_poly(np, pts); + if (!blitListP) + scan_poly(canvasP, np, pts); } +static drawFn PnLocHFrac; + static void -PnLocHFrac(int const version) { +PnLocHFrac(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + word frac = read_word(); if (verbose) @@ -2933,8 +3354,13 @@ PnLocHFrac(int const version) { +static drawFn TxMode; + static void -TxMode(int const version) { +TxMode(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + text_mode = read_word(); if (text_mode >= 8 && text_mode < 15) @@ -2949,8 +3375,13 @@ TxMode(int const version) { +static drawFn TxFont; + static void -TxFont(int const version) { +TxFont(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + text_font = read_word(); if (verbose) pm_message("text font %s", const_name(font_name, text_font)); @@ -2958,8 +3389,13 @@ TxFont(int const version) { +static drawFn TxFace; + static void -TxFace(int const version) { +TxFace(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + text_face = read_byte(); if (verbose) pm_message("text face %d", text_face); @@ -2967,8 +3403,13 @@ TxFace(int const version) { +static drawFn TxSize; + static void -TxSize(int const version) { +TxSize(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + text_size = read_word(); if (verbose) pm_message("text size %d", text_size); @@ -2977,8 +3418,11 @@ TxSize(int const version) { static void -skip_text(void) { +skip_text(blitList * const blitListP) { + skip(read_byte()); + + blitListP->unblittableText = true; } @@ -2997,6 +3441,7 @@ static struct font* get_font(int const font, int const size, int const style) { + int closeness, bestcloseness; struct fontinfo* fi, *best; @@ -3058,8 +3503,10 @@ rotate(int * const x, static void -do_ps_text(word const tx, - word const ty) { +do_ps_text(struct canvas * const canvasP, + word const tx, + word const ty) { + int len, width, i, w, h, x, y, rx, ry, o; byte str[256], ch; struct glyph* glyph; @@ -3110,9 +3557,9 @@ do_ps_text(word const tx, { o = PIXEL_INDEX(rx, ry); if (glyph->bmap[h * glyph->width + w]) { - red[o] = foreground.red; - green[o] = foreground.grn; - blue[o] = foreground.blu; + canvasP->planes.red[o] = foreground.red; + canvasP->planes.grn[o] = foreground.grn; + canvasP->planes.blu[o] = foreground.blu; } } } @@ -3125,16 +3572,19 @@ do_ps_text(word const tx, static void -do_text(word const startx, - word const starty) { - if (fullres) - skip_text(); +do_text(struct canvas * const canvasP, + blitList * const blitListP, + word const startx, + word const starty) { + + if (blitListP) + skip_text(blitListP); else { if (!(tfont = get_font(text_font, text_size, text_face))) tfont = pbm_defaultfont("bdf"); if (ps_text) - do_ps_text(startx, starty); + do_ps_text(canvasP, startx, starty); else { int len; word x, y; @@ -3154,7 +3604,8 @@ do_text(word const startx, struct RGBColor * const colorP = glyph->bmap[h * glyph->width + w] ? &black : &white; - draw_pixel(x + w + glyph->x, dy, colorP, text_trf); + draw_pixel(canvasP, + x + w + glyph->x, dy, colorP, text_trf); } } x += glyph->xadd; @@ -3168,34 +3619,56 @@ do_text(word const startx, +static drawFn LongText; + static void -LongText(int const version) { +LongText(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + struct Point p; read_point(&p); - do_text(p.x, p.y); + + do_text(canvasP, blitListP, p.x, p.y); } +static drawFn DHText; + static void -DHText(int const version) { +DHText(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + current.x += read_byte(); - do_text(current.x, current.y); + + do_text(canvasP, blitListP, current.x, current.y); } +static drawFn DVText; + static void -DVText(int const version) { +DVText(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + current.y += read_byte(); - do_text(current.x, current.y); + + do_text(canvasP, blitListP, current.x, current.y); } +static drawFn DHDVText; + static void -DHDVText(int const version) { +DHDVText(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { byte dh, dv; dh = read_byte(); @@ -3206,7 +3679,8 @@ DHDVText(int const version) { current.x += dh; current.y += dv; - do_text(current.x, current.y); + + do_text(canvasP, blitListP, current.x, current.y); } @@ -3216,8 +3690,10 @@ DHDVText(int const version) { */ static void -directBits(unsigned int const pictVersion, - bool const skipRegion) { +directBits(struct canvas * const canvasP, + blitList * const blitListP, + unsigned int const pictVersion, + bool const skipRegion) { struct pixMap p; struct Rect srcRect; @@ -3257,11 +3733,11 @@ directBits(unsigned int const pictVersion, pm_message("transfer mode = %s", const_name(transfer_name, mode)); if (skipRegion) - skip_poly_or_region(pictVersion); + skip_poly_or_region(canvasP, blitListP, pictVersion); unpackbits(ifp, &p.Bounds, 0, p.pixelSize, &raster); - blit(srcRect, p.Bounds, raster, p.pixelSize, + blit(srcRect, p.Bounds, raster, canvasP, blitListP, p.pixelSize, dstRect, picFrame, rowlen, NULL, mode); freeRaster(raster); @@ -3272,26 +3748,36 @@ directBits(unsigned int const pictVersion, #define SKIP_REGION_TRUE TRUE #define SKIP_REGION_FALSE FALSE +static drawFn DirectBitsRect; + static void -DirectBitsRect(int const version) { +DirectBitsRect(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { - directBits(version, SKIP_REGION_FALSE); + directBits(canvasP, blitListP, version, SKIP_REGION_FALSE); } +static drawFn DirectBitsRgn; + static void -DirectBitsRgn(int const version) { +DirectBitsRgn(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { - directBits(version, SKIP_REGION_TRUE); + directBits(canvasP, blitListP, version, SKIP_REGION_TRUE); } static void -do_pixmap(int const version, - word const rowBytes, - int const is_region) { +do_pixmap(struct canvas * const canvasP, + blitList * const blitListP, + int const version, + word const rowBytes, + int const is_region) { /*---------------------------------------------------------------------------- Do a paletted image. -----------------------------------------------------------------------------*/ @@ -3327,13 +3813,13 @@ do_pixmap(int const version, pm_message("transfer mode = %s", const_name(transfer_name, mode)); if (is_region) - skip_poly_or_region(version); + skip_poly_or_region(canvasP, blitListP, version); stage = "unpacking rectangle"; unpackbits(ifp, &p.Bounds, rowBytes, p.pixelSize, &raster); - blit(srcRect, p.Bounds, raster, 8, + blit(srcRect, p.Bounds, raster, canvasP, blitListP, 8, dstRect, picFrame, rowlen, color_table, mode); free(color_table); @@ -3343,17 +3829,25 @@ do_pixmap(int const version, static void -do_bitmap(int const version, - int const rowBytes, - int const is_region) { +do_bitmap(FILE * const ifP, + struct canvas * const canvasP, + blitList * const blitListP, + int const version, + int const rowBytes, + int const is_region) { /*---------------------------------------------------------------------------- Do a bitmap. That's one bit per pixel, 0 is white, 1 is black. + + Read the raster from file 'ifP'. -----------------------------------------------------------------------------*/ struct Rect Bounds; struct Rect srcRect; struct Rect dstRect; word mode; struct raster raster; + /* This raster contains padding on the right to make a multiple + of 16 pixels per row. + */ static struct RGBColor color_table[] = { {65535L, 65535L, 65535L}, {0, 0, 0} }; @@ -3365,13 +3859,13 @@ do_bitmap(int const version, pm_message("transfer mode = %s", const_name(transfer_name, mode)); if (is_region) - skip_poly_or_region(version); + skip_poly_or_region(canvasP, blitListP, version); stage = "unpacking rectangle"; - unpackbits(ifp, &Bounds, rowBytes, 1, &raster); + unpackbits(ifP, &Bounds, rowBytes, 1, &raster); - blit(srcRect, Bounds, raster, 8, + blit(srcRect, Bounds, raster, canvasP, blitListP, 8, dstRect, picFrame, rowlen, color_table, mode); freeRaster(raster); @@ -3379,8 +3873,12 @@ do_bitmap(int const version, +static drawFn BitsRect; + static void -BitsRect(int const version) { +BitsRect(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { word rowBytesWord; bool pixMap; @@ -3392,16 +3890,20 @@ BitsRect(int const version) { interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes); if (pixMap) - do_pixmap(version, rowBytes, 0); + do_pixmap(canvasP, blitListP, version, rowBytes, 0); else - do_bitmap(version, rowBytes, 0); + do_bitmap(ifp, canvasP, blitListP, version, rowBytes, 0); } -static void -BitsRegion(int const version) { +static drawFn BitsRegion; +static void +BitsRegion(struct canvas * const canvasP, + blitList * const blitListP, + int const version) { + word rowBytesWord; bool pixMap; unsigned int rowBytes; @@ -3412,9 +3914,9 @@ BitsRegion(int const version) { interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes); if (pixMap) - do_pixmap(version, rowBytes, 1); + do_pixmap(canvasP, blitListP, version, rowBytes, 1); else - do_bitmap(version, rowBytes, 1); + do_bitmap(ifp, canvasP, blitListP, version, rowBytes, 1); } @@ -3597,14 +4099,85 @@ static struct opdef const optable[] = { static void -interpret_pict(void) { +processOpcode(word const opcode, + struct canvas * const canvasP, + blitList * const blitListP, + unsigned int const version) { + + if (opcode < 0xa2) { + stage = optable[opcode].name; + if (verbose) { + if (streq(stage, "reserved")) + pm_message("reserved opcode=0x%x", opcode); + else + pm_message("Opcode: %s", optable[opcode].name); + } + + if (optable[opcode].impl != NULL) + (*optable[opcode].impl)(canvasP, blitListP, version); + else if (optable[opcode].len >= 0) + skip(optable[opcode].len); + else { + switch (optable[opcode].len) { + case WORD_LEN: { + word const len = read_word(); + skip(len); + } break; + default: + pm_error("can't do length %u", optable[opcode].len); + } + } + } else if (opcode == 0xc00) { + if (verbose) + pm_message("HeaderOp"); + stage = "HeaderOp"; + skip(24); + } else if (opcode >= 0xa2 && opcode <= 0xaf) { + stage = "skipping reserved"; + if (verbose) + pm_message("%s 0x%x", stage, opcode); + skip(read_word()); + } else if (opcode >= 0xb0 && opcode <= 0xcf) { + /* just a reserved opcode, no data */ + if (verbose) + pm_message("reserved 0x%x", opcode); + } else if (opcode >= 0xd0 && opcode <= 0xfe) { + stage = "skipping reserved"; + if (verbose) + pm_message("%s 0x%x", stage, opcode); + skip(read_long()); + } 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 */ + 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()); + } else + pm_error("This program does not understand opcode 0x%04x", opcode); +} + + + +static void +interpret_pict(FILE * const ofP) { + byte ch; word picSize; word opcode; - word len; unsigned int version; int i; - struct rgbPlanes planes; + struct canvas canvas; + blitList blitList; + + initBlitList(&blitList); for (i = 0; i < 64; i++) pen_pat.pix[i] = bkpat.pix[i] = fillpat.pix[i] = 1; @@ -3618,20 +4191,26 @@ interpret_pict(void) { picSize = read_word(); if (verbose) - pm_message("picture size = %d (0x%x)", picSize, picSize); + pm_message("picture size = %u (0x%x)", picSize, picSize); stage = "reading picture frame"; read_rect(&picFrame); if (verbose) { dumpRect("Picture frame:", picFrame); - pm_message("Picture size is %d x %d", - picFrame.right - picFrame.left, - picFrame.bottom - picFrame.top); + pm_message("Picture size is %u x %u", + picFrame.right - picFrame.left, + picFrame.bottom - picFrame.top); } - if (!fullres) - allocPlanes(&planes); + if (!fullres) { + rowlen = picFrame.right - picFrame.left; + collen = picFrame.bottom - picFrame.top; + + allocPlanes(rowlen, collen, &canvas.planes); + + clip_rect = picFrame; + } while ((ch = read_byte()) == 0) ; @@ -3657,71 +4236,35 @@ interpret_pict(void) { if (verbose) pm_message("PICT version %u", version); - while((opcode = get_op(version)) != 0xff) { - if (opcode < 0xa2) { - stage = optable[opcode].name; - if (verbose) { - if (STREQ(stage, "reserved")) - pm_message("reserved opcode=0x%x", opcode); - else - pm_message("Opcode: %s", optable[opcode].name); - } - - if (optable[opcode].impl != NULL) - (*optable[opcode].impl)(version); - else if (optable[opcode].len >= 0) - skip(optable[opcode].len); - else switch (optable[opcode].len) { - case WORD_LEN: - len = read_word(); - skip(len); - break; - default: - pm_error("can't do length %u", optable[opcode].len); - } - } else if (opcode == 0xc00) { - if (verbose) - pm_message("HeaderOp"); - stage = "HeaderOp"; - skip(24); - } else if (opcode >= 0xa2 && opcode <= 0xaf) { - stage = "skipping reserved"; - if (verbose) - pm_message("%s 0x%x", stage, opcode); - skip(read_word()); - } else if (opcode >= 0xb0 && opcode <= 0xcf) { - /* just a reserved opcode, no data */ - if (verbose) - pm_message("reserved 0x%x", opcode); - } else if (opcode >= 0xd0 && opcode <= 0xfe) { - stage = "skipping reserved"; - if (verbose) - pm_message("%s 0x%x", stage, opcode); - skip(read_long()); - } 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 */ - 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()); - } else - pm_error("This program does not understand opcode 0x%04x", opcode); - } + while((opcode = get_op(version)) != 0xff) + processOpcode(opcode, &canvas, fullres ? &blitList : NULL, version); - if (fullres) - do_blits(&planes); + if (fullres) { + if (blitList.unblittableText) + pm_message("Warning: text is omitted from the output because " + "we don't know how to do text with -fullres."); + doBlitList(&canvas, &blitList); + } + outputPpm(ofP, canvas.planes); + + freePlanes(canvas.planes); +} + + - outputPpm(planes); +static void +loadDefaultFontDir(void) { +/*---------------------------------------------------------------------------- + Load the fonts from the font directory file "fontdir" (in the current + directory), if it exists. +-----------------------------------------------------------------------------*/ + struct stat statbuf; + int rc; - freePlanes(planes); + rc = stat("fontdir", &statbuf); + + if (rc == 0) + load_fontdir("fontdir"); } @@ -3762,8 +4305,6 @@ main(int argc, char * argv[]) { ++argn; } - load_fontdir("fontdir"); - if (argn < argc) { ifp = pm_openr(argv[argn]); ++argn; @@ -3773,12 +4314,17 @@ main(int argc, char * argv[]) { if (argn != argc) pm_usage(usage); + loadDefaultFontDir(); + if (header) { stage = "Reading 512 byte header"; + /* Note that the "header" in PICT is entirely comment! */ skip(512); } - interpret_pict(); + interpret_pict(stdout); + + pm_close(stdout); return 0; } diff --git a/converter/ppm/ppmtoarbtxt.c b/converter/ppm/ppmtoarbtxt.c index fe466ea5..df859c84 100644 --- a/converter/ppm/ppmtoarbtxt.c +++ b/converter/ppm/ppmtoarbtxt.c @@ -24,6 +24,10 @@ typedef enum { WIDTH, HEIGHT, POSX, POSY } SKL_OBJ_TYP; +typedef enum { + OBJTYP_ICOLOR, OBJTYP_FCOLOR, OBJTYP_INT, OBJTYP_BDATA +} SKL_OBJ_CLASS; + /* Maximum size for a format string ("%d" etc.) */ #define MAXFORMAT 16 @@ -158,257 +162,328 @@ save_bin_data(int const ndat, +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 */ -static SKL_OBJ *save_icol_data (ctyp,format,icolmin,icolmax) -SKL_OBJ_TYP ctyp; -char *format; -int icolmin, icolmax; -{SKL_OBJ *obj; + SKL_OBJ * objP; - obj = (SKL_OBJ *)malloc (sizeof (SKL_OBJ)); - if (obj != NULL) - { - obj->otyp = ctyp; - strcpy (obj->odata.icol_data.icformat,format); - obj->odata.icol_data.icolmin = icolmin; - obj->odata.icol_data.icolmax = icolmax; - } - return (obj); + 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 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 */ -static SKL_OBJ *save_fcol_data (ctyp,format,fcolmin,fcolmax) -SKL_OBJ_TYP ctyp; -char *format; -double fcolmin, fcolmax; -{SKL_OBJ *obj; + SKL_OBJ * objP; - obj = (SKL_OBJ *)malloc (sizeof (SKL_OBJ)); - if (obj != NULL) - { - obj->otyp = ctyp; - strcpy (obj->odata.fcol_data.fcformat,format); - obj->odata.fcol_data.fcolmin = fcolmin; - obj->odata.fcol_data.fcolmax = fcolmax; - } - return (obj); + 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 SKL_OBJ * +save_i_data(SKL_OBJ_TYP const ctyp, + const char * const format) { + /* Save universal data in Object */ -static SKL_OBJ *save_i_data (ctyp,format) -SKL_OBJ_TYP ctyp; -char *format; -{SKL_OBJ *obj; + SKL_OBJ * objP; - obj = (SKL_OBJ *)malloc (sizeof (SKL_OBJ)); - if (obj != NULL) - { - obj->otyp = ctyp; - strcpy (obj->odata.i_data.iformat,format); - } - return (obj); + MALLOCVAR(objP); + if (objP) { + objP->otyp = ctyp; + strcpy(objP->odata.i_data.iformat, format); + } + return objP; } -/* Read skeleton file */ -static int read_skeleton (filename,maxskl,nskl,skl) -char *filename; -int maxskl,*nskl; -SKL_OBJ **skl; -{FILE *sklfile; - int slen, objlen, chr, n_odata; - int icolmin,icolmax; - double fcolmin,fcolmax; - SKL_OBJ_TYP otyp; - char line[MAX_LINE_BUF+MAX_OBJ_BUF+16]; - char objstr[MAX_OBJ_BUF],typstr[MAX_OBJ_BUF]; - char formstr[MAX_OBJ_BUF]; - char meta1 = '#', meta2 = '(', meta3 = ')'; +static char const escape = '#'; -#define SAVE_BIN(slen,line) \ - { if ((skl[*nskl] = save_bin_data (slen,line)) != NULL) (*nskl)++; \ - slen = 0; } -#define ADD_STR(slen,line,addlen,addstr) \ - {int count=0; line[slen++] = meta1; line[slen++] = meta2; \ - while (count++ < addlen) line[slen++] = addstr[count]; } - if ((sklfile = fopen (filename,"r")) == NULL) - return (-1); +static SKL_OBJ_TYP +interpretObjType(const char * const typstr) { - /* Parse skeleton file */ - *nskl = 0; + SKL_OBJ_TYP otyp; - slen = 0; - while ((chr = getc (sklfile)) != EOF) /* Up to end of skeleton file */ - { - if (*nskl >= maxskl) return (-1); + /* 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; - if (slen+1 >= MAX_LINE_BUF) /* Buffer finished ? Save as binary object */ - { - SAVE_BIN (slen,line); - } + return otyp; +} - if (chr != meta1) /* Look for start of replacement string */ - { - line[slen++] = chr; - continue; - } - if ((chr = getc (sklfile)) == EOF) - { - line[slen++] = meta1; - break; - } - if (chr != meta2) /* '(' ? Otherwise no replacement */ - { - line[slen++] = meta1; - line[slen++] = chr; - continue; - } - objlen = 0; - for (;;) /* Read replacement string up to ')' */ - { - if (objlen == sizeof (objstr)-1) break; /* ')' not found */ - if ((chr = getc (sklfile)) == EOF) break; - if (chr == meta3) break; - objstr[objlen++] = chr; - } - objstr[objlen] = '\0'; /* Now objstr keeps data without metas */ +static SKL_OBJ_CLASS +objClass(SKL_OBJ_TYP const otyp) { - if (chr != meta3) /* Object not found ? */ - { - ADD_STR (slen,line,objlen,objstr); /* Save what we already read */ - if (chr == EOF) break; - continue; - } + switch (otyp) { + case IRED: + case IGREEN: + case IBLUE: + case ILUM: + return OBJTYP_ICOLOR; - typstr[0] = '\0'; /* Get typ of data */ - sscanf (objstr,"%s",typstr); - - /* 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; - - if ((otyp == IRED) || (otyp == IGREEN) || (otyp == IBLUE) || (otyp == ILUM)) - { - n_odata = sscanf (objstr,"%*s%s%d%d",formstr,&icolmin,&icolmax); - - if (n_odata == EOF) /* No arguments specified ? Use defaults */ - { - strcpy (formstr,"%d"); icolmin = 0; icolmax = 255; - } - else if (n_odata != 3) /* Wrong specification */ - { - otyp = BDATA; - } - } + case FRED: + case FGREEN: + case FBLUE: + case FLUM: + return OBJTYP_FCOLOR; - if ((otyp == FRED) || (otyp == FGREEN) || (otyp == FBLUE) || (otyp == FLUM)) - { - n_odata = sscanf (objstr,"%*s%s%lf%lf",formstr,&fcolmin,&fcolmax); - - if (n_odata == EOF) /* No arguments specified ? Use defaults */ - { - strcpy (formstr,"%f"); fcolmin = 0.0; fcolmax = 1.0; - } - else if (n_odata != 3) /* Wrong specification */ - { - otyp = BDATA; - } - } + case WIDTH: + case HEIGHT: + case POSX: + case POSY: + return OBJTYP_INT; + case BDATA: + return OBJTYP_BDATA; + } + return 999; /* quiet compiler warning */ +} - if ( (otyp == WIDTH) || (otyp == HEIGHT) - || (otyp == POSX) || (otyp == POSY)) - { - n_odata = sscanf (objstr,"%*s%s",formstr); - - if (n_odata == EOF) /* No arguments specified ? Use defaults */ - { - strcpy (formstr,"%d"); - } - else if (n_odata != 1) /* Wrong specification */ - { - otyp = BDATA; - } - } - if (otyp != BDATA) /* Got an object definition ? */ - { - if (slen > 0) /* Save what we already found */ - { - SAVE_BIN (slen,line); - } - } - /* Now process the object in objstr */ - switch (otyp) - { - case BDATA: /* Bad object definition ? Save as text */ - ADD_STR (slen,line,objlen,objstr); - break; +static void +addImpostorReplacementSeq(char * const line, + unsigned int const startCursor, + const char * const seqContents, + unsigned int const seqContentsLen, + unsigned int * const newCursorP) { +/*---------------------------------------------------------------------------- + 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, - case IRED: - case IGREEN: - case IBLUE: - case ILUM: - skl[*nskl] = save_icol_data (otyp,formstr,icolmin,icolmax); - if (skl[*nskl] != NULL) (*nskl)++; - break; + "#(fread x)" - case FRED: - case FGREEN: - case FBLUE: - case FLUM: - skl[*nskl] = save_fcol_data (otyp,formstr,fcolmin,fcolmax); - if (skl[*nskl] != NULL) (*nskl)++; - break; + seqContents[] is the contents; 'seqContentsLen' its length. - case WIDTH: - case HEIGHT: - case POSX: - case POSY: - skl[*nskl] = save_i_data (otyp,formstr); - if (skl[*nskl] != NULL) (*nskl)++; - break; - } - } /* EOF of skeleton file */ + Return as *newCursorP where the line[] cursor ends up after adding + the sequence. +-----------------------------------------------------------------------------*/ + unsigned int cursor; + unsigned int i; - if (slen > 0) /* Drop finishing newline character */ - { - if (line[slen-1] == '\n') slen--; - } + cursor = startCursor; - if (slen > 0) /* Something left ? */ - { - SAVE_BIN (slen,line); /* Save it */ - } + line[cursor++] = escape; + line[cursor++] = '('; - fclose (sklfile); - return (0); + for (i = 0; i < seqContentsLen; ++i) + line[cursor++] = seqContents[i]; + + line[cursor++] = ')'; + + *newCursorP = cursor; } + +static int +read_skeleton(const char * const filename, + unsigned int const maxskl, + unsigned int * const nsklP, + SKL_OBJ ** const skl) { +/*---------------------------------------------------------------------------- + Read skeleton file +-----------------------------------------------------------------------------*/ + 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 (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; + } + /* Read replacement string up through ')'. Put contents of + parentheses in objstr[]. + */ + 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); + } + } /* EOF of skeleton file */ + + if (slen >= 1 && line[slen-1] == '\n') + /* Drop finishing newline character */ + --slen; + + SAVE_BIN(slen, line); /* Save whatever is left */ + + *nsklP = nskl; + + fclose(sklfile); + return 0; +} + + + int main( argc, argv ) int argc; char* argv[]; @@ -419,7 +494,7 @@ char* argv[]; pixval maxval,red,green,blue; double dmaxval; int argn, rows, cols, format, row; - int head_nskl,body_nskl,tail_nskl; + 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]; diff --git a/converter/ppm/ppmtobmp.c b/converter/ppm/ppmtobmp.c index 071f3b12..9075ad6d 100644 --- a/converter/ppm/ppmtobmp.c +++ b/converter/ppm/ppmtobmp.c @@ -18,15 +18,24 @@ #include <assert.h> #include <string.h> -#include "bmp.h" -#include "ppm.h" + +#include "pm_c_util.h" +#include "mallocvar.h" #include "shhopt.h" +#include "bmp.h" #include "bitio.h" +#include "ppm.h" #define MAXCOLORS 256 enum colortype {TRUECOLOR, PALETTE}; +struct rgb { + unsigned char red; + unsigned char grn; + unsigned char blu; +}; + typedef struct { /*---------------------------------------------------------------------------- A color map for a BMP file. @@ -34,13 +43,13 @@ typedef struct { unsigned int count; /* Number of colors in the map. The first 'count' elements of these arrays are defined; all others are not. + + At most MAXCOLORS. */ colorhash_table cht; - /* Indices in the following arrays are the same as in 'cht', above. */ - unsigned char red[MAXCOLORS]; - unsigned char grn[MAXCOLORS]; - unsigned char blu[MAXCOLORS]; + /* Indices in the following array are the same as in 'cht', above. */ + struct rgb bmpMap[MAXCOLORS]; } colorMap; @@ -54,7 +63,7 @@ freeColorMap(const colorMap * const colorMapP) { -static struct cmdline_info { +struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -62,63 +71,71 @@ static struct cmdline_info { int class; /* C_WIN or C_OS2 */ unsigned int bppSpec; unsigned int bpp; -} cmdline; + const char * mapfile; +}; static void -parse_command_line(int argc, char ** argv, - struct cmdline_info *cmdline_p) { +parseCommandLine(int argc, const char ** argv, + struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that many of the strings that this function returns in the *cmdline_p structure are actually in the supplied argv array. And sometimes, one of these strings is actually just a suffix of an entry in argv! -----------------------------------------------------------------------------*/ - optEntry *option_def = malloc(100*sizeof(optEntry)); + optEntry * option_def; /* Instructions to OptParseOptions3 on how to parse our options. */ optStruct3 opt; - unsigned int windowsSpec, os2Spec; + unsigned int windowsSpec, os2Spec, mapfileSpec; unsigned int option_def_index; + + MALLOCARRAY(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3('w', "windows", OPT_FLAG, NULL, &windowsSpec, 0); OPTENT3('o', "os2", OPT_FLAG, NULL, &os2Spec, 0); - OPTENT3(0, "bpp", OPT_UINT, &cmdline_p->bpp, - &cmdline_p->bppSpec, 0); + OPTENT3(0, "bpp", OPT_UINT, &cmdlineP->bpp, + &cmdlineP->bppSpec, 0); + OPTENT3(0, "mapfile", OPT_STRING, &cmdlineP->mapfile, + &mapfileSpec, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); if (windowsSpec && os2Spec) pm_error("Can't specify both -windows and -os2 options."); else if (windowsSpec) - cmdline_p->class = C_WIN; + cmdlineP->class = C_WIN; else if (os2Spec) - cmdline_p->class = C_OS2; + cmdlineP->class = C_OS2; else - cmdline_p->class = C_WIN; + cmdlineP->class = C_WIN; - if (cmdline_p->bppSpec) { - if (cmdline_p->bpp != 1 && cmdline_p->bpp != 4 && - cmdline_p->bpp != 8 && cmdline_p->bpp != 24) - pm_error("Invalid -bpp value specified: %u. The only values valid\n" + if (cmdlineP->bppSpec) { + if (cmdlineP->bpp != 1 && cmdlineP->bpp != 4 && + cmdlineP->bpp != 8 && cmdlineP->bpp != 24) + pm_error("Invalid -bpp value specified: %u. The only values valid " "in the BMP format are 1, 4, 8, and 24 bits per pixel", - cmdline_p->bpp); + cmdlineP->bpp); } + if (!mapfileSpec) + cmdlineP->mapfile = NULL; + if (argc - 1 == 0) - cmdline_p->input_filename = strdup("-"); /* he wants stdin */ + cmdlineP->input_filename = strdup("-"); /* he wants stdin */ else if (argc - 1 == 1) - cmdline_p->input_filename = strdup(argv[1]); + cmdlineP->input_filename = strdup(argv[1]); else - pm_error("Too many arguments. The only argument accepted\n" + pm_error("Too many arguments. The only argument accepted " "is the input file specificaton"); } @@ -243,7 +260,7 @@ BMPwriteinfoheader(FILE * const fp, static int -BMPwritergb(FILE * const fp, +BMPwriteRgb(FILE * const fp, int const class, pixval const R, pixval const G, @@ -264,7 +281,7 @@ BMPwritergb(FILE * const fp, PutByte(fp, R); return 3; default: - pm_error(er_internal, "BMPwritergb"); + pm_error(er_internal, "BMPwriteRgb"); } return -1; } @@ -272,101 +289,118 @@ BMPwritergb(FILE * const fp, static int -BMPwritecolormap(FILE * const ifP, +BMPwriteColormap(FILE * const ifP, int const class, int const bpp, const colorMap * const colorMapP) { /*---------------------------------------------------------------------------- Return the number of bytes written, or -1 on error. -----------------------------------------------------------------------------*/ - long const ncolors = (1 << bpp); + unsigned int const ncolors = (1 << bpp); - unsigned int nbyte; - unsigned int i; + unsigned int nbyte; + unsigned int i; - nbyte = 0; - for (i = 0; i < colorMapP->count; ++i) - nbyte += BMPwritergb(ifP, class, - colorMapP->red[i], - colorMapP->grn[i], - colorMapP->blu[i]); + assert(ncolors <= MAXCOLORS); + assert(ncolors <= ARRAY_SIZE(colorMapP->bmpMap)); + nbyte = 0; + for (i = 0; i < colorMapP->count; ++i) { + const struct rgb * const mapEntryP = &colorMapP->bmpMap[i]; + nbyte += BMPwriteRgb(ifP, class, + mapEntryP->red, mapEntryP->grn, mapEntryP->blu); + } for (; i < ncolors; ++i) - nbyte += BMPwritergb(ifP, class, 0, 0, 0); + nbyte += BMPwriteRgb(ifP, class, 0, 0, 0); return nbyte; } -static int -BMPwriterow_palette(FILE * const fp, +static void +lookupColor(colorhash_table const cht, + pixel const color, + unsigned int * const colorIndexP) { + + int rc; + + rc = ppm_lookupcolor(cht, &color); + + if (rc < 0) + pm_error("Color (%u,%u,%u) is not in the provided palette", + PPM_GETR(color), PPM_GETG(color), PPM_GETB(color)); + else + *colorIndexP = rc; +} + + + +static void +bmpWriteRow_palette(FILE * const fp, const pixel * const row, - unsigned long const cx, + unsigned int const cols, unsigned short const bpp, - colorhash_table const cht) { + colorhash_table const cht, + unsigned int * const nBytesP) { /*---------------------------------------------------------------------------- - Return the number of bytes written, or -1 on error. + Write a row to the raster in paletted format. + + Return the number of bytes written as *nBytesP. -----------------------------------------------------------------------------*/ - BITSTREAM b; - int retval; + BITSTREAM b; b = pm_bitinit(fp, "w"); if (b == NULL) - retval = -1; + pm_error("Failed to initialize output file for output"); else { + int rc; unsigned int nbyte; - unsigned int x; - bool error; + unsigned int col; nbyte = 0; /* initial value */ - error = FALSE; /* initial value */ - for (x = 0; x < cx && !error; ++x) { + for (col = 0; col < cols; ++col) { + unsigned int colorIndex; int rc; - rc = pm_bitwrite(b, bpp, ppm_lookupcolor(cht, &row[x])); + + lookupColor(cht, row[col], &colorIndex); + + rc = pm_bitwrite(b, bpp, colorIndex); if (rc == -1) - error = TRUE; + pm_error("Failed in writing a pixel " + "to the raster in the output file"); else nbyte += rc; } - if (error) - retval = -1; - else { - int rc; - rc = pm_bitfini(b); - if (rc == -1) - retval = -1; - else { - nbyte += rc; + rc = pm_bitfini(b); + + nbyte += rc; - /* Make sure we write a multiple of 4 bytes. */ - while (nbyte % 4 != 0) { - PutByte(fp, 0); - ++nbyte; - } - retval = nbyte; - } + /* Make sure we write a multiple of 4 bytes. */ + while (nbyte % 4 != 0) { + PutByte(fp, 0); + ++nbyte; } + *nBytesP = nbyte; } - return retval; } -static int -BMPwriterow_truecolor(FILE * const fp, - const pixel * const row, - unsigned long const cols, - pixval const maxval) { +static void +bmpWriteRow_truecolor(FILE * const fp, + const pixel * const row, + unsigned long const cols, + pixval const maxval, + unsigned int * const nBytesP) { /*---------------------------------------------------------------------------- Write a row of a truecolor BMP image to the file 'fp'. The row is 'row', which is 'cols' columns long. - Return the number of bytes written. - On error, issue error message and exit program. + Return the number of bytes written as *nBytesP. -----------------------------------------------------------------------------*/ /* This works only for 24 bits per pixel. To implement this for the general case (which is only hypothetical -- this program doesn't @@ -380,7 +414,7 @@ BMPwriterow_truecolor(FILE * const fp, int col; nbyte = 0; /* initial value */ - for (col = 0; col < cols; col++) { + for (col = 0; col < cols; ++col) { /* We scale to the BMP maxval, which is always 255. */ PutByte(fp, PPM_GETB(row[col]) * 255 / maxval); PutByte(fp, PPM_GETG(row[col]) * 255 / maxval); @@ -393,18 +427,18 @@ BMPwriterow_truecolor(FILE * const fp, */ while (nbyte % 4) { PutByte(fp, 0); - nbyte++; + ++nbyte; } - return nbyte; + *nBytesP = nbyte; } static int BMPwritebits(FILE * const fp, - unsigned long const cx, - unsigned long const cy, + unsigned long const cols, + unsigned long const rows, enum colortype const colortype, unsigned short const cBitCount, const pixel ** const pixels, @@ -413,29 +447,29 @@ BMPwritebits(FILE * const fp, /*---------------------------------------------------------------------------- Return the number of bytes written, or -1 on error. -----------------------------------------------------------------------------*/ - int nbyte; - long y; + unsigned int nbyte; + int row; if (cBitCount > 24) - pm_error("cannot handle cBitCount: %d", cBitCount); + pm_error("cannot handle cBitCount: %hu", cBitCount); nbyte = 0; /* initial value */ /* The picture is stored bottom line first, top line last */ - for (y = cy - 1; y >= 0; --y) { - int rc; + for (row = rows - 1; row >= 0; --row) { + unsigned int nBytesThisRow; + if (colortype == PALETTE) - rc = BMPwriterow_palette(fp, pixels[y], cx, - cBitCount, cht); + bmpWriteRow_palette(fp, pixels[row], cols, + cBitCount, cht, &nBytesThisRow); else - rc = BMPwriterow_truecolor(fp, pixels[y], cx, maxval); + bmpWriteRow_truecolor(fp, pixels[row], cols, maxval, + &nBytesThisRow); - if (rc == -1) - pm_error("couldn't write row %ld", y); - if (rc % 4 != 0) - pm_error("row had bad number of bytes: %d", rc); - nbyte += rc; + if (nBytesThisRow % 4 != 0) + pm_error("row had bad number of bytes: %u", nBytesThisRow); + nbyte += nBytesThisRow; } return nbyte; @@ -444,10 +478,10 @@ BMPwritebits(FILE * const fp, static void -BMPEncode(FILE * const ifP, +bmpEncode(FILE * const ifP, int const class, enum colortype const colortype, - int const bpp, + unsigned int const bpp, int const x, int const y, const pixel ** const pixels, @@ -459,25 +493,25 @@ BMPEncode(FILE * const ifP, unsigned long nbyte; if (colortype == PALETTE) - pm_message("Writing %d bits per pixel with a color palette", bpp); + pm_message("Writing %u bits per pixel with a color palette", bpp); else - pm_message("Writing %d bits per pixel truecolor (no palette)", bpp); + pm_message("Writing %u bits per pixel truecolor (no palette)", bpp); nbyte = 0; /* initial value */ nbyte += BMPwritefileheader(ifP, class, bpp, x, y); nbyte += BMPwriteinfoheader(ifP, class, bpp, x, y); if (colortype == PALETTE) - nbyte += BMPwritecolormap(ifP, class, bpp, colorMapP); + nbyte += BMPwriteColormap(ifP, class, bpp, colorMapP); if (nbyte != (BMPlenfileheader(class) + BMPleninfoheader(class) + BMPlencolormap(class, bpp, -1))) - pm_error(er_internal, "BMPEncode 1"); + pm_error(er_internal, "BmpEncode 1"); nbyte += BMPwritebits(ifP, x, y, colortype, bpp, pixels, maxval, colorMapP->cht); if (nbyte != BMPlenfile(class, bpp, -1, x, y)) - pm_error(er_internal, "BMPEncode 2"); + pm_error(er_internal, "BmpEncode 2"); } @@ -487,18 +521,18 @@ makeBilevelColorMap(colorMap * const colorMapP) { colorMapP->count = 2; colorMapP->cht = NULL; - colorMapP->red[0] = 0; - colorMapP->grn[0] = 0; - colorMapP->blu[0] = 0; - colorMapP->red[1] = 255; - colorMapP->grn[1] = 255; - colorMapP->blu[1] = 255; + colorMapP->bmpMap[0].red = 0; + colorMapP->bmpMap[0].grn = 0; + colorMapP->bmpMap[0].blu = 0; + colorMapP->bmpMap[1].red = 255; + colorMapP->bmpMap[1].grn = 255; + colorMapP->bmpMap[1].blu = 255; } static void -BMPEncodePBM(FILE * const ifP, +bmpEncodePbm(FILE * const ifP, int const class, int const cols, int const rows, @@ -508,7 +542,7 @@ BMPEncodePBM(FILE * const ifP, -----------------------------------------------------------------------------*/ /* Note: Only PBM input uses this routine. Color images represented by 1 bpp via - color palette use the general BMPEncode(). + color palette use the general bmpEncode(). */ unsigned int const adjustedCols = (cols + 31) / 32 * 32; unsigned int const packedBytes = adjustedCols / 8; @@ -526,12 +560,12 @@ BMPEncodePBM(FILE * const ifP, makeBilevelColorMap(&bilevelColorMap); - nbyte += BMPwritecolormap(ifP, class, 1, &bilevelColorMap); + nbyte += BMPwriteColormap(ifP, class, 1, &bilevelColorMap); if (nbyte != (BMPlenfileheader(class) + BMPleninfoheader(class) + BMPlencolormap(class, 1, -1))) - pm_error(er_internal, "BMPEncodePBM 1"); + pm_error(er_internal, "bmpEncodePBM 1"); for (row = 0; row < rows; ++row){ size_t bytesWritten; @@ -548,23 +582,129 @@ BMPEncodePBM(FILE * const ifP, } if (nbyte != BMPlenfile(class, 1, -1, cols, rows)) - pm_error(er_internal, "BMPEncodePBM 2"); + pm_error(er_internal, "bmpEncodePbm 2"); } static void -analyze_colors(const pixel ** const pixels, - int const cols, - int const rows, - pixval const maxval, - int * const minimum_bpp_p, - colorMap * const colorMapP) { +makeHashFromBmpMap(const struct rgb * const bmpMap, + unsigned int const nColors, + colorhash_table * const chtP) { + + colorhist_vector chv; + unsigned int i; + + MALLOCARRAY_NOFAIL(chv, nColors); + + for (i = 0; i < nColors; ++i) { + const struct rgb * const mapEntryP = &bmpMap[i]; + + PPM_ASSIGN(chv[i].color, + mapEntryP->red, mapEntryP->grn, mapEntryP->blu); + } + + *chtP = ppm_colorhisttocolorhash(chv, nColors); + + ppm_freecolorhist(chv); +} + + + +static unsigned int +minBmpBitsForColorCount(unsigned int const colorCount) { + + unsigned int const minbits = pm_maxvaltobits(colorCount - 1); + + /* Only 1, 4, 8, and 24 are defined in the BMP spec we + implement and other bpp's have in fact been seen to confuse + viewers. There is an extended BMP format that has 16 bpp + too, but this program doesn't know how to generate that + (see Bmptopnm.c, though). + */ + if (minbits == 1) + return 1; + else if (minbits <= 4) + return 4; + else if (minbits <= 8) + return 8; + else + return 24; +} + + + +static void +getMapFile(const char * const mapFileName, + unsigned int * const minimumBppP, + colorMap * const colorMapP) { +/*---------------------------------------------------------------------------- + Get the color map (palette) for the BMP from file 'mapFileName'. + + Return the color map as *colormapP. + + Return as *minimumBppP the minimum number of bits per pixel it will + take to represent all the colors in the map in the BMP format. +-----------------------------------------------------------------------------*/ + + FILE * mapFileP; + int cols, rows; + pixval maxval; + pixel ** pixels; + unsigned int row; + unsigned int count; + + mapFileP = pm_openr(mapFileName); + + pixels = ppm_readppm(mapFileP, &cols, &rows, &maxval); + + if (cols * rows > MAXCOLORS) + pm_error("The colormap file you gave (-mapfile) has too " + "many entries for a BMP. A BMP can have at most " + "%u colors; the file has %u pixels, each of which " + "represents an entry in the color map.", + MAXCOLORS, cols * rows); + + count = 0; /* initial value */ + + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + pixel const color = pixels[row][col]; + struct rgb * const mapEntryP = &colorMapP->bmpMap[count++]; + + assert(count <= ARRAY_SIZE(colorMapP->bmpMap)); + + mapEntryP->red = PPM_GETR(color) * 255 / maxval; + mapEntryP->grn = PPM_GETG(color) * 255 / maxval; + mapEntryP->blu = PPM_GETB(color) * 255 / maxval; + } + } + ppm_freearray(pixels, rows); + + colorMapP->count = count; + + makeHashFromBmpMap(colorMapP->bmpMap, colorMapP->count, &colorMapP->cht); + + *minimumBppP = minBmpBitsForColorCount(count); + + pm_close(mapFileP); +} + + + +static void +analyzeColors(const pixel ** const pixels, + int const cols, + int const rows, + pixval const maxval, + unsigned int * const minimumBppP, + colorMap * const colorMapP) { /*---------------------------------------------------------------------------- Look at the colors in the image 'pixels' and compute values to use in representing those colors in a BMP image. - First of all, count the distinct colors. Return as *minimum_bpp_p + First of all, count the distinct colors. Return as *minimumBppP the minimum number of bits per pixel it will take to represent all the colors in BMP format. @@ -589,37 +729,23 @@ analyze_colors(const pixel ** const pixels, colorMapP->count = colorCount; if (chv == NULL) { pm_message("More than %u colors found", MAXCOLORS); - *minimum_bpp_p = 24; + *minimumBppP = 24; colorMapP->cht = NULL; } else { - unsigned int const minbits = pm_maxvaltobits(colorMapP->count - 1); - unsigned int i; pm_message("%u colors found", colorMapP->count); - /* Only 1, 4, 8, and 24 are defined in the BMP spec we - implement and other bpp's have in fact been seen to confuse - viewers. There is an extended BMP format that has 16 bpp - too, but this program doesn't know how to generate that - (see Bmptopnm.c, though). - */ - if (minbits == 1) - *minimum_bpp_p = 1; - else if (minbits <= 4) - *minimum_bpp_p = 4; - else if (minbits <= 8) - *minimum_bpp_p = 8; - else - *minimum_bpp_p = 24; + *minimumBppP = minBmpBitsForColorCount(colorMapP->count); /* * Now scale the maxval to 255 as required by BMP format. */ for (i = 0; i < colorMapP->count; ++i) { - colorMapP->red[i] = (pixval) PPM_GETR(chv[i].color) * 255 / maxval; - colorMapP->grn[i] = (pixval) PPM_GETG(chv[i].color) * 255 / maxval; - colorMapP->blu[i] = (pixval) PPM_GETB(chv[i].color) * 255 / maxval; + struct rgb * const mapEntryP = &colorMapP->bmpMap[i]; + mapEntryP->red = (pixval) PPM_GETR(chv[i].color) * 255 / maxval; + mapEntryP->grn = (pixval) PPM_GETG(chv[i].color) * 255 / maxval; + mapEntryP->blu = (pixval) PPM_GETB(chv[i].color) * 255 / maxval; } /* And make a hash table for fast lookup. */ @@ -631,38 +757,52 @@ analyze_colors(const pixel ** const pixels, static void -choose_colortype_bpp(struct cmdline_info const cmdline, - unsigned int const colors, - unsigned int const minimum_bpp, - enum colortype * const colortype_p, - unsigned int * const bits_per_pixel_p) { +chooseColortypeBpp(bool const userRequestsBpp, + unsigned int const requestedBpp, + unsigned int const minimumBpp, + enum colortype * const colortypeP, + unsigned int * const bitsPerPixelP) { +/*---------------------------------------------------------------------------- + Determine whether the BMP raster should contain RGB values or palette + indices and how many bits is should have for each pixel. - if (!cmdline.bppSpec) { + 'userRequestsBpp' says the user has requested a particular number of + bits per pixel. 'requestedBpp' is his request, and we assume it's a + valid value for a BMP. + + 'colors' is how many colors are in the image. + + 'minimumBpp' is the minimum number of bits it takes to represent all + the colors in the image. We assume it is valid for a BMP. + + We return our choices as *colortypeP and *bitsPerPixelP. +-----------------------------------------------------------------------------*/ + if (!userRequestsBpp) { /* User has no preference as to bits per pixel. Choose the smallest number possible for this image. */ - *bits_per_pixel_p = minimum_bpp; + *bitsPerPixelP = minimumBpp; } else { - if (cmdline.bpp < minimum_bpp) + if (requestedBpp < minimumBpp) pm_error("There are too many colors in the image to " - "represent in the\n" - "number of bits per pixel you requested: %d.\n" - "You may use Ppmquant to reduce the number of " + "represent in the " + "number of bits per pixel you requested: %d. " + "You may use Pnmquant to reduce the number of " "colors in the image.", - cmdline.bpp); + requestedBpp); else - *bits_per_pixel_p = cmdline.bpp; + *bitsPerPixelP = requestedBpp; } - assert(*bits_per_pixel_p == 1 || - *bits_per_pixel_p == 4 || - *bits_per_pixel_p == 8 || - *bits_per_pixel_p == 24); + assert(*bitsPerPixelP == 1 || + *bitsPerPixelP == 4 || + *bitsPerPixelP == 8 || + *bitsPerPixelP == 24); - if (*bits_per_pixel_p > 8) - *colortype_p = TRUECOLOR; + if (*bitsPerPixelP > 8) + *colortypeP = TRUECOLOR; else { - *colortype_p = PALETTE; + *colortypeP = PALETTE; } } @@ -676,12 +816,12 @@ doPbm(FILE * const ifP, int const class, FILE * const ofP) { - /* In the PBM case the raster is read directly from the input by - pbm_readpbmrow_packed. The raster format is almost identical, - except that BMP specifies rows to be zero-filled to 32 bit borders - and that in BMP the bottom row comes first in order. + /* We read the raster directly from the input with + pbm_readpbmrow_packed(). The raster format is almost + identical, except that BMP specifies rows to be zero-filled to + 32 bit borders and that in BMP the bottom row comes first in + order. */ - int const CHARBITS = (sizeof(unsigned char)*8); int const colChars = pbm_packed_bytes(cols); int const adjustedCols = (cols+31) /32 * 32; @@ -709,7 +849,7 @@ doPbm(FILE * const ifP, thisRow[i] = ~thisRow[i]; /* flip all pixels */ } /* This may seem unnecessary, because the color palette - (RGB[] in BMPEncodePBM) can be inverted for the same effect. + (RGB[] in bmpEncodePbm) can be inverted for the same effect. However we take this precaution, for there is indication that some BMP viewers may get confused with that. */ @@ -721,25 +861,28 @@ doPbm(FILE * const ifP, } } - BMPEncodePBM(ofP, class, cols, rows, bitrow); + bmpEncodePbm(ofP, class, cols, rows, bitrow); } static void -doPgmPpm(FILE * const ifP, +doPgmPpm(FILE * const ifP, unsigned int const cols, unsigned int const rows, pixval const maxval, int const ppmFormat, int const class, + bool const userRequestsBpp, + unsigned int const requestedBpp, + const char * const mapFileName, FILE * const ofP) { - /* PGM and PPM. The input image is read into a PPM array, scanned - for color analysis and converted to a BMP raster. - Logic works for PBM. + /* PGM and PPM. We read the input image into a PPM array, scan it + to analyze the colors, and convert it to a BMP raster. Logic + works for PBM. */ - int minimumBpp; + unsigned int minimumBpp; unsigned int bitsPerPixel; enum colortype colortype; unsigned int row; @@ -752,13 +895,16 @@ doPgmPpm(FILE * const ifP, for (row = 0; row < rows; ++row) ppm_readppmrow(ifP, pixels[row], cols, maxval, ppmFormat); - analyze_colors((const pixel**)pixels, cols, rows, maxval, - &minimumBpp, &colorMap); + if (mapFileName) + getMapFile(mapFileName, &minimumBpp, &colorMap); + else + analyzeColors((const pixel**)pixels, cols, rows, maxval, + &minimumBpp, &colorMap); - choose_colortype_bpp(cmdline, colorMap.count, minimumBpp, &colortype, - &bitsPerPixel); + chooseColortypeBpp(userRequestsBpp, requestedBpp, minimumBpp, + &colortype, &bitsPerPixel); - BMPEncode(stdout, class, colortype, bitsPerPixel, + bmpEncode(ofP, class, colortype, bitsPerPixel, cols, rows, (const pixel**)pixels, maxval, &colorMap); freeColorMap(&colorMap); @@ -767,17 +913,19 @@ doPgmPpm(FILE * const ifP, int -main(int argc, char **argv) { +main(int argc, + const char ** argv) { + struct cmdlineInfo cmdline; FILE * ifP; int rows; int cols; pixval maxval; int ppmFormat; - ppm_init(&argc, argv); + pm_proginit(&argc, argv); - parse_command_line(argc, argv, &cmdline); + parseCommandLine(argc, argv, &cmdline); ifP = pm_openr(cmdline.input_filename); @@ -786,7 +934,9 @@ main(int argc, char **argv) { if (PPM_FORMAT_TYPE(ppmFormat) == PBM_TYPE) doPbm(ifP, cols, rows, ppmFormat, cmdline.class, stdout); else - doPgmPpm(ifP, cols, rows, maxval, ppmFormat, cmdline.class, stdout); + doPgmPpm(ifP, cols, rows, maxval, ppmFormat, + cmdline.class, cmdline.bppSpec, cmdline.bpp, cmdline.mapfile, + stdout); pm_close(ifP); pm_close(stdout); diff --git a/converter/ppm/ppmtogif.c b/converter/ppm/ppmtogif.c index 21ac1989..93feaa95 100644 --- a/converter/ppm/ppmtogif.c +++ b/converter/ppm/ppmtogif.c @@ -1,101 +1,63 @@ -/* ppmtogif.c - read a portable pixmap and produce a GIF file -** -** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A -** Lempel-Zim compression based on "compress". -** -** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl> -** -** The non-LZW GIF generation stuff was adapted from the Independent -** JPEG Group's djpeg on 2001.09.29. The uncompressed output subroutines -** are derived directly from the corresponding subroutines in djpeg's -** wrgif.c source file. Its copyright notice say: - - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - The reference README file is README.JPEG in the Netpbm package. -** -** Copyright (C) 1989 by Jef Poskanzer. -** -** Permission to use, copy, modify, and distribute this software and its -** documentation for any purpose and without fee is hereby granted, provided -** that the above copyright notice appear in all copies and that both that -** copyright notice and this permission notice appear in supporting -** documentation. This software is provided "as is" without express or -** implied warranty. -** -** The Graphics Interchange Format(c) is the Copyright property of -** CompuServe Incorporated. GIF(sm) is a Service Mark property of -** CompuServe Incorporated. -*/ +/* This is a backward compatibility interface to Pamtogif. + + Pamtogif replaced Ppmtogif in Netpbm 10.37 (December 2006). + + The only significant ways Pamtogif are not backward compatible with + old Ppmtogif are: -/* TODO: merge the LZW and uncompressed subroutines. They are separate - only because they had two different lineages and the code is too - complicated for me quickly to rewrite it. + - Pamtogif does not have a -alpha option. + + - Pamtogif requires a user-specififed map file (-mapfile) to + match the input in depth. */ +#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 <stdio.h> +#include <sys/stat.h> +#include <unistd.h> +#include "pm_c_util.h" #include "mallocvar.h" #include "shhopt.h" -#include "ppm.h" +#include "nstring.h" +#include "pam.h" -#define MAXCMAPSIZE 256 -static unsigned int const gifMaxval = 255; -static bool verbose; -/* - * a code_int must be able to hold 2**BITS values of type int, and also -1 - */ -typedef int code_int; +static const char * +dirname(const char * const fileName) { -typedef long int count_int; + char * buffer; + char * slashPos; + buffer = strdup(fileName); + + slashPos = strchr(buffer, '/'); + + if (slashPos) + *slashPos = '\0'; + + return buffer; +} -struct cmap { - /* This is the information for the GIF colormap (aka palette). */ - int red[MAXCMAPSIZE], green[MAXCMAPSIZE], blue[MAXCMAPSIZE]; - /* These arrays arrays map a color index, as is found in - the raster part of the GIF, to an intensity value for the indicated - RGB component. - */ - int perm[MAXCMAPSIZE], permi[MAXCMAPSIZE]; - /* perm[i] is the position in the sorted colormap of the color which - is at position i in the unsorted colormap. permi[] is the inverse - function of perm[]. - */ - int cmapsize; - /* Number of entries in the GIF colormap. I.e. number of colors - in the image, plus possibly one fake transparency color. - */ - int transparent; - /* color index number in GIF palette of the color that is to be - transparent. -1 if no color is transparent. - */ - colorhash_table cht; - /* A hash table that relates a PPM pixel value to to a pre-sort - GIF colormap index. - */ - pixval maxval; - /* The maxval for the colors in 'cht'. */ -}; struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char *input_filespec; /* Filespec of input file */ - const char *alpha_filespec; /* Filespec of alpha file; NULL if none */ - const char *alphacolor; /* -alphacolor option value or default */ - unsigned int interlace; /* -interlace option value */ - unsigned int sort; /* -sort option value */ + const char *inputFileName; /* Name of input file */ + const char *alpha_filespec; /* Filespec of alpha file; NULL if none */ + const char *alphacolor; /* -alphacolor option value or default */ + unsigned int interlace; /* -interlace option value */ + unsigned int sort; /* -sort option value */ const char *mapfile; /* -mapfile option value. NULL if none. */ const char *transparent; /* -transparent option value. NULL if none. */ const char *comment; /* -comment option value; NULL if none */ - unsigned int nolzw; /* -nolzw option */ + unsigned int nolzw; /* -nolzw option */ unsigned int verbose; }; @@ -122,8 +84,8 @@ handleLatex2htmlHack(void) { -Bryan 2001.11.14 -----------------------------------------------------------------------------*/ pm_error("latex2html, you should just try the -interlace and " - "-transparent options to see if they work instead of " - "expecting a 'usage' message from -h"); + "-transparent options to see if they work instead of " + "expecting a 'usage' message from -h"); } @@ -191,12 +153,12 @@ parseCommandLine(int argc, char ** argv, handleLatex2htmlHack(); 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); else - cmdlineP->input_filespec = argv[1]; + cmdlineP->inputFileName = argv[1]; if (cmdlineP->alpha_filespec && cmdlineP->transparent) pm_error("You cannot specify both -alpha and -transparent."); @@ -204,1362 +166,257 @@ parseCommandLine(int argc, char ** argv, -/* - * Write out a word to the GIF file - */ static void -Putword(int const w, FILE * const fp) { - - fputc( w & 0xff, fp ); - fputc( (w / 256) & 0xff, fp ); -} - - -static int -closestcolor(pixel const color, - pixval const maxval, - struct cmap * const cmapP) { +openPnmremapStream(const char * const inputFileName, + const char * const mapFileName, + bool const verbose, + FILE ** const pnmremapPipeP) { /*---------------------------------------------------------------------------- - Return the pre-sort colormap index of the color in the colormap *cmapP - that is closest to the color 'color', whose maxval is 'maxval'. - - Also add 'color' to the colormap hash, with the colormap index we - are returning. Caller must ensure that the color is not already in - there. + Create a process to run the image in file inputFileName[] through + Pnmremap, remapping it to the colors in mapFileName[]. Have it + write its output to a pipe and return as *pnmremapPipeP the other + end of that pipe. -----------------------------------------------------------------------------*/ - unsigned int i; - unsigned int imin, dmin; - - pixval const r = PPM_GETR(color) * gifMaxval / maxval; - pixval const g = PPM_GETG(color) * gifMaxval / maxval; - pixval const b = PPM_GETB(color) * gifMaxval / maxval; - - dmin = SQR(255) * 3; - imin = 0; - for (i=0;i < cmapP->cmapsize; i++) { - int const d = SQR(r-cmapP->red[i]) + - SQR(g-cmapP->green[i]) + - SQR(b-cmapP->blue[i]); - if (d < dmin) { - dmin = d; - imin = i; - } - } - ppm_addtocolorhash(cmapP->cht, &color, cmapP->permi[imin]); - - return cmapP->permi[imin]; -} - + FILE * pnmremapPipe; + const char * pnmremapCommand; + assert(inputFileName != NULL); + assert(mapFileName != NULL); -enum pass {MULT8PLUS0, MULT8PLUS4, MULT4PLUS2, MULT2PLUS1}; - - -struct pixelCursor { - unsigned int width; - /* Width of the image, in columns */ - unsigned int height; - /* Height of the image, in rows */ - bool interlace; - /* We're accessing the image in interlace fashion */ - unsigned int nPixelsLeft; - /* Number of pixels left to be read */ - unsigned int curCol; - /* Location of pointed-to pixel, column */ - unsigned int curRow; - /* Location of pointed-to pixel, row */ - enum pass pass; - /* The interlace pass. Undefined if !interlace */ -}; + asprintfN(&pnmremapCommand, "pnmremap -mapfile='%s' %s", + mapFileName, inputFileName); + if (verbose) + pm_message("Preprocessing Pamtogif input with shell command '%s'", + pnmremapCommand); + pnmremapPipe = popen(pnmremapCommand, "r"); -static struct pixelCursor pixelCursor; - /* Current location in the input pixels. */ - + if (pnmremapPipe == NULL) + pm_error("Shell command '%s', via popen(), to prepare the input " + "for Pamtogif, failed.", pnmremapCommand); + else + *pnmremapPipeP = pnmremapPipe; -static void -initPixelCursor(unsigned int const width, - unsigned int const height, - bool const interlace) { - - pixelCursor.width = width; - pixelCursor.height = height; - pixelCursor.interlace = interlace; - pixelCursor.pass = MULT8PLUS0; - pixelCursor.curCol = 0; - pixelCursor.curRow = 0; - pixelCursor.nPixelsLeft = width * height; + strfree(pnmremapCommand); } -static void -getPixel(pixel ** const pixels, - pixval const inputMaxval, - gray ** const alpha, - gray const alphaThreshold, - struct cmap * const cmapP, - struct pixelCursor const pixelCursor, - int * const retvalP) { -/*---------------------------------------------------------------------------- - Return as *retvalP the colormap index of the pixel at location - pointed to by 'pixelCursor' in the PPM raster 'pixels', using - colormap *cmapP. ------------------------------------------------------------------------------*/ - unsigned int const x = pixelCursor.curCol; - unsigned int const y = pixelCursor.curRow; +static const char * +pamtogifCommand(const char * const arg0, + struct cmdlineInfo const cmdline) { - int colorindex; + const char * const pamtogifName = "pamtogif"; - if (alpha && alpha[y][x] < alphaThreshold) - colorindex = cmapP->transparent; - else { - int presortColorindex; + const char * retval; - presortColorindex = ppm_lookupcolor(cmapP->cht, &pixels[y][x]); - if (presortColorindex == -1) - presortColorindex = - closestcolor(pixels[y][x], inputMaxval, cmapP); - colorindex = cmapP->perm[presortColorindex]; - } - *retvalP = colorindex; -} + const char * commandVerb; + const char * transparentOpt; + const char * commentOpt; + if (strchr(arg0, '/')) { + const char * const arg0DirName = dirname(arg0); + const char * progName; + struct stat statbuf; -static void -bumpRowInterlace(struct pixelCursor * const pixelCursorP) { -/*---------------------------------------------------------------------------- - Move *pixelCursorP to the next row in the interlace pattern. ------------------------------------------------------------------------------*/ - /* There are 4 passes: - MULT8PLUS0: Rows 8, 16, 24, 32, etc. - MULT8PLUS4: Rows 4, 12, 20, 28, etc. - MULT4PLUS2: Rows 2, 6, 10, 14, etc. - MULT2PLUS1: Rows 1, 3, 5, 7, 9, etc. - */ - - switch (pixelCursorP->pass) { - case MULT8PLUS0: - pixelCursorP->curRow += 8; - break; - case MULT8PLUS4: - pixelCursorP->curRow += 8; - break; - case MULT4PLUS2: - pixelCursorP->curRow += 4; - break; - case MULT2PLUS1: - pixelCursorP->curRow += 2; - break; - } - /* Set the proper pass for the next read. Note that if there are - more than 4 rows, the sequence of passes is sequential, but - when there are fewer than 4, we may skip e.g. from MULT8PLUS0 - to MULT4PLUS2. - */ - while (pixelCursorP->curRow >= pixelCursorP->height) { - switch (pixelCursorP->pass) { - case MULT8PLUS0: - pixelCursorP->pass = MULT8PLUS4; - pixelCursorP->curRow = 4; - break; - case MULT8PLUS4: - pixelCursorP->pass = MULT4PLUS2; - pixelCursorP->curRow = 2; - break; - case MULT4PLUS2: - pixelCursorP->pass = MULT2PLUS1; - pixelCursorP->curRow = 1; - break; - case MULT2PLUS1: - /* We've read the entire image; pass and current row are - now undefined. - */ - pixelCursorP->curRow = 0; - break; - } - } -} + asprintfN(&progName, "%s/%s", arg0DirName, pamtogifName); - - -static void -bumpPixel(struct pixelCursor * const pixelCursorP) { -/*---------------------------------------------------------------------------- - Bump *pixelCursorP to point to the next pixel to go into the GIF - - Must not call when there are no pixels left. ------------------------------------------------------------------------------*/ - assert(pixelCursorP->nPixelsLeft > 0); - - /* Move one column to the right */ - ++pixelCursorP->curCol; - - if (pixelCursorP->curCol >= pixelCursorP->width) { - /* That pushed us past the end of a row. */ - /* Reset to the left edge ... */ - pixelCursorP->curCol = 0; - - /* ... of the next row */ - if (!pixelCursorP->interlace) - /* Go to the following row */ - ++pixelCursorP->curRow; + if (stat(progName, &statbuf) == 0) + commandVerb = progName; else - bumpRowInterlace(pixelCursorP); - } - --pixelCursorP->nPixelsLeft; -} - - - -static int -gifNextPixel(pixel ** const pixels, - pixval const inputMaxval, - gray ** const alpha, - gray const alphaThreshold, - struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - Return the pre-sort color index (index into the unsorted GIF color map) - of the next pixel to be processed from the input image. - - 'alpha_threshold' is the gray level such that a pixel in the alpha - map whose value is less that that represents a transparent pixel - in the output. ------------------------------------------------------------------------------*/ - int retval; - - if (pixelCursor.nPixelsLeft == 0 ) - retval = EOF; - else { - getPixel(pixels, inputMaxval, alpha, alphaThreshold, cmapP, - pixelCursor, &retval); - - bumpPixel(&pixelCursor); - } - return retval; -} - - - -static void -write_transparent_color_index_extension(FILE *fp, const int Transparent) { -/*---------------------------------------------------------------------------- - Write out extension for transparent color index. ------------------------------------------------------------------------------*/ - - fputc( '!', fp ); - fputc( 0xf9, fp ); - fputc( 4, fp ); - fputc( 1, fp ); - fputc( 0, fp ); - fputc( 0, fp ); - fputc( Transparent, fp ); - fputc( 0, fp ); -} - - - -static void -write_comment_extension(FILE *fp, const char comment[]) { -/*---------------------------------------------------------------------------- - Write out extension for a comment ------------------------------------------------------------------------------*/ - char *segment; - - fputc('!', fp); /* Identifies an extension */ - fputc(0xfe, fp); /* Identifies a comment */ - - /* Write it out in segments no longer than 255 characters */ - for (segment = (char *) comment; - segment < comment+strlen(comment); - segment += 255) { + commandVerb = strdup(pamtogifName); - const int length_this_segment = MIN(255, strlen(segment)); + strfree(arg0DirName); + } else + commandVerb = strdup(pamtogifName); - fputc(length_this_segment, fp); - - fwrite(segment, 1, length_this_segment, fp); - } - - fputc(0, fp); /* No more comment blocks in this extension */ -} - - - -/*************************************************************************** - * - * GIFCOMPR.C - GIF Image compression routines - * - * Lempel-Ziv compression based on 'compress'. GIF modifications by - * David Rowley (mgardi@watdcsu.waterloo.edu) - * - ***************************************************************************/ - -/* - * General DEFINEs - */ - -#define BITS 12 - -#define HSIZE 5003 /* 80% occupancy */ - -#ifdef NO_UCHAR - typedef char char_type; -#else /*NO_UCHAR*/ - typedef unsigned char char_type; -#endif /*NO_UCHAR*/ - -/* - * - * GIF Image compression - modified 'compress' - * - * Based on: compress.c - File compression ala IEEE Computer, June 1984. - * - * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) - * Jim McKie (decvax!mcvax!jim) - * Steve Davies (decvax!vax135!petsd!peora!srd) - * Ken Turkowski (decvax!decwrl!turtlevax!ken) - * James A. Woods (decvax!ihnp4!ames!jaw) - * Joe Orost (decvax!vax135!petsd!joe) - * - */ -#include <ctype.h> - -#define ARGVAL() (*++(*argv) || (--argc && *++argv)) - -static code_int const maxmaxcode = (code_int)1 << BITS; - /* should NEVER generate this code */ -#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) - -static long htab [HSIZE]; -static unsigned short codetab [HSIZE]; -#define HashTabOf(i) htab[i] -#define CodeTabOf(i) codetab[i] - -/* - * To save much memory, we overlay the table used by compress() with those - * used by decompress(). The tab_prefix table is the same size and type - * as the codetab. The tab_suffix table needs 2**BITS characters. We - * get this from the beginning of htab. The output stack uses the rest - * of htab, and contains characters. There is plenty of room for any - * possible stack (stack used to be 8000 characters). - */ - -#define tab_prefixof(i) CodeTabOf(i) -#define tab_suffixof(i) ((char_type*)(htab))[i] -#define de_stack ((char_type*)&tab_suffixof((code_int)1<<BITS)) - -static code_int free_ent = 0; /* first unused entry */ - -/* - * block compression parameters -- after all codes are used up, - * and compression rate changes, start over. - */ -static int clear_flg = 0; - -static int offset; -static long int in_count = 1; /* length of input */ -static long int out_count = 0; /* # of codes output (for debugging) */ - -/* - * compress stdin to stdout - * - * Algorithm: use open addressing double hashing (no chaining) on the - * prefix code / next character combination. We do a variant of Knuth's - * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime - * secondary probe. Here, the modular division first probe is gives way - * to a faster exclusive-or manipulation. Also do block compression with - * an adaptive reset, whereby the code table is cleared when the compression - * ratio decreases, but after the table fills. The variable-length output - * codes are re-sized at this point, and a special CLEAR code is generated - * for the decompressor. Late addition: construct the table according to - * file size for noticeable speed improvement on small files. Please direct - * questions about this implementation to ames!jaw. - */ - -static int ClearCode; -static int EOFCode; - -/*************************************************************************** -* BYTE OUTPUTTER -***************************************************************************/ - -typedef struct { - FILE * fileP; /* The file to which to output */ - unsigned int count; - /* Number of bytes so far in the current data block */ - unsigned char buffer[256]; - /* The current data block, under construction */ -} byteBuffer; - - - -static byteBuffer * -byteBuffer_create(FILE * const fileP) { - - byteBuffer * byteBufferP; - - MALLOCVAR_NOFAIL(byteBufferP); - - byteBufferP->fileP = fileP; - byteBufferP->count = 0; - - return byteBufferP; -} - - - -static void -byteBuffer_destroy(byteBuffer * const byteBufferP) { - - free(byteBufferP); -} - - - -static void -byteBuffer_flush(byteBuffer * const byteBufferP) { -/*---------------------------------------------------------------------------- - Write the current data block to the output file, then reset the current - data block to empty. ------------------------------------------------------------------------------*/ - if (byteBufferP->count > 0 ) { - if (verbose) - pm_message("Writing %u byte block", byteBufferP->count); - fputc(byteBufferP->count, byteBufferP->fileP); - fwrite(byteBufferP->buffer, 1, byteBufferP->count, byteBufferP->fileP); - byteBufferP->count = 0; - } -} - - - -static void -byteBuffer_flushFile(byteBuffer * const byteBufferP) { - - fflush(byteBufferP->fileP); - - if (ferror(byteBufferP->fileP)) - pm_error("error writing output file"); -} - - - -static void -byteBuffer_out(byteBuffer * const byteBufferP, - unsigned char const c) { -/*---------------------------------------------------------------------------- - Add a byte to the end of the current data block, and if it is now 254 - characters, flush the data block to the output file. ------------------------------------------------------------------------------*/ - byteBufferP->buffer[byteBufferP->count++] = c; - if (byteBufferP->count >= 254) - byteBuffer_flush(byteBufferP); -} - - - -struct gif_dest { - /* This structure controls output of uncompressed GIF raster */ - - byteBuffer * byteBufferP; /* Where the full bytes go */ - - /* State for packing variable-width codes into a bitstream */ - int n_bits; /* current number of bits/code */ - int maxcode; /* maximum code, given n_bits */ - int cur_accum; /* holds bits not yet output */ - int cur_bits; /* # of bits in cur_accum */ - - /* State for GIF code assignment */ - int ClearCode; /* clear code (doesn't change) */ - int EOFCode; /* EOF code (ditto) */ - int code_counter; /* counts output symbols */ -}; - - - -static unsigned long const masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, - 0x001F, 0x003F, 0x007F, 0x00FF, - 0x01FF, 0x03FF, 0x07FF, 0x0FFF, - 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; - -typedef struct { - byteBuffer * byteBufferP; - unsigned int initBits; - unsigned int n_bits; /* number of bits/code */ - code_int maxcode; /* maximum code, given n_bits */ - unsigned long curAccum; - int curBits; -} codeBuffer; - - - -static codeBuffer * -codeBuffer_create(FILE * const ofP, - unsigned int const initBits) { - - codeBuffer * codeBufferP; - - MALLOCVAR_NOFAIL(codeBufferP); - - codeBufferP->initBits = initBits; - codeBufferP->n_bits = codeBufferP->initBits; - codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits); - codeBufferP->byteBufferP = byteBuffer_create(ofP); - codeBufferP->curAccum = 0; - codeBufferP->curBits = 0; - - return codeBufferP; -} - - - -static void -codeBuffer_destroy(codeBuffer * const codeBufferP) { - - byteBuffer_destroy(codeBufferP->byteBufferP); - - free(codeBufferP); -} - - - -static void -codeBuffer_output(codeBuffer * const codeBufferP, - code_int const code) { -/*---------------------------------------------------------------------------- - Output one GIF code to the file, through the code buffer. - - The code is represented as n_bits bits in the file -- the lower - n_bits bits of 'code'. - - If the code is EOF, flush the code buffer to the file. - - In some cases, change n_bits and recalculate maxcode to go with it. ------------------------------------------------------------------------------*/ - /* - Algorithm: - Maintain a BITS character long buffer (so that 8 codes will - fit in it exactly). Use the VAX insv instruction to insert each - code in turn. When the buffer fills up empty it and start over. - */ - - codeBufferP->curAccum &= masks[codeBufferP->curBits]; - - if (codeBufferP->curBits > 0) - codeBufferP->curAccum |= ((long)code << codeBufferP->curBits); + if (cmdline.transparent) + asprintfN(&transparentOpt, "-transparent=%s", cmdline.transparent); else - codeBufferP->curAccum = code; - - codeBufferP->curBits += codeBufferP->n_bits; + transparentOpt = strdup(""); - while (codeBufferP->curBits >= 8) { - byteBuffer_out(codeBufferP->byteBufferP, - codeBufferP->curAccum & 0xff); - codeBufferP->curAccum >>= 8; - codeBufferP->curBits -= 8; - } - - if (clear_flg) { - codeBufferP->n_bits = codeBufferP->initBits; - codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits); - clear_flg = 0; - } else if (free_ent > codeBufferP->maxcode) { - /* The next entry is going to be too big for the code size, so - increase it, if possible. - */ - ++codeBufferP->n_bits; - if (codeBufferP->n_bits == BITS) - codeBufferP->maxcode = maxmaxcode; - else - codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits); - } + if (cmdline.comment) + asprintfN(&commentOpt, "-comment=%s", cmdline.comment); + else + commentOpt = strdup(""); + + asprintfN(&retval, "%s - -alphacolor=%s %s %s %s %s %s %s", + commandVerb, + cmdline.alphacolor, + cmdline.interlace ? "-interlace" : "", + cmdline.sort ? "-sort" : "", + transparentOpt, + commentOpt, + cmdline.nolzw ? "-nolzw" : "", + cmdline.verbose ? "-verbose" : ""); - if (code == EOFCode) { - /* We're at EOF. Output the possible partial byte in the buffer */ - if (codeBufferP->curBits > 0) { - byteBuffer_out(codeBufferP->byteBufferP, - codeBufferP->curAccum & 0xff); - codeBufferP->curBits = 0; - } - byteBuffer_flush(codeBufferP->byteBufferP); - - byteBuffer_flushFile(codeBufferP->byteBufferP); - } -} - + strfree(transparentOpt); + strfree(commentOpt); - -static void -cl_hash(long const hsize) { - /* reset code table */ - - long const m1 = -1; - - long * htab_p; - long i; - - htab_p = htab + hsize; /* initial value */ - - i = hsize - 16; - do { /* might use Sys V memset(3) here */ - *(htab_p-16) = m1; - *(htab_p-15) = m1; - *(htab_p-14) = m1; - *(htab_p-13) = m1; - *(htab_p-12) = m1; - *(htab_p-11) = m1; - *(htab_p-10) = m1; - *(htab_p-9) = m1; - *(htab_p-8) = m1; - *(htab_p-7) = m1; - *(htab_p-6) = m1; - *(htab_p-5) = m1; - *(htab_p-4) = m1; - *(htab_p-3) = m1; - *(htab_p-2) = m1; - *(htab_p-1) = m1; - htab_p -= 16; - } while ((i -= 16) >= 0); - - for (i += 16; i > 0; --i) - *--htab_p = m1; + return retval; } static void -cl_block(codeBuffer * const codeBufferP) { -/*---------------------------------------------------------------------------- - Clear out the hash table ------------------------------------------------------------------------------*/ - cl_hash(HSIZE); - free_ent = ClearCode + 2; - clear_flg = 1; +feedPamtogifNoAlpha(struct pam * const inPamP, + FILE * const pipeToPamtogif) { - codeBuffer_output(codeBufferP, (code_int)ClearCode); -} + unsigned int row; + struct pam outPam; + tuple * tuplerow; + tuplerow = pnm_allocpamrow(inPamP); - -static void -write_raster_LZW(pixel ** const pixels, - pixval const input_maxval, - gray ** const alpha, - gray const alpha_maxval, - struct cmap * const cmapP, - int const initBits, - FILE * const ofP) { -/*---------------------------------------------------------------------------- - Write the raster to file 'ofP'. - - The raster to write is 'pixels', which has maxval 'input_maxval', - modified by alpha mask 'alpha', which has maxval 'alpha_maxval'. - - Use the colormap 'cmapP' to generate the raster ('pixels' is - composed of RGB samples; the GIF raster is colormap indices). - - Write the raster using LZW compression. ------------------------------------------------------------------------------*/ - gray const alpha_threshold = (alpha_maxval + 1) / 2; - /* gray levels below this in the alpha mask indicate transparent - pixels in the output image. - */ - code_int ent; - code_int disp; - int hshift; - bool eof; - codeBuffer * codeBufferP; - - codeBufferP = codeBuffer_create(ofP, initBits); + outPam = *inPamP; + outPam.file = pipeToPamtogif; - /* - * Set up the necessary values - */ - offset = 0; - out_count = 0; - clear_flg = 0; - in_count = 1; - - ClearCode = (1 << (initBits - 1)); - EOFCode = ClearCode + 1; - free_ent = ClearCode + 2; - - ent = gifNextPixel(pixels, input_maxval, alpha, alpha_threshold, cmapP); - - { - long fcode; - hshift = 0; - for (fcode = HSIZE; fcode < 65536L; fcode *= 2L) - ++hshift; - hshift = 8 - hshift; /* set hash code range bound */ - } - cl_hash(HSIZE); /* clear hash table */ - - codeBuffer_output(codeBufferP, (code_int)ClearCode); - - eof = FALSE; - while (!eof) { - int gifpixel; - /* The value for the pixel in the GIF image. I.e. the colormap - index. Or -1 to indicate "no more pixels." - */ - gifpixel = gifNextPixel(pixels, - input_maxval, alpha, alpha_threshold, cmapP); - if (gifpixel == EOF) eof = TRUE; - if (!eof) { - long const fcode = (long) (((long) gifpixel << BITS) + ent); - code_int i; - /* xor hashing */ - - ++in_count; - - i = (((code_int)gifpixel << hshift) ^ ent); - - if (HashTabOf (i) == fcode) { - ent = CodeTabOf (i); - continue; - } else if ((long)HashTabOf(i) < 0) /* empty slot */ - goto nomatch; - disp = HSIZE - i; /* secondary hash (after G. Knott) */ - if (i == 0) - disp = 1; - probe: - if ((i -= disp) < 0) - i += HSIZE; - - if (HashTabOf(i) == fcode) { - ent = CodeTabOf(i); - continue; - } - if ((long)HashTabOf(i) > 0) - goto probe; - nomatch: - codeBuffer_output(codeBufferP, (code_int)ent); - ++out_count; - ent = gifpixel; - if (free_ent < maxmaxcode) { - CodeTabOf(i) = free_ent++; /* code -> hashtable */ - HashTabOf(i) = fcode; - } else - cl_block(codeBufferP); - } - } - /* Put out the final code. */ - codeBuffer_output(codeBufferP, (code_int)ent); - ++out_count; - codeBuffer_output(codeBufferP, (code_int) EOFCode); - - codeBuffer_destroy(codeBufferP); -} - + pnm_writepaminit(&outPam); + for (row = 0; row < inPamP->height; ++row) { + pnm_readpamrow(inPamP, tuplerow); -/* Routine to convert variable-width codes into a byte stream */ - -static void -outputUncompressed(struct gif_dest * const dinfoP, - int const code) { - - /* Emit a code of n_bits bits */ - /* Uses cur_accum and cur_bits to reblock into 8-bit bytes */ - dinfoP->cur_accum |= ((int) code) << dinfoP->cur_bits; - dinfoP->cur_bits += dinfoP->n_bits; - - while (dinfoP->cur_bits >= 8) { - byteBuffer_out(dinfoP->byteBufferP, dinfoP->cur_accum & 0xFF); - dinfoP->cur_accum >>= 8; - dinfoP->cur_bits -= 8; - } -} - - -static void -writeRasterUncompressedInit(FILE * const ofP, - struct gif_dest * const dinfoP, - int const i_bits) { -/*---------------------------------------------------------------------------- - Initialize pseudo-compressor ------------------------------------------------------------------------------*/ - - /* init all the state variables */ - dinfoP->n_bits = i_bits; - dinfoP->maxcode = MAXCODE(dinfoP->n_bits); - dinfoP->ClearCode = (1 << (i_bits - 1)); - dinfoP->EOFCode = dinfoP->ClearCode + 1; - dinfoP->code_counter = dinfoP->ClearCode + 2; - /* init output buffering vars */ - dinfoP->byteBufferP = byteBuffer_create(ofP); - dinfoP->cur_accum = 0; - dinfoP->cur_bits = 0; - /* GIF specifies an initial Clear code */ - outputUncompressed(dinfoP, dinfoP->ClearCode); -} - - - -static void -writeRasterUncompressedPixel(struct gif_dest * const dinfoP, - unsigned int const colormapIndex) { -/*---------------------------------------------------------------------------- - "Compress" one pixel value and output it as a symbol. - - 'colormapIndex' must be less than dinfoP->n_bits wide. ------------------------------------------------------------------------------*/ - assert(colormapIndex >> dinfoP->n_bits == 0); - - outputUncompressed(dinfoP, colormapIndex); - /* Issue Clear codes often enough to keep the reader from ratcheting up - * its symbol size. - */ - if (dinfoP->code_counter < dinfoP->maxcode) { - ++dinfoP->code_counter; - } else { - outputUncompressed(dinfoP, dinfoP->ClearCode); - dinfoP->code_counter = dinfoP->ClearCode + 2; /* reset the counter */ + pnm_writepamrow(&outPam, tuplerow); } + pnm_freepamrow(tuplerow); } static void -writeRasterUncompressedTerm(struct gif_dest * const dinfoP) { - - outputUncompressed(dinfoP, dinfoP->EOFCode); - - if (dinfoP->cur_bits > 0) - byteBuffer_out(dinfoP->byteBufferP, dinfoP->cur_accum & 0xFF); - - byteBuffer_flush(dinfoP->byteBufferP); - - byteBuffer_destroy(dinfoP->byteBufferP); -} - - - -static void -writeRasterUncompressed(FILE * const ofP, - pixel ** const pixels, - pixval const inputMaxval, - gray ** const alpha, - gray const alphaMaxval, - struct cmap * const cmapP, - int const initBits) { -/*---------------------------------------------------------------------------- - Write the raster to file 'ofP'. - - Same as write_raster_LZW(), except written out one code per - pixel (plus some clear codes), so no compression. And no use - of the LZW patent. ------------------------------------------------------------------------------*/ - gray const alphaThreshold = (alphaMaxval + 1) / 2; - /* gray levels below this in the alpha mask indicate transparent - pixels in the output image. - */ - bool eof; - - struct gif_dest gifDest; - - writeRasterUncompressedInit(ofP, &gifDest, initBits); - - eof = FALSE; - while (!eof) { - int gifpixel; - /* The value for the pixel in the GIF image. I.e. the colormap - index. Or -1 to indicate "no more pixels." - */ - gifpixel = gifNextPixel(pixels, - inputMaxval, alpha, alphaThreshold, cmapP); - if (gifpixel == EOF) - eof = TRUE; - else - writeRasterUncompressedPixel(&gifDest, gifpixel); - } - writeRasterUncompressedTerm(&gifDest); -} - - - -/****************************************************************************** - * - * GIF Specific routines - * - *****************************************************************************/ - -static void -writeGifHeader(FILE * const fp, - int const Width, int const Height, - int const GInterlace, int const Background, - int const BitsPerPixel, struct cmap * const cmapP, - const char comment[]) { - - int B; - int const Resolution = BitsPerPixel; - int const ColorMapSize = 1 << BitsPerPixel; - - /* Write the Magic header */ - if (cmapP->transparent != -1 || comment) - fwrite("GIF89a", 1, 6, fp); - else - fwrite("GIF87a", 1, 6, fp); - - /* Write out the screen width and height */ - Putword( Width, fp ); - Putword( Height, fp ); - - /* Indicate that there is a global color map */ - B = 0x80; /* Yes, there is a color map */ - - /* OR in the resolution */ - B |= (Resolution - 1) << 4; - - /* OR in the Bits per Pixel */ - B |= (BitsPerPixel - 1); - - /* Write it out */ - fputc( B, fp ); - - /* Write out the Background color */ - fputc( Background, fp ); - - /* Byte of 0's (future expansion) */ - fputc( 0, fp ); - - { - /* Write out the Global Color Map */ - /* Note that the Global Color Map is always a power of two colors - in size, but *cmapP could be smaller than that. So we pad with - black. - */ - int i; - for ( i=0; i < ColorMapSize; ++i ) { - if ( i < cmapP->cmapsize ) { - fputc( cmapP->red[i], fp ); - fputc( cmapP->green[i], fp ); - fputc( cmapP->blue[i], fp ); - } else { - fputc( 0, fp ); - fputc( 0, fp ); - fputc( 0, fp ); - } +copyRasterWithAlpha(struct pam * const inPamP, + struct pam * const alphaPamP, + struct pam * const outPamP, + unsigned int const alphaPlane) { + + tuple * tuplerow; + tuple * alpharow; + unsigned int row; + + inPamP->allocation_depth = outPamP->depth; + + tuplerow = pnm_allocpamrow(inPamP); + alpharow = pnm_allocpamrow(alphaPamP); + + for (row = 0; row < inPamP->height; ++row) { + unsigned int col; + + pnm_readpamrow(inPamP, tuplerow); + pnm_readpamrow(alphaPamP, alpharow); + + for (col = 0; col < inPamP->width; ++col) { + tuplerow[col][alphaPlane] = pnm_scalesample(alpharow[col][0], + alphaPamP->maxval, + inPamP->maxval); } + pnm_writepamrow(outPamP, tuplerow); } - - if ( cmapP->transparent >= 0 ) - write_transparent_color_index_extension(fp, cmapP->transparent); - - if ( comment ) - write_comment_extension(fp, comment); -} - - - -static void -writeImageHeader(FILE * const ofP, - unsigned int const leftOffset, - unsigned int const topOffset, - unsigned int const gWidth, - unsigned int const gHeight, - unsigned int const gInterlace, - unsigned int const initCodeSize) { - - Putword(leftOffset, ofP); - Putword(topOffset, ofP); - Putword(gWidth, ofP); - Putword(gHeight, ofP); - - /* Write out whether or not the image is interlaced */ - if (gInterlace) - fputc(0x40, ofP); - else - fputc(0x00, ofP); - - /* Write out the initial code size */ - fputc(initCodeSize, ofP); -} - - - -static void -gifEncode(FILE * const ofP, - pixel ** const pixels, - pixval const inputMaxval, - int const gWidth, - int const gHeight, - gray ** const alpha, - gray const alphaMaxval, - int const gInterlace, - int const background, - int const bitsPerPixel, - struct cmap * const cmapP, - char const comment[], - bool const nolzw) { - - unsigned int const leftOffset = 0; - unsigned int const topOffset = 0; - - unsigned int const initCodeSize = bitsPerPixel <= 1 ? 2 : bitsPerPixel; - /* The initial code size */ - - if (gWidth > 65535) - pm_error("Image width %u too large for GIF format. (Max 65535)", - gWidth); - - if (gHeight > 65535) - pm_error("Image height %u too large for GIF format. (Max 65535)", - gHeight); - - writeGifHeader(ofP, gWidth, gHeight, gInterlace, background, - bitsPerPixel, cmapP, comment); - - /* Write an Image separator */ - fputc(',', ofP); - - writeImageHeader(ofP, leftOffset, topOffset, gWidth, gHeight, gInterlace, - initCodeSize); - - initPixelCursor(gWidth, gHeight, gInterlace); - - /* Write the actual raster */ - if (nolzw) - writeRasterUncompressed(ofP, pixels, - inputMaxval, alpha, alphaMaxval, cmapP, - initCodeSize + 1); - else - write_raster_LZW(pixels, - inputMaxval, alpha, alphaMaxval, cmapP, - initCodeSize + 1, ofP); - - /* Write out a zero length data block (to end the series) */ - fputc(0, ofP); - - /* Write the GIF file terminator */ - fputc(';', ofP); -} - - - -static int -compute_transparent(const char colorarg[], - struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - Figure out the color index (index into the colormap) of the color - that is to be transparent in the GIF. - - colorarg[] is the string that specifies the color the user wants to - be transparent (e.g. "red", "#fefefe"). Its maxval is the maxval - of the colormap. 'cmap' is the full colormap except that its - 'transparent' component isn't valid. - - colorarg[] is a standard Netpbm color specification, except that - may have a "=" prefix, which means it specifies a particular exact - color, as opposed to without the "=", which means "the color that - is closest to this and actually in the image." - - Return -1 if colorarg[] specifies an exact color and that color is not - in the image. Also issue an informational message. ------------------------------------------------------------------------------*/ - int retval; - - const char *colorspec; - bool exact; - int presort_colorindex; - pixel transcolor; - - if (colorarg[0] == '=') { - colorspec = &colorarg[1]; - exact = TRUE; - } else { - colorspec = colorarg; - exact = FALSE; - } - - transcolor = ppm_parsecolor((char*)colorspec, cmapP->maxval); - presort_colorindex = ppm_lookupcolor(cmapP->cht, &transcolor); - - if (presort_colorindex != -1) - retval = cmapP->perm[presort_colorindex]; - else if (!exact) - retval = cmapP->perm[closestcolor(transcolor, cmapP->maxval, cmapP)]; - else { - retval = -1; - pm_message( - "Warning: specified transparent color does not occur in image."); - } - return retval; + pnm_freepamrow(alpharow); + pnm_freepamrow(tuplerow); } static void -sort_colormap(int const sort, struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - Sort (in place) the colormap *cmapP. - - Create the perm[] and permi[] mappings for the colormap. - - 'sort' is logical: true means to sort the colormap by red intensity, - then by green intensity, then by blue intensity. False means a null - sort -- leave it in the same order in which we found it. ------------------------------------------------------------------------------*/ - int * const Red = cmapP->red; - int * const Blue = cmapP->blue; - int * const Green = cmapP->green; - int * const perm = cmapP->perm; - int * const permi = cmapP->permi; - unsigned int const cmapsize = cmapP->cmapsize; - - int i; - - for (i=0; i < cmapsize; i++) - permi[i] = i; - - if (sort) { - pm_message("sorting colormap"); - for (i=0; i < cmapsize; i++) { - int j; - for (j=i+1; j < cmapsize; j++) - if (((Red[i]*MAXCMAPSIZE)+Green[i])*MAXCMAPSIZE+Blue[i] > - ((Red[j]*MAXCMAPSIZE)+Green[j])*MAXCMAPSIZE+Blue[j]) { - int tmp; - - tmp=permi[i]; permi[i]=permi[j]; permi[j]=tmp; - tmp=Red[i]; Red[i]=Red[j]; Red[j]=tmp; - tmp=Green[i]; Green[i]=Green[j]; Green[j]=tmp; - tmp=Blue[i]; Blue[i]=Blue[j]; Blue[j]=tmp; } } +feedPamtogifWithAlpha(struct pam * const inPamP, + struct pam * const alphaPamP, + FILE * const pipeToPamtogif) { + + unsigned int alphaPlane; + struct pam outPam; + + if (inPamP->width != alphaPamP->width || + inPamP->height != alphaPamP->height) + pm_error("-alpha image dimensions (%u w x %u h) do not match " + "the input image dimensions (%u x %u)", + alphaPamP->width, alphaPamP->height, + inPamP->width, inPamP->height); + + outPam = *inPamP; + outPam.file = pipeToPamtogif; + outPam.format = PAM_FORMAT; + outPam.plainformat = 0; + + if (inPamP->depth == 1) { + alphaPlane = 1; + strcpy(outPam.tuple_type, "GRAYSCALE_ALPHA"); + } else if (inPamP->depth == 3) { + alphaPlane = 3; + strcpy(outPam.tuple_type, "RGB_ALPHA"); } + outPam.depth = alphaPlane + 1; - for (i=0; i < cmapsize; i++) - perm[permi[i]] = i; -} + pnm_writepaminit(&outPam); - - -static void -normalize_to_255(colorhist_vector const chv, struct cmap * const cmapP) { -/*---------------------------------------------------------------------------- - With a PPM color histogram vector 'chv' as input, produce a colormap - of integers 0-255 as output in *cmapP. ------------------------------------------------------------------------------*/ - int i; - pixval const maxval = cmapP->maxval; - - if ( maxval != 255 ) - pm_message( - "maxval is not 255 - automatically rescaling colors" ); - - for ( i = 0; i < cmapP->cmapsize; ++i ) { - if ( maxval == 255 ) { - cmapP->red[i] = (int) PPM_GETR( chv[i].color ); - cmapP->green[i] = (int) PPM_GETG( chv[i].color ); - cmapP->blue[i] = (int) PPM_GETB( chv[i].color ); - } else { - cmapP->red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval; - cmapP->green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval; - cmapP->blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval; - } - } -} - - - -static void add_to_colormap(struct cmap * const cmapP, - const char * const colorspec, - int * const new_indexP) { -/*---------------------------------------------------------------------------- - Add a new entry to the colormap. Make the color that specified by - 'colorspec', and return the index of the new entry as *new_indexP. - - 'colorspec' is a color specification given by the user, e.g. - "red" or "rgb:ff/03.0d". The maxval for this color specification is - that for the colormap *cmapP. ------------------------------------------------------------------------------*/ - pixel const transcolor = ppm_parsecolor((char*)colorspec, cmapP->maxval); - - *new_indexP = cmapP->cmapsize++; - - cmapP->red[*new_indexP] = PPM_GETR(transcolor); - cmapP->green[*new_indexP] = PPM_GETG(transcolor); - cmapP->blue[*new_indexP] = PPM_GETB(transcolor); + copyRasterWithAlpha(inPamP, alphaPamP, &outPam, alphaPlane); } static void -colormap_from_file(const char filespec[], unsigned int const maxcolors, - colorhist_vector * const chvP, pixval * const maxvalP, - int * const colorsP) { -/*---------------------------------------------------------------------------- - Read a colormap from the PPM file filespec[]. Return the color histogram - vector (which is practically a colormap) of the input image as *cvhP - and the maxval for that histogram as *maxvalP. ------------------------------------------------------------------------------*/ - FILE *mapfile; - int cols, rows; - pixel ** colormap_ppm; - - mapfile = pm_openr(filespec); - colormap_ppm = ppm_readppm(mapfile, &cols, &rows, maxvalP); - pm_close(mapfile); +feedPamtogif(struct pam * const inPamP, + const char * const alphaFilespec, + FILE * const pipeToPamtogif) { - /* Figure out the colormap from the <mapfile>. */ - pm_message("computing other colormap..."); - *chvP = - ppm_computecolorhist(colormap_ppm, cols, rows, maxcolors, colorsP); - - ppm_freearray(colormap_ppm, rows); -} - - - -static void -get_alpha(const char * const alpha_filespec, int const cols, int const rows, - gray *** const alphaP, gray * const maxvalP) { - - if (alpha_filespec) { - int alpha_cols, alpha_rows; - *alphaP = pgm_readpgm(pm_openr(alpha_filespec), - &alpha_cols, &alpha_rows, maxvalP); - if (alpha_cols != cols || alpha_rows != rows) - pm_error("alpha mask is not the same dimensions as the " - "input file (alpha is %dW x %dH; image is %dW x %dH)", - alpha_cols, alpha_rows, cols, rows); - } else - *alphaP = NULL; -} - - - -static void -compute_ppm_colormap(pixel ** const pixels, int const cols, int const rows, - int const input_maxval, bool const have_alpha, - const char * const mapfile, colorhist_vector * const chvP, - colorhash_table * const chtP, - pixval * const colormap_maxvalP, - int * const colorsP) { -/*---------------------------------------------------------------------------- - Compute a colormap, PPM style, for the image 'pixels', which is - 'cols' by 'rows' with maxval 'input_maxval'. If 'mapfile' is - non-null, Use the colors in that (PPM) file for the color map - instead of the colors in 'pixels'. - - Return the colormap as *chvP and *chtP. Return the maxval for that - colormap as *colormap_maxvalP. - - While we're at it, count the colors and validate that there aren't - too many. Return the count as *colorsP. In determining if there are - too many, allow one slot for a fake transparency color if 'have_alpha' - is true. If there are too many, issue an error message and abort the - program. ------------------------------------------------------------------------------*/ - unsigned int maxcolors; - /* The most colors we can tolerate in the image. If we have - our own made-up entry in the colormap for transparency, it - isn't included in this count. - */ - - if (have_alpha) - maxcolors = MAXCMAPSIZE - 1; - else - maxcolors = MAXCMAPSIZE; - - if (mapfile) { - /* Read the colormap from a separate colormap file. */ - colormap_from_file(mapfile, maxcolors, chvP, colormap_maxvalP, - colorsP); - } else { - /* Figure out the color map from the input file */ - pm_message("computing colormap..."); - *chvP = ppm_computecolorhist(pixels, cols, rows, maxcolors, colorsP); - *colormap_maxvalP = input_maxval; - } - - if (*chvP == NULL) - pm_error("too many colors - try doing a 'pnmquant %d'", maxcolors); - pm_message("%d colors found", *colorsP); - - /* And make a hash table for fast lookup. */ - *chtP = ppm_colorhisttocolorhash(*chvP, *colorsP); + if (alphaFilespec) { + FILE * afP; + struct pam alphaPam; + afP = pm_openr(alphaFilespec); + pnm_readpaminit(afP, &alphaPam, PAM_STRUCT_SIZE(tuple_type)); + feedPamtogifWithAlpha(inPamP, &alphaPam, pipeToPamtogif); + pm_close(afP); + } else + feedPamtogifNoAlpha(inPamP, pipeToPamtogif); } int -main(int argc, char *argv[]) { +main(int argc, + char * argv[]) { + struct cmdlineInfo cmdline; FILE * ifP; - int rows, cols; - int BitsPerPixel; - pixel ** pixels; /* The input image, in PPM format */ - pixval input_maxval; /* Maxval for 'pixels' */ - gray ** alpha; /* The supplied alpha mask; NULL if none */ - gray alpha_maxval; /* Maxval for 'alpha' */ - - struct cmap cmap; - /* The colormap, with all its accessories */ - colorhist_vector chv; - int fake_transparent; - /* colormap index of the fake transparency color we're using to - implement the alpha mask. Undefined if we're not doing an alpha - mask. - */ + struct pam inPam; + const char * command; + FILE * pipeToPamtogif; + int rc; - ppm_init( &argc, argv ); + pnm_init(&argc, argv); parseCommandLine(argc, argv, &cmdline); - verbose = cmdline.verbose; - - ifP = pm_openr(cmdline.input_filespec); - - pixels = ppm_readppm(ifP, &cols, &rows, &input_maxval); - - pm_close(ifP); + if (cmdline.mapfile) + openPnmremapStream(cmdline.inputFileName, cmdline.mapfile, + cmdline.verbose, &ifP); + else + ifP = pm_openr(cmdline.inputFileName); + + command = pamtogifCommand(argv[0], cmdline); - get_alpha(cmdline.alpha_filespec, cols, rows, &alpha, &alpha_maxval); + if (cmdline.verbose) + pm_message("Executing shell command '%s'", command); + + pipeToPamtogif = popen(command, "w"); - compute_ppm_colormap(pixels, cols, rows, input_maxval, (alpha != NULL), - cmdline.mapfile, - &chv, &cmap.cht, &cmap.maxval, &cmap.cmapsize); + if (pipeToPamtogif == NULL) + pm_error("Shell command '%s', via popen(), failed.", command); - /* Now turn the ppm colormap into the appropriate GIF colormap. */ + pnm_readpaminit(ifP, &inPam, PAM_STRUCT_SIZE(allocation_depth)); - normalize_to_255(chv, &cmap); + feedPamtogif(&inPam, cmdline.alpha_filespec, pipeToPamtogif); - ppm_freecolorhist(chv); + rc = pclose(pipeToPamtogif); - if (alpha) { - /* Add a fake entry to the end of the colormap for transparency. - Make its color black. - */ - add_to_colormap(&cmap, cmdline.alphacolor, &fake_transparent); - } - sort_colormap(cmdline.sort, &cmap); - - BitsPerPixel = pm_maxvaltobits(cmap.cmapsize-1); - - if (alpha) { - cmap.transparent = cmap.perm[fake_transparent]; - } else { - if (cmdline.transparent) - cmap.transparent = - compute_transparent(cmdline.transparent, &cmap); - else - cmap.transparent = -1; - } - /* All set, let's do it. */ - gifEncode(stdout, pixels, input_maxval, cols, rows, - alpha, alpha_maxval, - cmdline.interlace, 0, BitsPerPixel, &cmap, cmdline.comment, - cmdline.nolzw); + if (rc != 0) + pm_error("Pamtogif process failed. pclose() failed."); - ppm_freearray(pixels, rows); - if (alpha) - pgm_freearray(alpha, rows); + strfree(command); - fclose(stdout); + pm_close(ifP); + pm_close(stdout); return 0; } diff --git a/converter/ppm/ppmtoilbm.c b/converter/ppm/ppmtoilbm.c index 6c04c9be..4a1b5cb7 100644 --- a/converter/ppm/ppmtoilbm.c +++ b/converter/ppm/ppmtoilbm.c @@ -433,14 +433,14 @@ compute_ham_cmap(cols, rows, maxval, maxcolors, colorsP, hbits) tmp = hmap[i].b - b; dist += tmp * tmp; if( dist <= maxdist ) { - int sum = hmap[i].count + hmap[col].count; - - hmap[i].r = (hmap[i].r * hmap[i].count + - r * hmap[col].count + sum/2)/sum; - hmap[i].g = (hmap[i].g * hmap[i].count + - g * hmap[col].count + sum/2)/sum; - hmap[i].b = (hmap[i].b * hmap[i].count + - b * hmap[col].count + sum/2)/sum; + unsigned int sum = hmap[i].count + hmap[col].count; + + hmap[i].r = ROUNDDIV(hmap[i].r * hmap[i].count + + r * hmap[col].count, sum); + hmap[i].g = ROUNDDIV(hmap[i].g * hmap[i].count + + g * hmap[col].count, sum); + hmap[i].b = ROUNDDIV(hmap[i].b * hmap[i].count + + b * hmap[col].count, sum); hmap[i].count = sum; hmap[col] = hmap[i]; /* temp store */ @@ -635,20 +635,9 @@ ppm_to_ham(fp, cols, rows, maxval, colormap, colors, cmapmaxval, hamplanes) static long -#ifdef __STDC__ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, pixval hammaxval, int nPlanes, pixel *colormap, int colors) -#else -do_ham_body(ifP, ofp, cols, rows, maxval, hammaxval, nPlanes, colormap, colors) - FILE *ifP, *ofp; - int cols, rows; - pixval maxval; /* maxval of image color components */ - pixval hammaxval; /* maxval of HAM color changes */ - int nPlanes; - pixel *colormap; - int colors; -#endif { register int col, row, i; rawtype *raw_rowbuf; @@ -876,16 +865,8 @@ ppm_to_deep(fp, cols, rows, maxval, bitspercolor) static long -#if __STDC__ do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, int bitspercolor) -#else -do_deep_body(ifP, ofp, cols, rows, maxval, bitspercolor) - FILE *ifP, *ofp; - int cols, rows; - pixval maxval; - int bitspercolor; -#endif { register int row, col; pixel *pP; @@ -1014,16 +995,8 @@ ppm_to_dcol(fp, cols, rows, maxval, dcol) static long -#if __STDC__ do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, DirectColor *dcol) -#else -do_dcol_body(ifP, ofp, cols, rows, maxval, dcol) - FILE *ifP, *ofp; - int cols, rows; - pixval maxval; - DirectColor *dcol; -#endif { register int row, col; pixel *pP; @@ -1161,18 +1134,8 @@ ppm_to_std(fp, cols, rows, maxval, colormap, colors, cmapmaxval, static long -#if __STDC__ do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, pixel *colormap, int colors, int nPlanes) -#else -do_std_body(ifP, ofp, cols, rows, maxval, colormap, colors, nPlanes) - FILE *ifP, *ofp; - int cols, rows; - pixval maxval; - pixel *colormap; - int colors; - int nPlanes; -#endif { register int row, col, i; pixel *pP; @@ -1783,12 +1746,7 @@ runbyte1(size) /************ other utility functions ************/ static void -#if __STDC__ put_big_short(short s) -#else -put_big_short(s) - short s; -#endif { if ( pm_writebigshort( stdout, s ) == -1 ) pm_error( "write error" ); @@ -1818,12 +1776,12 @@ static int * make_val_table(oldmaxval, newmaxval) int oldmaxval, newmaxval; { - int i; - int *table; + unsigned int i; + int * table; MALLOCARRAY_NOFAIL(table, oldmaxval + 1); - for(i = 0; i <= oldmaxval; i++ ) - table[i] = (i * newmaxval + oldmaxval/2) / oldmaxval; + for (i = 0; i <= oldmaxval; ++i) + table[i] = ROUNDDIV(i * newmaxval, oldmaxval); return table; } diff --git a/converter/ppm/ppmtoleaf.c b/converter/ppm/ppmtoleaf.c index fa5fdaf5..dcff0985 100644 --- a/converter/ppm/ppmtoleaf.c +++ b/converter/ppm/ppmtoleaf.c @@ -1,4 +1,4 @@ -/* ppmtoleaf.c - read a portable pixmap and produce a ileaf img file +/* ppmtoleaf.c - read a PPM and produce a ileaf img file * * Copyright (C) 1994 by Bill O'Donnell. * @@ -15,57 +15,60 @@ */ #include <stdio.h> + #include "ppm.h" #define MAXCOLORS 256 -pixel **pixels; +pixel ** pixels; colorhash_table cht; -int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS]; +static int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS]; static int -colorstobpp( colors ) -int colors; -{ +colorstobpp(unsigned int const colors) { + int bpp; - if ( colors <= 2 ) - bpp = 1; - else if ( colors <= 256 ) - bpp = 8; + if (colors <= 2) + bpp = 1; + else if (colors <= 256) + bpp = 8; else - bpp = 24; + bpp = 24; + return bpp; } static int -GetPixel( x, y ) -int x, y; -{ +GetPixel(int const x, + int const y) { + int color; - color = ppm_lookupcolor( cht, &pixels[y][x] ); + color = ppm_lookupcolor(cht, &pixels[y][x]); + return color; } -/* OK, this routine is not wicked efficient, but it is simple to follow - and it works. */ + static void -leaf_writeimg(width, height, depth, ncolors, maxval) -int width; -int height; -int depth; -int ncolors; -{ - int i,row,col; - +leaf_writeimg(unsigned int const width, + unsigned int const height, + unsigned int const depth, + unsigned int const ncolors, + pixval const maxval) { + + /* OK, this routine is not wicked efficient, but it is simple to follow + and it works. + */ + /* NOTE: byte order in ileaf img file fmt is big-endian, always! */ /* magic */ @@ -115,136 +118,142 @@ int ncolors; /* format, mono/gray = 0x20000000, RGB=0x29000000 */ if (depth == 1) - fputc(0x20, stdout); + fputc(0x20, stdout); else - fputc(0x29, stdout); + fputc(0x29, stdout); + fputc(0x00, stdout); fputc(0x00, stdout); fputc(0x00, stdout); /* colormap size */ - if (depth == 8) - { - fputc((unsigned char)((ncolors >> 8) & 0x00ff), stdout); - fputc((unsigned char)(ncolors & 0x00ff), stdout); - for (i=0; i<256; i++) - fputc((unsigned char) Red[i]*255/maxval, stdout); - for (i=0; i<256; i++) - fputc((unsigned char) Green[i]*255/maxval, stdout); - for (i=0; i<256; i++) - fputc((unsigned char) Blue[i]*255/maxval, stdout); - - for (row=0; row<height; row++) - { - for (col=0; col<width; col++) - fputc(GetPixel(col, row), stdout); - if (width % 2) - fputc(0x00, stdout); /* pad to 2-bytes */ - } + if (depth == 8) { + unsigned int i; + unsigned int row; + + fputc((unsigned char)((ncolors >> 8) & 0x00ff), stdout); + fputc((unsigned char)(ncolors & 0x00ff), stdout); + for (i = 0; i < 256; ++i) + fputc((unsigned char) Red[i]*255/maxval, stdout); + for (i=0; i < 256; ++i) + fputc((unsigned char) Green[i]*255/maxval, stdout); + for (i = 0; i < 256; ++i) + fputc((unsigned char) Blue[i]*255/maxval, stdout); + + for (row=0; row < height; ++row) { + unsigned int col; + for (col = 0; col < width; ++col) + fputc(GetPixel(col, row), stdout); + if ((width % 2) != 0) + fputc(0x00, stdout); /* pad to 2-bytes */ + } } else if (depth == 1) { - /* mono image */ - /* no colormap */ - fputc(0x00, stdout); - fputc(0x00, stdout); - - for (row=0; row<height; row++) - { - unsigned char bits = 0; - for (col=0; col<width; col++) { - if (GetPixel(col,row)) - bits |= (unsigned char) (0x0080 >> (col % 8)); - if (((col + 1) % 8) == 0) { - fputc(bits, stdout); - bits = 0; - } - } - if ((width % 8) != 0) - fputc(bits, stdout); - if ((width % 16) && (width % 16) <= 8) - fputc(0x00, stdout); /* 16 bit pad */ - } + /* mono image */ + /* no colormap */ + + unsigned int row; + + fputc(0x00, stdout); + fputc(0x00, stdout); + + for (row = 0; row < height; ++row) { + unsigned char bits; + unsigned int col; + bits = 0; + for (col = 0; col < width; ++col) { + if (GetPixel(col,row)) + bits |= (unsigned char) (0x0080 >> (col % 8)); + if (((col + 1) % 8) == 0) { + fputc(bits, stdout); + bits = 0; + } + } + if ((width % 8) != 0) + fputc(bits, stdout); + if ((width % 16) && (width % 16) <= 8) + fputc(0x00, stdout); /* 16 bit pad */ + } } else { - /* no colormap, direct or true color (24 bit) image */ - fputc(0x00, stdout); - fputc(0x00, stdout); - - for (row=0; row<height; row++) - { - for (col=0; col<width; col++) - fputc(pixels[row][col].r * 255 / maxval, stdout); - if (width % 2) - fputc(0x00, stdout); /* pad to 2-bytes */ - for (col=0; col<width; col++) - fputc(pixels[row][col].g * 255 / maxval, stdout); - if (width % 2) - fputc(0x00, stdout); /* pad to 2-bytes */ - for (col=0; col<width; col++) - fputc(pixels[row][col].b * 255 / maxval, stdout); - if (width % 2) - fputc(0x00, stdout); /* pad to 2-bytes */ - } + /* no colormap, direct or true color (24 bit) image */ + + unsigned int row; + + fputc(0x00, stdout); + fputc(0x00, stdout); + + for (row = 0; row < height; ++row) { + unsigned int col; + for (col = 0; col < width; ++col) + fputc(pixels[row][col].r * 255 / maxval, stdout); + if (width % 2 != 0) + fputc(0x00, stdout); /* pad to 2-bytes */ + for (col = 0; col < width; ++col) + fputc(pixels[row][col].g * 255 / maxval, stdout); + if (width % 2 != 0) + fputc(0x00, stdout); /* pad to 2-bytes */ + for (col = 0; col < width; ++col) + fputc(pixels[row][col].b * 255 / maxval, stdout); + if (width % 2 != 0) + fputc(0x00, stdout); /* pad to 2-bytes */ + } } } int -main( argc, argv ) -int argc; -char *argv[]; -{ - FILE *ifd; - int argn, rows, cols, colors, i, BitsPerPixel; +main(int argc, const char * argv[]) { + + FILE * ifP; + int argn; + int rows, cols; + unsigned int BitsPerPixel; + int colors; pixval maxval; colorhist_vector chv; const char * const usage = "[ppmfile]"; - ppm_init(&argc, argv); + pm_proginit(&argc, argv); argn = 1; - if ( argn < argc ) - { - ifd = pm_openr( argv[argn] ); - argn++; + if (argn < argc) { + ifP = pm_openr(argv[argn]); + argn++; } else - ifd = stdin; + ifP = stdin; - if ( argn != argc ) - pm_usage( usage ); + if (argn != argc) + pm_usage(usage); - pixels = ppm_readppm( ifd, &cols, &rows, &maxval ); + pixels = ppm_readppm(ifP, &cols, &rows, &maxval); - pm_close( ifd ); + pm_close(ifP); /* Figure out the colormap. */ - fprintf( stderr, "(Computing colormap..." ); - fflush( stderr ); - chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors ); - if ( chv != (colorhist_vector) 0 ) - { - fprintf( stderr, " Done. %d colors found.)\n", colors ); - - for ( i = 0; i < colors; i++ ) - { - Red[i] = (int) PPM_GETR( chv[i].color ); - Green[i] = (int) PPM_GETG( chv[i].color ); - Blue[i] = (int) PPM_GETB( chv[i].color ); - } - BitsPerPixel = colorstobpp( colors ); - - /* And make a hash table for fast lookup. */ - cht = ppm_colorhisttocolorhash( chv, colors ); - ppm_freecolorhist( chv ); + pm_message("Computing colormap..."); + chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors); + if (chv) { + unsigned int i; + + pm_message("... Done. %u colors found.", colors); + + for (i = 0; i < colors; ++i) { + Red[i] = (int) PPM_GETR( chv[i].color); + Green[i] = (int) PPM_GETG( chv[i].color); + Blue[i] = (int) PPM_GETB( chv[i].color); + } + BitsPerPixel = colorstobpp(colors); + + /* And make a hash table for fast lookup. */ + cht = ppm_colorhisttocolorhash(chv, colors); + ppm_freecolorhist(chv); } else { - BitsPerPixel = 24; - fprintf( stderr, " Done. 24-bit true color %d color image.)\n", colors ); + BitsPerPixel = 24; + pm_message(" ... Done. 24-bit true color %u color image.", colors); } leaf_writeimg(cols, rows, BitsPerPixel, colors, maxval); - return( 0 ); + return 0; } - - - diff --git a/converter/ppm/ppmtomitsu.c b/converter/ppm/ppmtomitsu.c index 3934ae45..e59f09b3 100644 --- a/converter/ppm/ppmtomitsu.c +++ b/converter/ppm/ppmtomitsu.c @@ -1,10 +1,10 @@ -/* ppmtomitsu.c - read a portable pixmap and produce output for the +/* ppmtomitsu.c - read a PPM image and produce output for the ** Mitsubishi S340-10 Thermo-Sublimation Printer ** (or the S3410-30 parallel interface) ** ** Copyright (C) 1992,93 by S.Petra Zeidler ** Minor modifications by Ingo Wilken: -x** - mymalloc() and check_and_rotate() functions for often used +** - mymalloc() and check_and_rotate() functions for often used ** code fragments. Reduces code size by a few KB. ** - use pm_error() instead of fprintf(stderr) ** - localized allocation of colorhastable @@ -20,362 +20,70 @@ x** - mymalloc() and check_and_rotate() functions for often used ** implied warranty. */ +#include <assert.h> #include <string.h> +#include <stdio.h> #include "pm_c_util.h" -#include "ppm.h" #include "nstring.h" #include "mallocvar.h" +#include "ppm.h" #include "mitsu.h" -#include <stdio.h> - #define HASHSIZE 2048 #define myhash(x) ((PPM_GETR(x)*3 + PPM_GETG(x)*5 + PPM_GETB(x)*7) % HASHSIZE) typedef struct hashinfo { pixel color; long flag; - struct hashinfo *next; + struct hashinfo * next; } hashinfo; -#ifdef __STDC__ -static void lineputinit(int cols, int rows, int sharpness, int enlarge, int - copy, struct mediasize medias); -static void frametransferinit(int cols, int rows, int sharpness, int enlarge, - int copy, struct mediasize medias); -static void lookuptableinit(int sharpness, int enlarge, int copy, - struct mediasize medias); -static void lookuptabledata(int cols, int rows, int enlarge, - struct mediasize medias); -static void check_and_rotate(int cols, int rows, int enlarge, - struct mediasize medias); -#define CONST const -#else /*__STDC__*/ -static int lineputinit(); -static int lookuptableinit(); -static int lookuptabledata(); -static int frametransferinit(); -static int check_and_rotate(); -#define CONST -#endif - #define cmd(arg) fputc((arg), stdout) #define datum(arg) fputc((char)(arg), stdout) #define data(arg,num) fwrite((arg), sizeof(char), (num), stdout) -#ifdef __STDC__ -int main(int argc, char *argv[] ) -#else -int main( argc, argv ) - int argc; - char* argv[]; -#endif - { - FILE *ifp; - /*hashinfo colorhashtable[HASHSIZE];*/ - struct hashinfo *hashrun; - pixel *xP; - int argn; - bool dpi300; - int cols, rows, format, col, row; - int sharpness, enlarge, copy, tiny; - pixval maxval; - struct mediasize medias; - char media[16]; - const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media <a,a4,as,a4s>] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]"; - - ppm_init(&argc, argv); - - dpi300 = FALSE; - argn = 1; - sharpness = 32; - enlarge = 1; - copy = 1; - memset(media, '\0', 16); - tiny = FALSE; - - /* check for flags */ - while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { - if (pm_keymatch(argv[argn], "-sharpness", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1) - pm_usage(usage); - else if (sharpness < 1 || sharpness > 4) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-enlarge", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1) - pm_usage(usage); - else if (enlarge < 1 || enlarge > 3) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-media", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%15s", media) < 1) - pm_usage(usage); - else if (TOUPPER(media[0]) != 'A') - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-copy", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", ©) != 1) - pm_usage(usage); - else if (copy < 1 || copy > 9) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-dpi300", 2)) - dpi300 = TRUE; - else if (pm_keymatch(argv[argn], "-tiny", 2)) - tiny = TRUE; - else - pm_usage(usage); - ++argn; - } - - if (argn < argc) { - ifp = pm_openr(argv[argn]); - ++argn; - } - else - ifp = stdin; - - if (argn != argc) - pm_usage(usage); - if (TOUPPER(media[0]) == 'A') - switch (TOUPPER(media[1])) { - case 'S': - medias = MSize_AS; - break; - case '4': - if(TOUPPER(media[2]) == 'S') - medias = MSize_A4S; - else { - medias = MSize_A4; - } - break; - default: - medias = MSize_A; - } - else - medias = MSize_User; - - if (dpi300) { - medias.maxcols *= 2; - medias.maxrows *= 2; - } +static void +check_and_rotate(int const cols, + int const rows, + int const enlarge, + struct mediasize const medias) { - if (tiny) { - pixel *pixelrow; - char *redrow, *greenrow, *bluerow; - - ppm_readppminit(ifp, &cols, &rows, &maxval, &format); - pixelrow = (pixel *) ppm_allocrow(cols); - MALLOCARRAY_NOFAIL(redrow, cols); - MALLOCARRAY_NOFAIL(greenrow, cols); - MALLOCARRAY_NOFAIL(bluerow, cols); - lineputinit(cols, rows, sharpness, enlarge, copy, medias); - - for ( row = 0; row < rows; ++row ) { - ppm_readppmrow(ifp, pixelrow, cols, maxval, format); - switch(PPM_FORMAT_TYPE(format)) { - /* color */ - case PPM_TYPE: - for (col = 0, xP = pixelrow; col < cols; col++, xP++) { - /* First red. */ - redrow[col] = PPM_GETR(*xP); - /* Then green. */ - greenrow[col] = PPM_GETG(*xP); - /* And blue. */ - bluerow[col] = PPM_GETB(*xP); - } - data(redrow, cols); - data(greenrow, cols); - data(bluerow, cols); - break; - /* grayscale */ - default: - for (col = 0, xP = pixelrow; col < cols; col++, xP++) - bluerow[col] = PPM_GETB(*xP); - data(bluerow, cols); - data(bluerow, cols); - data(bluerow, cols); - break; - } - } - pm_close(ifp); + if (cols > rows) { + ROTATEIMG(DOROTATE); /* rotate image */ + if (enlarge * rows > medias.maxcols || enlarge * cols > medias.maxrows) + pm_error("Image too large, MaxPixels = %u x %u", + medias.maxrows, medias.maxcols); + HPIXELS(cols); + VPIXELS(rows); + HPIXELSOFF((medias.maxcols/enlarge - rows)/2); + VPIXELSOFF((medias.maxrows/enlarge - cols)/2); + pm_message("rotating image for output"); + } else { + ROTATEIMG(DONTROTATE); + if (enlarge * rows > medias.maxrows || enlarge * cols > medias.maxcols) + pm_error("Image too large, MaxPixels = %u x %u", + medias.maxrows, medias.maxcols); + HPIXELS(cols); + VPIXELS(rows); + HPIXELSOFF((medias.maxcols/enlarge - cols)/2); + VPIXELSOFF((medias.maxrows/enlarge - rows)/2); } - else { - pixel **pixelpic; - int colanz, colval; - int i; - colorhist_vector table; - - ppm_readppminit( ifp, &cols, &rows, &maxval, &format ); - pixelpic = ppm_allocarray( cols, rows ); - for (row = 0; row < rows; row++) - ppm_readppmrow( ifp, pixelpic[row], cols, maxval, format ); - pm_close(ifp); - - /* first check wether we can use the lut transfer */ +} - table = ppm_computecolorhist(pixelpic, cols, rows, MAXLUTCOL+1, - &colanz); - if (table != NULL) { - hashinfo *colorhashtable; - MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE); - for (i=0; i<HASHSIZE; i++) { - colorhashtable[i].flag = -1; - colorhashtable[i].next = NULL; - } - /* we can use the lookuptable */ - pm_message("found %d colors - using the lookuptable-method", - colanz); - lookuptableinit(sharpness, enlarge, copy, medias); - switch(PPM_FORMAT_TYPE(format)) { - /* color */ - case PPM_TYPE: - for (colval=0; colval<colanz; colval++) { - cmd('$'); - datum(colval); - datum(PPM_GETR((table[colval]).color)); - datum(PPM_GETG((table[colval]).color)); - datum(PPM_GETB((table[colval]).color)); - - hashrun = &colorhashtable[myhash((table[colval]).color)]; - if (hashrun->flag == -1) { - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - } - else { - while (hashrun->next != NULL) - hashrun = hashrun->next; - MALLOCVAR_NOFAIL(hashrun->next); - hashrun = hashrun->next; - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - hashrun->next = NULL; - } - } - break; - /* other */ - default: - for (colval=0; colval<colanz; colval++) { - cmd('$'); - datum(colval); - datum(PPM_GETB((table[colval]).color)); - datum(PPM_GETB((table[colval]).color)); - datum(PPM_GETB((table[colval]).color)); - - hashrun = &colorhashtable[myhash((table[colval]).color)]; - if (hashrun->flag == -1) { - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - } - else { - while (hashrun->next != NULL) - hashrun = hashrun->next; - MALLOCVAR_NOFAIL(hashrun->next); - hashrun = hashrun->next; - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - hashrun->next = NULL; - } - } - } - lookuptabledata(cols, rows, enlarge, medias); - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) { - hashrun = &colorhashtable[myhash(*xP)]; - while (!PPM_EQUAL((hashrun->color), *xP)) - if (hashrun->next != NULL) - hashrun = hashrun->next; - else { - pm_error("you just found a lethal bug."); - } - datum(hashrun->flag); - } - } - free(colorhashtable); - } - else { - /* $#%@^!& no lut possible, so send the pic as 24bit */ - pm_message("found too many colors for fast lookuptable mode"); - frametransferinit(cols, rows, sharpness, enlarge, copy, medias); - switch(PPM_FORMAT_TYPE(format)) { - /* color */ - case PPM_TYPE: - COLORDES(RED); - DATASTART; /* red coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETR(*xP)); - } - COLORDES(GREEN); - DATASTART; /* green coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETG(*xP)); - } - COLORDES(BLUE); - DATASTART; /* blue coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETB(*xP)); - } - break; - /* grayscale */ - default: - COLORDES(RED); - DATASTART; /* red coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETB(*xP)); - } - COLORDES(GREEN); - DATASTART; /* green coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETB(*xP)); - } - COLORDES(BLUE); - DATASTART; /* blue coming */ - for (row=0; row<rows; row++) { - xP = pixelpic[row]; - for (col=0; col<cols; col++, xP++) - datum(PPM_GETB(*xP)); - } - } - } - } - PRINTIT; - exit(0); -} - -#ifdef __STDC__ -static void lineputinit(int cols, int rows, - int sharpness, int enlarge, int copy, - struct mediasize medias) -#else /*__STDC__*/ -static int lineputinit(cols, rows, sharpness, enlarge, copy, medias) - int cols, rows; - int sharpness, enlarge, copy; - struct mediasize medias; -#endif /*__STDC__*/ -{ +static void +lineputinit(int const cols, + int const rows, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { ONLINE; CLRMEM; MEDIASIZE(medias); @@ -426,18 +134,16 @@ static int lineputinit(cols, rows, sharpness, enlarge, copy, medias) } check_and_rotate(cols, rows, enlarge, medias); DATASTART; - return; } -#ifdef __STDC__ -static void lookuptableinit(int sharpness, int enlarge, int copy, - struct mediasize medias) -#else /*__STDC__*/ -static int lookuptableinit(sharpness, enlarge, copy, medias) - int sharpness, enlarge, copy; - struct mediasize medias; -#endif /*__STDC__*/ -{ + + +static void +lookuptableinit(int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { + ONLINE; CLRMEM; MEDIASIZE(medias); @@ -486,36 +192,31 @@ static int lookuptableinit(sharpness, enlarge, copy, medias) } LOADLOOKUPTABLE; - return; } -#ifdef __STDC__ -static void lookuptabledata(int cols, int rows, int enlarge, - struct mediasize medias) -#else /*__STDC__*/ -static int lookuptabledata(cols, rows, enlarge, medias) - int rows, cols; - int enlarge; - struct mediasize medias; -#endif /*__STDC__*/ -{ + + +static void +lookuptabledata(int const cols, + int const rows, + int const enlarge, + struct mediasize const medias) { + DONELOOKUPTABLE; check_and_rotate(cols, rows, enlarge, medias); DATASTART; - return; } -#ifdef __STDC__ -static void frametransferinit(int cols, int rows, int sharpness, - int enlarge, int copy, struct mediasize medias) -#else -static int frametransferinit(cols, rows, sharpness, enlarge, copy, medias) - int rows, cols; - int sharpness, enlarge, copy; - struct mediasize medias; -#endif -{ + +static void +frametransferinit(int const cols, + int const rows, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { + ONLINE; CLRMEM; MEDIASIZE(medias); @@ -565,40 +266,458 @@ static int frametransferinit(cols, rows, sharpness, enlarge, copy, medias) SHARPNESS(SP_USER); } check_and_rotate(cols, rows, enlarge, medias); - return; } -#ifdef __STDC__ + static void -check_and_rotate(int cols, int rows, int enlarge, struct mediasize medias) -#else -static int -check_and_rotate(cols, rows, enlarge, medias) - int cols, rows, enlarge; - struct mediasize medias; -#endif -{ - if (cols > rows) { - ROTATEIMG(DOROTATE); /* rotate image */ - if (enlarge*rows > medias.maxcols || enlarge*cols > medias.maxrows) { - pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols); +doLookupTableColors(colorhist_vector const table, + unsigned int const nColor, + hashinfo * const colorhashtable) { + + unsigned int colval; + for (colval = 0; colval < nColor; ++colval) { + struct hashinfo * const hashchain = + &colorhashtable[myhash((table[colval]).color)]; + + struct hashinfo * hashrun; + + cmd('$'); + datum(colval); + datum(PPM_GETR((table[colval]).color)); + datum(PPM_GETG((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + + hashrun = hashchain; /* start at beginning of chain */ + + if (hashrun->flag == -1) { + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + } else { + while (hashrun->next != NULL) + hashrun = hashrun->next; + MALLOCVAR_NOFAIL(hashrun->next); + hashrun = hashrun->next; + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + hashrun->next = NULL; } - HPIXELS(cols); - VPIXELS(rows); - HPIXELSOFF((medias.maxcols/enlarge - rows)/2); - VPIXELSOFF((medias.maxrows/enlarge - cols)/2); - pm_message("rotating image for output"); } - else { - ROTATEIMG(DONTROTATE); - if (enlarge*rows > medias.maxrows || enlarge*cols > medias.maxcols) { - pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols); +} + + + +static void +doLookupTableGrays(colorhist_vector const table, + unsigned int const nColor, + hashinfo * const colorhashtable) { + + unsigned int colval; + for (colval = 0; colval < nColor; ++colval) { + struct hashinfo * const hashchain = + &colorhashtable[myhash((table[colval]).color)]; + struct hashinfo * hashrun; + + cmd('$'); + datum(colval); + datum(PPM_GETB((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + + hashrun = hashchain; /* start at beginning of chain */ + + if (hashrun->flag == -1) { + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + } else { + while (hashrun->next != NULL) + hashrun = hashrun->next; + MALLOCVAR_NOFAIL(hashrun->next); + hashrun = hashrun->next; + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + hashrun->next = NULL; } - HPIXELS(cols); - VPIXELS(rows); - HPIXELSOFF((medias.maxcols/enlarge - cols)/2); - VPIXELSOFF((medias.maxrows/enlarge - rows)/2); } } + + +static void +generateLookupTable(colorhist_vector const table, + unsigned int const nColor, + unsigned int const cols, + unsigned int const rows, + int const format, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias, + hashinfo ** const colorhashtableP) { +/*---------------------------------------------------------------------------- + Write to the output file the palette (color lookup table) indicated by + 'table' and generate a hash table to use with it: *colorhashtableP. + + Also write the various properties 'sharpness', 'enlarge', 'copy', and + 'medias' to the output file. +-----------------------------------------------------------------------------*/ + hashinfo * colorhashtable; + + lookuptableinit(sharpness, enlarge, copy, medias); + + /* Initialize the hash table to empty */ + + MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE); + { + unsigned int i; + for (i = 0; i < HASHSIZE; ++i) { + colorhashtable[i].flag = -1; + colorhashtable[i].next = NULL; + } + } + + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: + doLookupTableColors(table, nColor, colorhashtable); + break; + default: + doLookupTableGrays(table, nColor, colorhashtable); + } + lookuptabledata(cols, rows, enlarge, medias); + + *colorhashtableP = colorhashtable; +} + + + +static void +writeColormapRaster(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + hashinfo * const colorhashtable) { +/*---------------------------------------------------------------------------- + Write a colormapped raster: write the pixels pixels[][] (dimensions cols x + rows) as indices into the colormap (palette; lookup table) indicated by + 'colorhashtable'. +-----------------------------------------------------------------------------*/ + unsigned int row; + + for (row = 0; row < rows; ++row) { + unsigned int col; + + for (col = 0; col < cols; ++col) { + pixel * const pixrow = pixels[row]; + struct hashinfo * const hashchain = + &colorhashtable[myhash(pixrow[col])]; + struct hashinfo * p; + + p = hashchain; + while (!PPM_EQUAL((p->color), pixrow[col])) { + assert(p->next); + p = p->next; + } + datum(p->flag); + } + } +} + + + +static void +useLookupTable(pixel ** const pixels, + colorhist_vector const table, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias, + unsigned int const cols, + unsigned int const rows, + int const format, + unsigned int const nColor) { + + hashinfo * colorhashtable; + + pm_message("found %u colors - using the lookuptable-method", nColor); + + generateLookupTable(table, nColor, cols, rows, format, + sharpness, enlarge, copy, medias, + &colorhashtable); + + writeColormapRaster(pixels, cols, rows, colorhashtable); + + free(colorhashtable); +} + + + +static void +noLookupColor(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows) { + + unsigned int row; + COLORDES(RED); + DATASTART; /* red coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETR(pixrow[col])); + } + COLORDES(GREEN); + DATASTART; /* green coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETG(pixrow[col])); + } + COLORDES(BLUE); + DATASTART; /* blue coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } +} + + + +static void +noLookupGray(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows) { + + unsigned int row; + COLORDES(RED); + DATASTART; /* red coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } + COLORDES(GREEN); + DATASTART; /* green coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } + COLORDES(BLUE); + DATASTART; /* blue coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } +} + + + +static void +useNoLookupTable(pixel ** const pixels, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias, + unsigned int const cols, + unsigned int const rows, + int const format) { + + /* $#%@^!& no lut possible, so send the pic as 24bit */ + + pm_message("found too many colors for fast lookuptable mode"); + + frametransferinit(cols, rows, sharpness, enlarge, copy, medias); + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: + noLookupColor(pixels, cols, rows); + break; + default: + noLookupGray(pixels, cols, rows); + } +} + + + +static void +doTiny(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + int const format, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { + + pixel * pixelrow; + unsigned char * redrow; + unsigned char * grnrow; + unsigned char * blurow; + unsigned int row; + + pixelrow = ppm_allocrow(cols); + MALLOCARRAY_NOFAIL(redrow, cols); + MALLOCARRAY_NOFAIL(grnrow, cols); + MALLOCARRAY_NOFAIL(blurow, cols); + lineputinit(cols, rows, sharpness, enlarge, copy, medias); + + for (row = 0; row < rows; ++row) { + ppm_readppmrow(ifP, pixelrow, cols, maxval, format); + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: { /* color */ + unsigned int col; + for (col = 0; col < cols; ++col) { + redrow[col] = PPM_GETR(pixelrow[col]); + grnrow[col] = PPM_GETG(pixelrow[col]); + blurow[col] = PPM_GETB(pixelrow[col]); + } + data(redrow, cols); + data(grnrow, cols); + data(blurow, cols); + } break; + default: { /* grayscale */ + unsigned int col; + for (col = 0; col < cols; ++col) + blurow[col] = PPM_GETB(pixelrow[col]); + data(blurow, cols); + data(blurow, cols); + data(blurow, cols); + } + } + } +} + + + +int +main(int argc, char * argv[]) { + FILE * ifP; + int argn; + bool dpi300; + int cols, rows, format; + pixval maxval; + int sharpness, enlarge, copy, tiny; + struct mediasize medias; + char media[16]; + const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media <a,a4,as,a4s>] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]"; + + ppm_init(&argc, argv); + + dpi300 = FALSE; + argn = 1; + sharpness = 32; + enlarge = 1; + copy = 1; + memset(media, '\0', 16); + tiny = FALSE; + + /* check for flags */ + while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { + if (pm_keymatch(argv[argn], "-sharpness", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1) + pm_usage(usage); + else if (sharpness < 1 || sharpness > 4) + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-enlarge", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1) + pm_usage(usage); + else if (enlarge < 1 || enlarge > 3) + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-media", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%15s", media) < 1) + pm_usage(usage); + else if (TOUPPER(media[0]) != 'A') + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-copy", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", ©) != 1) + pm_usage(usage); + else if (copy < 1 || copy > 9) + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-dpi300", 2)) + dpi300 = TRUE; + else if (pm_keymatch(argv[argn], "-tiny", 2)) + tiny = TRUE; + else + pm_usage(usage); + ++argn; + } + + if (argn < argc) { + ifP = pm_openr(argv[argn]); + ++argn; + } + else + ifP = stdin; + + if (argn != argc) + pm_usage(usage); + + if (TOUPPER(media[0]) == 'A') + switch (TOUPPER(media[1])) { + case 'S': + medias = MSize_AS; + break; + case '4': + if(TOUPPER(media[2]) == 'S') + medias = MSize_A4S; + else { + medias = MSize_A4; + } + break; + default: + medias = MSize_A; + } + else + medias = MSize_User; + + if (dpi300) { + medias.maxcols *= 2; + medias.maxrows *= 2; + } + + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); + + if (tiny) { + doTiny(ifP, cols, rows, maxval, format, + sharpness, enlarge, copy, medias); + + } else { + pixel ** pixels; + int nColor; + colorhist_vector table; + unsigned int row; + + pixels = ppm_allocarray(cols, rows); + for (row = 0; row < rows; ++row) + ppm_readppmrow(ifP, pixels[row], cols, maxval, format); + + /* first check wether we can use the lut transfer */ + + table = ppm_computecolorhist(pixels, cols, rows, MAXLUTCOL+1, + &nColor); + if (table) + useLookupTable(pixels, table, sharpness, enlarge, copy, medias, + cols, rows, format, nColor); + else + useNoLookupTable(pixels, sharpness, enlarge, copy, medias, + cols, rows, format); + ppm_freearray(pixels, rows); + } + PRINTIT; + pm_close(ifP); + return 0; +} diff --git a/converter/ppm/ppmtomitsu.test b/converter/ppm/ppmtomitsu.test new file mode 100644 index 00000000..f574d927 --- /dev/null +++ b/converter/ppm/ppmtomitsu.test @@ -0,0 +1,12 @@ +echo Test 1. Should print 3110813682 101562 +./ppmtomitsu ../../testimg.ppm | cksum +echo Test 2. Should print 239186803 34399 +pnmquant 100 ../../testimg.ppm | ./ppmtomitsu | cksum +echo Test 3. Should print 3201293405 310 +./ppmtomitsu ../../testgrid.pbm | cksum +echo Test 4. Should print 3354679572 752 +./ppmtomitsu -tiny ../../testgrid.pbm | cksum +echo Test 5. Should print 3999654426 101549 +./ppmtomitsu -tiny ../../testimg.ppm | cksum +echo Test 2. Should print 3078685526 101549 +pnmquant 100 ../../testimg.ppm | ./ppmtomitsu -tiny | cksum diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile index 4e0ad8d6..d3342c9a 100644 --- a/converter/ppm/ppmtompeg/Makefile +++ b/converter/ppm/ppmtompeg/Makefile @@ -5,7 +5,7 @@ endif SUBDIR = converter/ppm/ppmtompeg VPATH=.:$(SRCDIR)/$(SUBDIR) -include $(BUILDDIR)/Makefile.config +include $(BUILDDIR)/config.mk ifeq ($(JPEGLIB),NONE) # 'nojpeg' is a module that implements all the jpeg access routines as @@ -18,11 +18,12 @@ else JPEGLIBX = $(JPEGLIB) endif -INCLUDES = -I$(SRCDIR)/$(SUBDIR)/headers +COMP_INCLUDES = -I$(SRCDIR)/$(SUBDIR)/headers +EXTERN_INCLUDES = ifneq ($(JPEGHDR_DIR),NONE) ifneq ($(JPEGHDR_DIR)x,x) - INCLUDES += -I$(JPEGHDR_DIR) + EXTERN_INCLUDES += -I$(JPEGHDR_DIR) endif endif @@ -38,17 +39,31 @@ endif # MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o -MP_ENCODE_OBJS = iframe.o pframe.o bframe.o psearch.o bsearch.o block.o +MP_ENCODE_OBJS = \ + frames.o \ + iframe.o \ + pframe.o \ + bframe.o \ + psearch.o \ + bsearch.o \ + block.o + MP_OTHER_OBJS = mpeg.o subsample.o param.o rgbtoycc.o \ readframe.o combine.o jrevdct.o frame.o fsize.o frametype.o \ - specifics.o rate.o opts.o input.o gethostname.o + specifics.o rate.o opts.o input.o ifeq ($(OMIT_NETWORK),y) - MP_PARALLEL_OBJS = noparallel.o + MP_OTHER_OBJS += noparallel.o +else + MP_OTHER_OBJS += parallel.o psocket.o +endif +ifeq ($(WIN32),y) + MP_OTHER_OBJS += gethostname_win32.o else - MP_PARALLEL_OBJS = parallel.o psocket.o + MP_OTHER_OBJS += gethostname.o endif + NONMAIN_OBJS = $(MP_BASE_OBJS) $(MP_OTHER_OBJS) $(MP_ENCODE_OBJS) \ - $(MP_PARALLEL_OBJS) $(JPEG_MODULE).o + $(JPEG_MODULE).o OBJECTS = ppmtompeg.o $(NONMAIN_OBJS) MERGE_OBJECTS = ppmtompeg.o2 $(NONMAIN_OBJS) MP_INCLUDE = mproto.h mtypes.h huff.h bitio.h @@ -61,7 +76,7 @@ SCRIPTS = .PHONY: all all: ppmtompeg -include $(SRCDIR)/Makefile.common +include $(SRCDIR)/common.mk ifeq ($(NEED_RUNTIME_PATH),Y) LIBOPTR = -runtime diff --git a/converter/ppm/ppmtompeg/bframe.c b/converter/ppm/ppmtompeg/bframe.c index 5dfb76d3..1dbc1846 100644 --- a/converter/ppm/ppmtompeg/bframe.c +++ b/converter/ppm/ppmtompeg/bframe.c @@ -84,7 +84,6 @@ static struct bframeStats { *====================*/ extern Block **dct, **dctr, **dctb; -extern dct_data_type **dct_data; #define NO_MOTION 0 #define MOTION 1 #define SKIP 2 /* used in useMotion in dct_data */ diff --git a/converter/ppm/ppmtompeg/bsearch.c b/converter/ppm/ppmtompeg/bsearch.c index 142987f5..70edfef6 100644 --- a/converter/ppm/ppmtompeg/bsearch.c +++ b/converter/ppm/ppmtompeg/bsearch.c @@ -77,6 +77,7 @@ #include "frames.h" #include "motion_search.h" #include "fsize.h" +#include "block.h" /*==================* diff --git a/converter/ppm/ppmtompeg/combine.c b/converter/ppm/ppmtompeg/combine.c index 52cc646d..8e0d3281 100644 --- a/converter/ppm/ppmtompeg/combine.c +++ b/converter/ppm/ppmtompeg/combine.c @@ -35,8 +35,8 @@ #include <errno.h> #include <unistd.h> -#include "ppm.h" #include "nstring.h" +#include "nsleep.h" #include "mtypes.h" #include "frames.h" @@ -111,11 +111,9 @@ appendSpecifiedGopFiles(struct inputSource * const inputSourceP, ++nAttempts) { ifP = fopen(fileName, "rb"); - if (ifP == NULL) { + if (ifP == NULL) pm_message("ERROR: Couldn't read file '%s'. retry %u", fileName, nAttempts); - sleep(1); - } } if (ifP) { if (!realQuiet) diff --git a/converter/ppm/ppmtompeg/file.c b/converter/ppm/ppmtompeg/file.c index ae741962..223170a4 100644 --- a/converter/ppm/ppmtompeg/file.c +++ b/converter/ppm/ppmtompeg/file.c @@ -19,17 +19,6 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -/* - * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/file.c,v 1.2 1993/06/30 20:06:09 keving Exp $ - * $Log: file.c,v $ - * Revision 1.2 1993/06/30 20:06:09 keving - * nothing - * - * Revision 1.1 1993/06/03 21:08:08 keving - * nothing - * - */ - #include "tk.h" #include "all.h" @@ -40,11 +29,10 @@ #include <time.h> #include <string.h> #include <dirent.h> -#include <strings.h> #define MAX_FILES 1000 -#define MAX_NAME_LEN 256 -#define MAX_STRING_LEN MAX_NAME_LEN +#define MAX_NAME_LEN 256 +#define MAX_STRING_LEN MAX_NAME_LEN typedef int boolean; #define TRUE 1 @@ -52,77 +40,76 @@ typedef int boolean; extern char currentPath[MAXPATHLEN]; -char globString[1024]; +char globString[1024]; -static DIR *dfd; +static DIR * dfd; -void ResetPath(void); +void ResetPath(void); int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, - char **argv); + char **argv); int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, - char **argv); -void SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN], - boolean *dirList, int permute[]); + char **argv); +void SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN], + boolean *dirList, int permute[]); + +static void UpdatePath(Tcl_Interp *interp, char *directory); +static boolean MatchesGlob(char *string, char *glob); -static void UpdatePath(Tcl_Interp *interp, char *directory); -static boolean MatchesGlob(char *string, char *glob); +void +ResetPath() { -void ResetPath() -{ - if ( getwd(currentPath) == 0 ) - { - fprintf(stderr, "Error getting pathname!!!\n"); - exit(1); + if (getwd(currentPath) == 0) { + fprintf(stderr, "Error getting pathname!!!\n"); + exit(1); } strcpy(¤tPath[strlen(currentPath)], "/"); dfd = opendir(currentPath); - if ( dfd == NULL ) - { - fprintf(stderr, "can't open '%s'\n", currentPath); - exit(1); + if (dfd == NULL) { + fprintf(stderr, "can't open '%s'\n", currentPath); + exit(1); } } -static void UpdatePath(Tcl_Interp *interp, char *directory) -{ + +static void +UpdatePath(Tcl_Interp *interp, char *directory) { + int length; char *charPtr; length = strlen(currentPath); - if ( strcmp(directory, "./") == 0 ) - return /* nothing */ ; - else if ( strcmp(directory, "../") == 0 ) - { - /* delete backwards up to '/' */ - - if ( length < 2 ) - { - fprintf(stderr, "Error: backing up from root directory!!!\n"); - exit(1); - } - - charPtr = ¤tPath[length-2]; - while ( (charPtr != currentPath) && (*charPtr != '/') ) - charPtr--; - charPtr++; /* leave the '/' */ - *charPtr = '\0'; - } - else - { - strcpy(¤tPath[length], directory); + if (streq(directory, "./")) + return /* nothing */ ; + else if (streq(directory, "../")) { + /* delete backwards up to '/' */ + + if (length < 2) { + fprintf(stderr, "Error: backing up from root directory!!!\n"); + exit(1); + } + + charPtr = ¤tPath[length-2]; + while ((charPtr != currentPath) && (*charPtr != '/')) + --charPtr; + ++charPtr; /* leave the '/' */ + *charPtr = '\0'; + } else { + strcpy(¤tPath[length], directory); } } -int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, - char **argv) -{ + +int +ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, + char **argv) { + char *directory = argv[1]; UpdatePath(interp, directory); @@ -130,82 +117,74 @@ int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, fprintf(stdout, "Opening directory: '%s'\n", currentPath); dfd = opendir(currentPath); - if ( dfd == NULL ) - { - fprintf(stderr, "can't open '%s'\n", currentPath); - return TCL_OK; /* shouldn't, really */ + if (dfd == NULL) { + fprintf(stderr, "can't open '%s'\n", currentPath); + return TCL_OK; /* shouldn't, really */ } - + return TCL_OK; } -int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, - char **argv) -{ - struct dirent *dp; + +int +ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, + char **argv) { + + struct dirent * dp; struct stat stbuf; char command[256]; char fileName[MAX_FILES][MAX_NAME_LEN]; boolean dirList[MAX_FILES]; int permute[MAX_FILES]; - int fileCount = 0; - register int index; + int fileCount = 0; + int index; char fullName[MAXPATHLEN]; - char *restPtr; + char * restPtr; sprintf(command, "ShowCurrentDirectory %s", currentPath); Tcl_Eval(interp, command, 0, (char **) NULL); - if ( dfd == NULL ) - { - fprintf(stderr, "TRIED TO LIST NULL DIRECTORY\n"); + if (dfd == NULL) { + fprintf(stderr, "TRIED TO LIST NULL DIRECTORY\n"); - return TCL_OK; + return TCL_OK; } -/* check if root directory */ - if ( strlen(currentPath) != 1 ) - { - sprintf(fileName[fileCount], "../"); - dirList[fileCount] = TRUE; - fileCount++; + /* check if root directory */ + if (strlen(currentPath) != 1) { + sprintf(fileName[fileCount], "../"); + dirList[fileCount] = TRUE; + ++fileCount; } strcpy(fullName, currentPath); restPtr = &fullName[strlen(fullName)]; - while ( (dp = readdir(dfd)) != NULL ) - { - strcpy(restPtr, dp->d_name); - stat(fullName, &stbuf); - - if ( dp->d_name[0] != '.' ) - { - if ( S_ISDIR(stbuf.st_mode) ) - { - sprintf(fileName[fileCount], "%s/", dp->d_name); - dirList[fileCount] = TRUE; - fileCount++; - } - else - { - if ( MatchesGlob(dp->d_name, globString) ) - { - strcpy(fileName[fileCount], dp->d_name); - dirList[fileCount] = FALSE; - fileCount++; - } - } - } + while ((dp = readdir(dfd)) != NULL) { + strcpy(restPtr, dp->d_name); + stat(fullName, &stbuf); + + if (dp->d_name[0] != '.') { + if (S_ISDIR(stbuf.st_mode)) { + sprintf(fileName[fileCount], "%s/", dp->d_name); + dirList[fileCount] = TRUE; + ++fileCount; + } else { + if (MatchesGlob(dp->d_name, globString)) { + strcpy(fileName[fileCount], dp->d_name); + dirList[fileCount] = FALSE; + ++fileCount; + } + } + } } SortFiles(fileCount, fileName, dirList, permute); - for ( index = 0; index < fileCount; index++ ) - { - sprintf(command, "AddBrowseFile %s", fileName[permute[index]]); - Tcl_Eval(interp, command, 0, (char **) NULL); + for (index = 0; index < fileCount; ++index) { + sprintf(command, "AddBrowseFile %s", fileName[permute[index]]); + Tcl_Eval(interp, command, 0, (char **) NULL); } closedir(dfd); @@ -214,108 +193,110 @@ int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, } -void SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN], - boolean *dirList, int permute[]) -{ - register int i, j; - int temp; - int numDirs; - int ptr; - for ( i = 0; i < numStrings; i++ ) - permute[i] = i; +void +SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN], + boolean *dirList, int permute[]) { + + int i; + int numDirs; + int ptr; + + for (i = 0; i < numStrings; ++i) + permute[i] = i; /* put all directories at front */ numDirs = 0; ptr = numStrings-1; - while ( numDirs != ptr ) - { - /* go past dirs */ - while ( (numDirs < ptr) && (dirList[permute[numDirs]]) ) - numDirs++; - - /* go past non-dirs */ - while ( (numDirs < ptr) && (! dirList[permute[ptr]]) ) - ptr--; - - if ( numDirs != ptr ) - { - temp = permute[numDirs]; - permute[numDirs] = ptr; - permute[ptr] = temp; - } + while (numDirs != ptr) { + /* go past dirs */ + while ((numDirs < ptr) && (dirList[permute[numDirs]])) + ++numDirs; + + /* go past non-dirs */ + while ((numDirs < ptr) && (! dirList[permute[ptr]])) + --ptr; + + if (numDirs != ptr) { + int const temp = permute[numDirs]; + permute[numDirs] = ptr; + permute[ptr] = temp; + } } - if ( dirList[permute[numDirs]] ) - numDirs++; - - for ( i = 0; i < numDirs; i++ ) - for ( j = i+1; j < numDirs; j++ ) - { - if ( strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0 ) - { - temp = permute[j]; - permute[j] = permute[i]; - permute[i] = temp; - } - } - - for ( i = numDirs; i < numStrings; i++ ) - for ( j = i+1; j < numStrings; j++ ) - { - if ( strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0 ) - { - temp = permute[j]; - permute[j] = permute[i]; - permute[i] = temp; - } - } + if (dirList[permute[numDirs]]) + ++numDirs; + + for (i = 0; i < numDirs; ++i) { + int j; + for (j = i + 1; j < numDirs; ++j) { + if (strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0) { + int const temp = permute[j]; + permute[j] = permute[i]; + permute[i] = temp; + } + } + } + for (i = numDirs; i < numStrings; ++i) { + int j; + for (j = i + 1; j < numStrings; ++j) { + if (strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0) { + int const temp = permute[j]; + permute[j] = permute[i]; + permute[i] = temp; + } + } + } } -int SetBrowseGlob (ClientData nulldata, Tcl_Interp *interp, - int argc, char **argv) -{ - if (argc == 2 ) - { - strcpy(globString, argv[1]); - fprintf(stdout, "GLOB: %s\n", globString); +int +SetBrowseGlob(ClientData nulldata, Tcl_Interp *interp, + int argc, char **argv) { + + if (argc == 2) { + strcpy(globString, argv[1]); + + fprintf(stdout, "GLOB: %s\n", globString); - return TCL_OK; + return TCL_OK; } - Tcl_AppendResult (interp, - "wrong args: should be \"", argv[0]," string\"", (char *) NULL); - return TCL_ERROR; + Tcl_AppendResult(interp, + "wrong args: should be \"", argv[0]," string\"", + NULL); + return TCL_ERROR; } -static boolean MatchesGlob(char *string, char *glob) -{ - char *stringRight, *globRight; - while ( (*glob != '\0') && (*glob != '*') ) /* match left side */ - { - if ( (*string == '\0') || (*string != *glob) ) - return FALSE; - string++; - glob++; +static boolean +MatchesGlob(char *string, char *glob) { + + char * stringRight; + char * globRight; + + while ((*glob != '\0') && (*glob != '*')) { + /* match left side */ + if ((*string == '\0') || (*string != *glob)) + return FALSE; + ++string; + ++glob; } - if ( *glob == '\0' ) /* no star */ - return TRUE; + if (*glob == '\0') /* no star */ + return TRUE; /* now match right side */ stringRight = &string[strlen(string)-1]; globRight = &glob[strlen(glob)-1]; - while ( *globRight != '*' ) - { - if ( (stringRight < string) || (*stringRight != *globRight) ) - return FALSE; - globRight--; - stringRight--; + while (*globRight != '*') { + if ((stringRight < string) || (*stringRight != *globRight)) + return FALSE; + --globRight; + --stringRight; } return TRUE; diff --git a/converter/ppm/ppmtompeg/frames.c b/converter/ppm/ppmtompeg/frames.c new file mode 100644 index 00000000..a0764890 --- /dev/null +++ b/converter/ppm/ppmtompeg/frames.c @@ -0,0 +1,58 @@ +#include "mallocvar.h" +#include "fsize.h" + +#include "frames.h" + + +Block **dct=NULL, **dctr=NULL, **dctb=NULL; +dct_data_type **dct_data; /* used in p/bframe.c */ + + +/*===========================================================================* + * + * AllocDctBlocks + * + * allocate memory for dct blocks + * + * RETURNS: nothing + * + * SIDE EFFECTS: creates dct, dctr, dctb + * + *===========================================================================*/ +void +AllocDctBlocks(void) { + + int dctx, dcty; + int i; + + dctx = Fsize_x / DCTSIZE; + dcty = Fsize_y / DCTSIZE; + + MALLOCARRAY(dct, dcty); + ERRCHK(dct, "malloc"); + for (i = 0; i < dcty; ++i) { + dct[i] = (Block *) malloc(sizeof(Block) * dctx); + ERRCHK(dct[i], "malloc"); + } + + MALLOCARRAY(dct_data, dcty); + ERRCHK(dct_data, "malloc"); + for (i = 0; i < dcty; ++i) { + MALLOCARRAY(dct_data[i], dctx); + ERRCHK(dct[i], "malloc"); + } + + MALLOCARRAY(dctr, dcty/2); + ERRCHK(dctr, "malloc"); + MALLOCARRAY(dctb, dcty/2); + ERRCHK(dctb, "malloc"); + for (i = 0; i < dcty/2; ++i) { + MALLOCARRAY(dctr[i], dctx/2); + ERRCHK(dctr[i], "malloc"); + MALLOCARRAY(dctb[i], dctx/2); + ERRCHK(dctb[i], "malloc"); + } +} + + + diff --git a/converter/ppm/ppmtompeg/gethostname_win32.c b/converter/ppm/ppmtompeg/gethostname_win32.c new file mode 100644 index 00000000..383f4e55 --- /dev/null +++ b/converter/ppm/ppmtompeg/gethostname_win32.c @@ -0,0 +1,404 @@ +/* define this macro for activating debugging version */ +/* #define GETHOSTNAME_LOCAL_DEBUG 1*/ + +#include <windows.h> +#include <tchar.h> +#include <stdarg.h> + +#ifndef GETHOSTNAME_LOCAL_DEBUG +#include "pm.h" +#include "gethostname.h" +#endif + +#define BUFSIZE 80 + +typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); +typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); + +typedef struct { + char str[256]; + int level; +} push_string_t; + +static void +pushString(push_string_t *p, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + p->level += _vsnprintf(p->str + p->level, sizeof(p->str)-p->level, fmt, args); + va_end(args); +} + +#if _WIN32_WINNT < 0x0600 +/* + * Reference available here: + * + * GetProductInfo() Function + * http://msdn2.microsoft.com/en-us/library/ms724358.aspx + */ +#define PRODUCT_BUSINESS 0x00000006 /* Business Edition */ +#define PRODUCT_BUSINESS_N 0x00000010 /* Business Edition */ +#define PRODUCT_CLUSTER_SERVER 0x00000012 /* Cluster Server Edition */ +#define PRODUCT_DATACENTER_SERVER 0x00000008 /* Server Datacenter Edition (full installation) */ +#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C /* Server Datacenter Edition (core installation) */ +#define PRODUCT_ENTERPRISE 0x00000004 /* Enterprise Edition */ +#define PRODUCT_ENTERPRISE_N 0x0000001B /* Enterprise Edition */ +#define PRODUCT_ENTERPRISE_SERVER 0x0000000A /* Server Enterprise Edition (full installation) */ +#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E /* Server Enterprise Edition (core installation) */ +#define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F /* Server Enterprise Edition for Itanium-based Systems */ +#define PRODUCT_HOME_BASIC 0x00000002 /* Home Basic Edition */ +#define PRODUCT_HOME_BASIC_N 0x00000005 /* Home Basic Edition */ +#define PRODUCT_HOME_PREMIUM 0x00000003 /* Home Premium Edition */ +#define PRODUCT_HOME_PREMIUM_N 0x0000001A /* Home Premium Edition */ +#define PRODUCT_HOME_SERVER 0x00000013 /* Home Server Edition */ +#define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018 /* Server for Small Business Edition */ +#define PRODUCT_SMALLBUSINESS_SERVER 0x00000009 /* Small Business Server */ +#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019 /* Small Business Server Premium Edition */ +#define PRODUCT_STANDARD_SERVER 0x00000007 /* Server Standard Edition (full installation) */ +#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D /* Server Standard Edition (core installation) */ +#define PRODUCT_STARTER 0x0000000B /* Starter Edition */ +#define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017 /* Storage Server Enterprise Edition */ +#define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014 /* Storage Server Express Edition */ +#define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015 /* Storage Server Standard Edition */ +#define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016 /* Storage Server Workgroup Edition */ +#define PRODUCT_UNDEFINED 0x00000000 /* An unknown product */ +#define PRODUCT_ULTIMATE 0x00000001 /* Ultimate Edition */ +#define PRODUCT_ULTIMATE_N 0x0000001C /* Ultimate Edition */ +#define PRODUCT_WEB_SERVER 0x00000011 /* Web Server Edition (full installation) */ +#define PRODUCT_WEB_SERVER_CORE 0x0000001D /* Web Server Edition (core installation) */ +#endif + +static BOOL +get_string_version(push_string_t *str) +{ + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + PGPI pGPI; + PGNSI pGNSI; + BOOL bOsVersionInfoEx; + DWORD dwType; + + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + + /* + * Try calling GetVersionEx using the OSVERSIONINFOEX structure. + * If that fails, try using the OSVERSIONINFO structure. + */ + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) ) + { + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) + return FALSE; + } + + /* Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. */ + pGNSI = (PGNSI) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), + "GetNativeSystemInfo"); + if (NULL != pGNSI) + pGNSI(&si); + else + GetSystemInfo(&si); + + switch (osvi.dwPlatformId) + { + /* Test for the Windows NT product family. */ + case VER_PLATFORM_WIN32_NT: + /* Test for the specific product. */ + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + pushString(str, "Windows Vista "); + else + pushString(str, "Windows Server 2008 "); + + pGPI = (PGPI) GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), + "GetProductInfo"); + + pGPI( 6, 0, 0, 0, &dwType); + switch (dwType) + { + case PRODUCT_ULTIMATE: + pushString(str, "Ultimate Edition"); + break; + case PRODUCT_HOME_PREMIUM: + pushString(str, "Home Premium Edition"); + break; + case PRODUCT_HOME_BASIC: + pushString(str, "Home Basic Edition"); + break; + case PRODUCT_ENTERPRISE: + pushString(str, "Enterprise Edition"); + break; + case PRODUCT_BUSINESS: + pushString(str, "Business Edition"); + break; + case PRODUCT_STARTER: + pushString(str, "Starter Edition"); + break; + case PRODUCT_CLUSTER_SERVER: + pushString(str, "Cluster Server Edition"); + break; + case PRODUCT_DATACENTER_SERVER: + pushString(str, "Datacenter Edition"); + break; + case PRODUCT_DATACENTER_SERVER_CORE: + pushString(str, "Datacenter Edition (core installation)"); + break; + case PRODUCT_ENTERPRISE_SERVER: + pushString(str, "Enterprise Edition"); + break; + case PRODUCT_ENTERPRISE_SERVER_CORE: + pushString(str, "Enterprise Edition (core installation)"); + break; + case PRODUCT_ENTERPRISE_SERVER_IA64: + pushString(str, "Enterprise Edition for Itanium-based Systems"); + break; + case PRODUCT_SMALLBUSINESS_SERVER: + pushString(str, "Small Business Server"); + break; + case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: + pushString(str, "Small Business Server Premium Edition"); + break; + case PRODUCT_STANDARD_SERVER: + pushString(str, "Standard Edition"); + break; + case PRODUCT_STANDARD_SERVER_CORE: + pushString(str, "Standard Edition (core installation)"); + break; + case PRODUCT_WEB_SERVER: + pushString(str, "Web Server Edition"); + break; + } + if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) + pushString(str, ", 64-bit"); + else + if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL) + pushString(str, ", 32-bit"); + else + /* space for optional build number */ + pushString(str, " "); + } + else + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) + { + if( GetSystemMetrics(SM_SERVERR2) ) + pushString(str, "Microsoft Windows Server 2003 \"R2\" "); + else + if ( osvi.wSuiteMask==VER_SUITE_STORAGE_SERVER ) + pushString(str, "Windows Storage Server 2003 "); + else + if( osvi.wProductType == VER_NT_WORKSTATION && + si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) + pushString(str, "Microsoft Windows XP Professional x64 Edition "); + else + pushString(str, "Microsoft Windows Server 2003, "); + + /* Test for the server type. */ + if ( osvi.wProductType != VER_NT_WORKSTATION ) + { + switch (si.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_IA64: + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + pushString(str, "Datacenter Edition for Itanium-based Systems "); + else + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + pushString(str, "Enterprise Edition for Itanium-based Systems "); + break; + + case PROCESSOR_ARCHITECTURE_AMD64: + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + pushString(str, "Datacenter x64 Edition "); + else + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + pushString(str, "Enterprise x64 Edition "); + else + pushString(str, "Standard x64 Edition "); + break; + + default: + if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) + pushString(str, "Compute Cluster Edition "); + else + if ( osvi.wSuiteMask & VER_SUITE_DATACENTER) + pushString(str, "Datacenter Edition "); + else + if ( osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + pushString(str, "Enterprise Edition "); + else + if ( osvi.wSuiteMask & VER_SUITE_BLADE) + pushString(str, "Web Edition "); + else + pushString(str, "Standard Edition "); + break; + } + } + } + else + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 ) + { + pushString(str, "Microsoft Windows XP "); + if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) + pushString(str, "Home Edition "); + else + pushString(str, "Professional "); + } + else + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 ) + { + pushString(str, "Microsoft Windows 2000 "); + if (osvi.wProductType == VER_NT_WORKSTATION) + pushString(str, "Professional "); + else + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + pushString(str, "Datacenter Server "); + else + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + pushString(str, "Advanced Server "); + else + pushString(str, "Server "); + } else + if ( osvi.dwMajorVersion <= 4 ) + pushString(str, "Microsoft Windows NT "); + + /* Test for specific product on Windows NT 4.0 SP6 and later. */ + if (bOsVersionInfoEx) + { + /* Test for the workstation type. */ + switch (osvi.wProductType) + { + case VER_NT_WORKSTATION: + if (si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64 && + osvi.dwMajorVersion == 4) + pushString(str, "Workstation 4.0 "); + break; + + case VER_NT_SERVER: + case VER_NT_DOMAIN_CONTROLLER: + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + pushString(str, "Server 4.0, Enterprise Edition "); + else + pushString(str, "Server 4.0 "); + break; + } + } + /* Test for specific product on Windows NT 4.0 SP5 and earlier */ + else + { + HKEY hKey; + TCHAR szProductType[BUFSIZE]; + DWORD dwBufLen=BUFSIZE*sizeof(TCHAR); + LONG lRet; + + lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), + 0, KEY_QUERY_VALUE, &hKey); + if (lRet != ERROR_SUCCESS) + return FALSE; + + lRet = RegQueryValueEx(hKey, TEXT("ProductType"), NULL, NULL, + (LPBYTE) szProductType, &dwBufLen); + RegCloseKey( hKey ); + + if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE*sizeof(TCHAR))) + return FALSE; + + if (lstrcmpi(TEXT("WINNT"), szProductType) == 0) + pushString(str, "Workstation "); + else + if (lstrcmpi(TEXT("LANMANNT"), szProductType) == 0) + pushString(str, "Server "); + else + if (lstrcmpi( TEXT("SERVERNT"), szProductType) == 0) + pushString(str, "Advanced Server "); + else + pushString(str, "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion); + } + + /* Display service pack (if any) and build number. */ + if (osvi.dwMajorVersion == 4 && + lstrcmpi(osvi.szCSDVersion, TEXT("Service Pack 6")) == 0) + { + HKEY hKey; + LONG lRet; + + /* Test for SP6 versus SP6a. */ + lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), + 0, KEY_QUERY_VALUE, &hKey ); + if( lRet == ERROR_SUCCESS ) + pushString(str, "Service Pack 6a (Build %d)\n", osvi.dwBuildNumber & 0xFFFF ); + else + /* Windows NT 4.0 prior to SP6a */ + pushString(str, "%s (Build %d)\n", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); + + RegCloseKey( hKey ); + } + else /* not Windows NT 4.0 */ + pushString(str, "%s (Build %d)\n", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); + + break; + + /* Test for the Windows Me/98/95. */ + case VER_PLATFORM_WIN32_WINDOWS: + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) + { + pushString(str, "Microsoft Windows 95"); + if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B') + pushString(str, " OSR2"); + } + else + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + { + pushString(str, "Microsoft Windows 98"); + if (osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B') + pushString(str, " SE"); + } + else + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + pushString(str, "Microsoft Windows Millennium Edition\n"); + break; + + case VER_PLATFORM_WIN32s: + pushString(str, "Microsoft Win32s\n"); + break; + } + return TRUE; +} + +const char * +GetHostName(void) +{ +/*---------------------------------------------------------------------------- + Return the host name of this system. +-----------------------------------------------------------------------------*/ + push_string_t str; + + ZeroMemory(&str, sizeof(str)); + if (!get_string_version(&str)) { +#ifndef GETHOSTNAME_LOCAL_DEBUG + pm_error("Unable to find out host name."); +#endif + pushString(&str, "unknown"); + } + return (const char *)_strdup(str.str); +} + +#ifdef GETHOSTNAME_LOCAL_DEBUG +int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, + LPSTR lpsCmdLine, int nCmdShow) +{ + char *hostName = (char *)GetHostName(); + + /* compile as ascii only (not UNICODE) */ + MessageBox(NULL, hostName, TEXT("GetHostName"), MB_OK); + free(hostName); + + return 0; +} +#endif diff --git a/converter/ppm/ppmtompeg/headers/bitio.h b/converter/ppm/ppmtompeg/headers/bitio.h index 89e61fbb..a24c21cd 100644 --- a/converter/ppm/ppmtompeg/headers/bitio.h +++ b/converter/ppm/ppmtompeg/headers/bitio.h @@ -60,9 +60,7 @@ #define BIT_IO_INCLUDED -/*==============* - * HEADER FILES * - *==============*/ +#include <stdio.h> #include "general.h" #include "ansi.h" diff --git a/converter/ppm/ppmtompeg/headers/block.h b/converter/ppm/ppmtompeg/headers/block.h index 46050492..22d306a1 100644 --- a/converter/ppm/ppmtompeg/headers/block.h +++ b/converter/ppm/ppmtompeg/headers/block.h @@ -1,3 +1,46 @@ +#ifndef BLOCK_H_INCLUDED + +#include "frame.h" +#include "mtypes.h" + +/* DIFFERENCE FUNCTIONS */ + +int32 +LumBlockMAD(const LumBlock * const currentBlockP, + const LumBlock * const motionBlockP, + int32 const bestSoFar); + +int32 +LumBlockMSE(const LumBlock * const currentBlockP, + const LumBlock * const motionBlockP, + int32 const bestSoFar); + +int32 +LumMotionError(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumAddMotionError(const LumBlock * const currentBlockP, + const LumBlock * const blockSoFarP, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorSubSampled(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int const startY, + int const startX); + void ComputeDiffDCTs(MpegFrame * const current, MpegFrame * const prev, @@ -51,3 +94,4 @@ AddBMotionBlock(Block block, void BlockifyFrame(MpegFrame * const frameP); +#endif diff --git a/converter/ppm/ppmtompeg/headers/byteorder.h b/converter/ppm/ppmtompeg/headers/byteorder.h index 0070252a..e2d8030c 100644 --- a/converter/ppm/ppmtompeg/headers/byteorder.h +++ b/converter/ppm/ppmtompeg/headers/byteorder.h @@ -72,6 +72,8 @@ #else /* let in.h handle it, if possible */ #include <sys/types.h> +#if !defined(WIN32) || defined(__CYGWIN__) #include <netinet/in.h> +#endif #endif /* FORCE_LITTLE_ENDIAN */ #endif /* FORCE_BIG_ENDIAN */ diff --git a/converter/ppm/ppmtompeg/headers/frame.h b/converter/ppm/ppmtompeg/headers/frame.h index 6df3d19f..acd74419 100644 --- a/converter/ppm/ppmtompeg/headers/frame.h +++ b/converter/ppm/ppmtompeg/headers/frame.h @@ -130,18 +130,4 @@ Frame_Resize(MpegFrame * const omf, int const outsize_x, int const outsize_y); - -extern void Frame_Free _ANSI_ARGS_((MpegFrame * const frame)); -extern void Frame_Exit _ANSI_ARGS_((void)); -extern void Frame_AllocPPM _ANSI_ARGS_((MpegFrame * frame)); -extern void Frame_AllocYCC _ANSI_ARGS_((MpegFrame * const mf)); -extern void Frame_AllocDecoded _ANSI_ARGS_((MpegFrame * const frame, - boolean const makeReference)); -extern void Frame_AllocHalf _ANSI_ARGS_((MpegFrame * const frame)); -extern void Frame_AllocBlocks _ANSI_ARGS_((MpegFrame * const mf)); -extern void Frame_Resize _ANSI_ARGS_((MpegFrame * const omf, MpegFrame * const mf, - int const insize_x, int const insize_y, - int const outsize_x, int const outsize_y)); - - -#endif /* FRAME_INCLUDED */ +#endif diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h index 14304c48..f2bcf6ae 100644 --- a/converter/ppm/ppmtompeg/headers/frames.h +++ b/converter/ppm/ppmtompeg/headers/frames.h @@ -16,6 +16,7 @@ #include "ansi.h" #include "mtypes.h" #include "mheaders.h" +#include "iframe.h" #include "frame.h" @@ -86,11 +87,13 @@ typedef struct dct_data_tye_struct { int fmotionX, fmotionY, bmotionX, bmotionY; } dct_data_type; -void EncodeYDC _ANSI_ARGS_((int32 const dc_term, int32 * const pred_term, BitBucket * const bb)); -void -EncodeCDC(int32 const dc_term, - int32 * const pred_term, - BitBucket * const bb); + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern Block **dct, **dctr, **dctb; +extern dct_data_type **dct_data; /*========* @@ -101,63 +104,6 @@ EncodeCDC(int32 const dc_term, #define int_ceil_div(a,b,c) ((b*(c = a/b) < a) ? (c+1) : c) #define int_floor_div(a,b,c) ((b*(c = a/b) > a) ? (c-1) : c) -/* assumes many things: - * block indices are (y,x) - * variables y_dc_pred, cr_dc_pred, and cb_dc_pred - * flat block fb exists - */ -#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) { \ - boolean overflow, overflowChange=FALSE; \ - int overflowValue = 0; \ - do { \ - overflow = Mpost_QuantZigBlock(dct[y][x], fb[0], \ - qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1], \ - qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2], \ - qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3], \ - qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], \ - fb[4], qscale, TRUE)==MPOST_OVERFLOW; \ - overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], \ - fb[5], qscale, TRUE)==MPOST_OVERFLOW; \ - if ((overflow) && (qscale!=31)) { \ - overflowChange = TRUE; overflowValue++; \ - qscale++; \ - } else overflow = FALSE; \ - } while (overflow); \ - Mhead_GenMBHeader(bb, \ - frameType /* pict_code_type */, mbAI /* addr_incr */, \ - qscale /* q_scale */, \ - 0 /* forw_f_code */, 0 /* back_f_code */, \ - 0 /* horiz_forw_r */, 0 /* vert_forw_r */, \ - 0 /* horiz_back_r */, 0 /* vert_back_r */, \ - 0 /* motion_forw */, 0 /* m_horiz_forw */, \ - 0 /* m_vert_forw */, 0 /* motion_back */, \ - 0 /* m_horiz_back */, 0 /* m_vert_back */, \ - 0 /* mb_pattern */, TRUE /* mb_intra */); \ - \ - /* Y blocks */ \ - EncodeYDC(fb[0][0], &y_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[0], bb); \ - EncodeYDC(fb[1][0], &y_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[1], bb); \ - EncodeYDC(fb[2][0], &y_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[2], bb); \ - EncodeYDC(fb[3][0], &y_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[3], bb); \ - \ - /* CB block */ \ - EncodeCDC(fb[4][0], &cb_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[4], bb); \ - \ - /* CR block */ \ - EncodeCDC(fb[5][0], &cr_dc_pred, bb); \ - Mpost_RLEHuffIBlock(fb[5], bb); \ - if (overflowChange) qscale -= overflowValue; \ - } - #define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) { \ x1 = (bx1)*DCTSIZE; \ x2 = (bx2)*DCTSIZE; \ @@ -254,6 +200,9 @@ encodeMotionVector(int const x, *===============================*/ void +AllocDctBlocks(void); + +void ComputeBMotionLumBlock(MpegFrame * const prev, MpegFrame * const next, int const by, @@ -271,8 +220,6 @@ BMotionSearch(const LumBlock * const currentBlockP, motion * const motionP, int const oldMode); -void GenIFrame (BitBucket * const bb, - MpegFrame * const mf); void GenPFrame (BitBucket * const bb, MpegFrame * const current, MpegFrame * const prev); @@ -280,11 +227,6 @@ void GenBFrame (BitBucket * const bb, MpegFrame * const curr, MpegFrame * const prev, MpegFrame * const next); -void AllocDctBlocks _ANSI_ARGS_((void )); - - -float -IFrameTotalTime(void); float PFrameTotalTime(void); @@ -293,11 +235,6 @@ float BFrameTotalTime(void); void -ShowIFrameSummary(unsigned int const inputFrameBits, - unsigned int const totalBits, - FILE * const fpointer); - -void ShowPFrameSummary(unsigned int const inputFrameBits, unsigned int const totalBits, FILE * const fpointer); @@ -307,87 +244,6 @@ ShowBFrameSummary(unsigned int const inputFrameBits, unsigned int const totalBits, FILE * const fpointer); -/* DIFFERENCE FUNCTIONS */ - -int32 -LumBlockMAD(const LumBlock * const currentBlockP, - const LumBlock * const motionBlockP, - int32 const bestSoFar); - -int32 -LumBlockMSE(const LumBlock * const currentBlockP, - const LumBlock * const motionBlockP, - int32 const bestSoFar); - -int32 -LumMotionError(const LumBlock * const currentBlockP, - MpegFrame * const prev, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumAddMotionError(const LumBlock * const currentBlockP, - const LumBlock * const blockSoFarP, - MpegFrame * const prev, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorA(const LumBlock * const currentBlockP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorB(const LumBlock * const currentP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorC(const LumBlock * const currentP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorD(const LumBlock * const currentP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int32 const bestSoFar); - -int32 -LumMotionErrorSubSampled(const LumBlock * const currentBlockP, - MpegFrame * const prevFrame, - int const by, - int const bx, - vector const m, - int const startY, - int const startX); - -void -BlockComputeSNR(MpegFrame * const current, - float * const snr, - float * const psnr); - -int32 -time_elapsed(void); - -void -AllocDctBlocks(void); - /*==================* * GLOBAL VARIABLES * *==================*/ @@ -399,7 +255,7 @@ extern int gopSize; extern int slicesPerFrame; extern int blocksPerSlice; extern int referenceFrame; -extern int specificsOn; +extern boolean specificsOn; extern int quietTime; /* shut up for at least quietTime seconds; * negative means shut up forever */ @@ -413,7 +269,7 @@ extern int fCodeI,fCodeP,fCodeB; extern boolean forceEncodeLast; extern int TIME_RATE; -#endif /* FRAMES_INCLUDED */ +#endif /* diff --git a/converter/ppm/ppmtompeg/headers/iframe.h b/converter/ppm/ppmtompeg/headers/iframe.h new file mode 100644 index 00000000..c4f77c74 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/iframe.h @@ -0,0 +1,118 @@ +#ifndef IFRAME_H_INCLUDED +#define IFRAME_H_INCLUDED + +#include "frame.h" + +void +SetFCode(void); + +void +SetSlicesPerFrame(int const number); + +void +SetBlocksPerSlice(void); + +void +SetIQScale(int const qI); + +int +GetIQScale(void); + +void +GenIFrame(BitBucket * const bb, + MpegFrame * const current); + +void +ResetIFrameStats(void); + +float +IFrameTotalTime(void); + + +void +ShowIFrameSummary(unsigned int const inputFrameBits, + unsigned int const totalBits, + FILE * const fpointer); + +void +EncodeYDC(int32 const dc_term, + int32 * const pred_term, + BitBucket * const bb); + +void +EncodeCDC(int32 const dc_term, + int32 * const pred_term, + BitBucket * const bb); + +void +BlockComputeSNR(MpegFrame * const current, + float * const snr, + float * const psnr); + +void +WriteDecodedFrame(MpegFrame * const frame); + +void +PrintItoIBitRate(int const numBits, + int const frameNum); + +int32 time_elapsed(void); + +/* assumes many things: + * block indices are (y,x) + * variables y_dc_pred, cr_dc_pred, and cb_dc_pred + * flat block fb exists + */ +#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) { \ + boolean overflow, overflowChange=FALSE; \ + int overflowValue = 0; \ + do { \ + overflow = Mpost_QuantZigBlock(dct[y][x], fb[0], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], \ + fb[4], qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], \ + fb[5], qscale, TRUE)==MPOST_OVERFLOW; \ + if ((overflow) && (qscale!=31)) { \ + overflowChange = TRUE; overflowValue++; \ + qscale++; \ + } else overflow = FALSE; \ + } while (overflow); \ + Mhead_GenMBHeader(bb, \ + frameType /* pict_code_type */, mbAI /* addr_incr */, \ + qscale /* q_scale */, \ + 0 /* forw_f_code */, 0 /* back_f_code */, \ + 0 /* horiz_forw_r */, 0 /* vert_forw_r */, \ + 0 /* horiz_back_r */, 0 /* vert_back_r */, \ + 0 /* motion_forw */, 0 /* m_horiz_forw */, \ + 0 /* m_vert_forw */, 0 /* motion_back */, \ + 0 /* m_horiz_back */, 0 /* m_vert_back */, \ + 0 /* mb_pattern */, TRUE /* mb_intra */); \ + \ + /* Y blocks */ \ + EncodeYDC(fb[0][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[0], bb); \ + EncodeYDC(fb[1][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[1], bb); \ + EncodeYDC(fb[2][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[2], bb); \ + EncodeYDC(fb[3][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[3], bb); \ + \ + /* CB block */ \ + EncodeCDC(fb[4][0], &cb_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[4], bb); \ + \ + /* CR block */ \ + EncodeCDC(fb[5][0], &cr_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[5], bb); \ + if (overflowChange) qscale -= overflowValue; \ + } + +#endif diff --git a/converter/ppm/ppmtompeg/headers/motion_search.h b/converter/ppm/ppmtompeg/headers/motion_search.h index ab83cbca..62f3abab 100644 --- a/converter/ppm/ppmtompeg/headers/motion_search.h +++ b/converter/ppm/ppmtompeg/headers/motion_search.h @@ -100,6 +100,9 @@ PMotionSearch(const LumBlock * const currentBlockP, int const bx, vector * const motionP); +void +MotionSearchPreComputation(MpegFrame * const frameP); + /*==================* * GLOBAL VARIABLES * *==================*/ diff --git a/converter/ppm/ppmtompeg/headers/mpeg.h b/converter/ppm/ppmtompeg/headers/mpeg.h index 23875c2c..56862c42 100644 --- a/converter/ppm/ppmtompeg/headers/mpeg.h +++ b/converter/ppm/ppmtompeg/headers/mpeg.h @@ -90,8 +90,9 @@ void ReadDecodedRefFrame(MpegFrame * const frameP, unsigned int const frameNumber); -extern void WriteDecodedFrame _ANSI_ARGS_((MpegFrame * const frame)); -extern void SetBitRateFileName _ANSI_ARGS_((char *fileName)); +void +SetBitRateFileName(const char * const fileName); + extern void SetFrameRate _ANSI_ARGS_((void)); diff --git a/converter/ppm/ppmtompeg/headers/mproto.h b/converter/ppm/ppmtompeg/headers/mproto.h index c3b0f4b3..d8fefd84 100644 --- a/converter/ppm/ppmtompeg/headers/mproto.h +++ b/converter/ppm/ppmtompeg/headers/mproto.h @@ -74,7 +74,6 @@ #include "bitio.h" -#define DCTSIZE2 DCTSIZE*DCTSIZE typedef short DCTELEM; typedef DCTELEM DCTBLOCK[DCTSIZE2]; @@ -111,9 +110,6 @@ void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width, boolean ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer)); void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); -void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); -boolean PMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, - int by, int bx, int *motionY, int *motionX)); void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); void mp_validate_size _ANSI_ARGS_((int *x, int *y)); void AllocYCC _ANSI_ARGS_((MpegFrame * mf)); @@ -126,7 +122,3 @@ void j_rev_dct _ANSI_ARGS_((DCTBLOCK data )); void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos )); void j_rev_dct _ANSI_ARGS_((DCTBLOCK data )); -/* block.c */ -void BlockToData _ANSI_ARGS_((uint8 **data, Block block, int by, int bx)); -void AddMotionBlock _ANSI_ARGS_((Block block, uint8 **prev, int by, int bx, - int my, int mx)); diff --git a/converter/ppm/ppmtompeg/headers/param.h b/converter/ppm/ppmtompeg/headers/param.h index 31be61ee..c7f57b44 100644 --- a/converter/ppm/ppmtompeg/headers/param.h +++ b/converter/ppm/ppmtompeg/headers/param.h @@ -1,30 +1,4 @@ -/*===========================================================================* - * param.h * - * * - * reading the parameter file * - * * - *===========================================================================*/ - -/* - * Copyright (c) 1995 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement is - * hereby granted, provided that the above copyright notice and the following - * two paragraphs appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF - * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ +/* COPYRIGHT information is at end of file */ #include "pm_c_util.h" #include "ansi.h" @@ -35,14 +9,21 @@ * CONSTANTS * *===========*/ -#define MAX_MACHINES 256 +#define MAX_MACHINES 256 #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif -#define ENCODE_FRAMES 0 -#define COMBINE_GOPS 1 -#define COMBINE_FRAMES 2 +typedef enum { + ENCODE_FRAMES, + /* The regular, default function: Input is individual single unencoded + frames. + */ + COMBINE_GOPS, + /* Input is pre-encoded GOPs */ + COMBINE_FRAMES + /* Input is pre-encoded individual frames */ +} majorProgramFunction; struct params { @@ -53,9 +34,9 @@ struct params { void -ReadParamFile(const char * const fileName, - int const function, - struct params * const paramP); +ReadParamFile(const char * const fileName, + majorProgramFunction const function, + struct params * const paramP); /*==================* * GLOBAL VARIABLES * @@ -63,25 +44,47 @@ ReadParamFile(const char * const fileName, /* All this stuff ought to be in a struct param instead */ -extern char outputFileName[256]; -extern int whichGOP; +extern char outputFileName[256]; +extern int whichGOP; extern int numMachines; -extern char machineName[MAX_MACHINES][256]; -extern char userName[MAX_MACHINES][256]; -extern char executable[MAX_MACHINES][1024]; -extern char remoteParamFile[MAX_MACHINES][1024]; -extern boolean remote[MAX_MACHINES]; -extern char currentPath[MAXPATHLEN]; -extern char currentFramePath[MAXPATHLEN]; -extern char currentGOPPath[MAXPATHLEN]; +extern char machineName[MAX_MACHINES][256]; +extern char userName[MAX_MACHINES][256]; +extern char executable[MAX_MACHINES][1024]; +extern char remoteParamFile[MAX_MACHINES][1024]; +extern boolean remote[MAX_MACHINES]; +extern char currentPath[MAXPATHLEN]; +extern char currentFramePath[MAXPATHLEN]; +extern char currentGOPPath[MAXPATHLEN]; extern char inputConversion[1024]; extern char yuvConversion[256]; -extern int yuvWidth, yuvHeight; -extern int realWidth, realHeight; +extern int yuvWidth, yuvHeight; +extern int realWidth, realHeight; extern char ioConversion[1024]; extern char slaveConversion[1024]; -extern FILE *bitRateFile; +extern FILE * bitRateFile; extern boolean showBitRatePerFrame; extern boolean computeMVHist; extern const double VidRateNum[9]; extern boolean keepTempFiles; + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/converter/ppm/ppmtompeg/headers/prototypes.h b/converter/ppm/ppmtompeg/headers/prototypes.h index a284888f..b421af35 100644 --- a/converter/ppm/ppmtompeg/headers/prototypes.h +++ b/converter/ppm/ppmtompeg/headers/prototypes.h @@ -44,33 +44,26 @@ void ResetBFrameStats _ANSI_ARGS_((void)); void ResetPFrameStats _ANSI_ARGS_((void)); void SetSearchRange (int const pixelsP, int const pixelsB); -void ResetIFrameStats _ANSI_ARGS_((void)); void SetPixelSearch(const char * const searchType); -void SetIQScale _ANSI_ARGS_((int const qI)); void SetPQScale _ANSI_ARGS_((int qP)); void SetBQScale _ANSI_ARGS_((int qB)); -float EstimateSecondsPerIFrame _ANSI_ARGS_((void)); float EstimateSecondsPerPFrame _ANSI_ARGS_((void)); float EstimateSecondsPerBFrame _ANSI_ARGS_((void)); void SetGOPSize _ANSI_ARGS_((int size)); void SetStatFileName(const char * const fileName); -void SetSlicesPerFrame _ANSI_ARGS_((int const number)); -void SetBlocksPerSlice _ANSI_ARGS_((void)); void DCTFrame _ANSI_ARGS_((MpegFrame * mf)); void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); -void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame * const frame)); +void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); void mp_validate_size _ANSI_ARGS_((int *x, int *y)); -extern void SetFCode _ANSI_ARGS_((void)); - /* psearch.c */ void ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer)); diff --git a/converter/ppm/ppmtompeg/headers/subsample.h b/converter/ppm/ppmtompeg/headers/subsample.h new file mode 100644 index 00000000..deedf251 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/subsample.h @@ -0,0 +1,39 @@ +#ifndef SUBSAMPLE_H_INCLUDED +#define SUBSAMPLE_H_INCLUDED + +#include "frame.h" +#include "mtypes.h" + +int32 +LumMotionErrorA(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorB(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorC(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorD(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +#endif diff --git a/converter/ppm/ppmtompeg/huff.h b/converter/ppm/ppmtompeg/huff.h deleted file mode 100644 index 4d0b8840..00000000 --- a/converter/ppm/ppmtompeg/huff.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/huff.h,v 1.2 1995/01/19 23:08:28 eyhung Exp $ - */ - -/* - * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! - */ -#define HUFF_MAXRUN 32 -#define HUFF_MAXLEVEL 41 - -extern int huff_maxlevel[]; -extern uint32 *huff_table[]; -extern int *huff_bits[]; diff --git a/converter/ppm/ppmtompeg/iframe.c b/converter/ppm/ppmtompeg/iframe.c index f4d7665a..7552f413 100644 --- a/converter/ppm/ppmtompeg/iframe.c +++ b/converter/ppm/ppmtompeg/iframe.c @@ -11,10 +11,9 @@ * GetIQScale * * ResetIFrameStats * * ShowIFrameSummary * - * EstimateSecondsPerIFrame * * EncodeYDC * * EncodeCDC * - * time_elapsed * + * time_elapsed * * * *===========================================================================*/ @@ -43,11 +42,11 @@ * HEADER FILES * *==============*/ +#include <time.h> /* Defines CLOCKS_PER_SEC, if this system has clock() */ -#ifdef CLOCKS_PER_SEC -#include <times.h> -#else -#include <sys/times.h> +#ifndef CLOCKS_PER_SEC + /* System doesn't have clock(); we assume it has times() instead */ + #include <sys/times.h> #endif #include <sys/types.h> @@ -67,12 +66,14 @@ #include "specifics.h" #include "opts.h" +#include "iframe.h" + /*==================* * STATIC VARIABLES * *==================*/ -static int lastNumBits = 0; -static int lastIFrame = 0; +static int lastNumBits = 0; +static int lastIFrame = 0; static int numBlocks = 0; static int numBits; static int numFrames = 0; @@ -128,24 +129,11 @@ int fCodeI, fCodeP, fCodeB; boolean printSNR = FALSE; boolean printMSE = FALSE; boolean decodeRefFrames = FALSE; -Block **dct=NULL, **dctr=NULL, **dctb=NULL; -dct_data_type **dct_data; /* used in p/bframe.c */ int TIME_RATE; -/*=====================* - * EXPORTED PROCEDURES * - *=====================*/ -extern void PrintItoIBitRate _ANSI_ARGS_((int const numBits, int const frameNum)); -/*===============================* - * INTERNAL PROCEDURE prototypes * - *===============================*/ -void AllocDctBlocks(void ); -int SetFCodeHelper (int const sr); -void CalcDistortion (MpegFrame * const current, int const y, int const x); - -int +static int SetFCodeHelper(int const SR) { int range,fCode; @@ -296,6 +284,68 @@ GetIQScale(void) { +static void +CalcDistortion(MpegFrame * const current, + int const y, + int const x) { + + int qscale, distort=0; + Block decblk; + FlatBlock fblk; + int datarate = 0; + + for (qscale = 1; qscale < 32; qscale ++) { + distort = 0; + datarate = 0; + Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y][x], decblk); + + Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y][x+1], decblk); + + Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y+1][x], decblk); + + Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y+1][x+1], decblk); + + Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->cb_blocks[y>>1][x>>1], decblk); + + Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk); + + if (!collect_distortion_detailed) { + fprintf(distortion_fp, "\t%d\n", distort); + } else if (collect_distortion_detailed == 1) { + fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate); + } else { + fprintf(fp_table_rate[qscale-1], "%d\n", datarate); + fprintf(fp_table_dist[qscale-1], "%d\n", distort); + } + } +} + + + /*===========================================================================* * * GenIFrame @@ -618,24 +668,6 @@ ShowIFrameSummary(unsigned int const inputFrameBits, /*===========================================================================* * - * EstimateSecondsPerIFrame - * - * estimates the number of seconds required per I-frame - * - * RETURNS: seconds (floating point value) - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -float -EstimateSecondsPerIFrame() -{ - return (float)totalTime/((float)TIME_RATE*(float)numFrames); -} - - -/*===========================================================================* - * * EncodeYDC * * Encode the DC portion of a DCT of a luminance block @@ -926,53 +958,6 @@ PrintItoIBitRate(int const numBits, -/*===========================================================================* - * - * AllocDctBlocks - * - * allocate memory for dct blocks - * - * RETURNS: nothing - * - * SIDE EFFECTS: creates dct, dctr, dctb - * - *===========================================================================*/ -void -AllocDctBlocks(void) { - int dctx, dcty; - int i; - - dctx = Fsize_x / DCTSIZE; - dcty = Fsize_y / DCTSIZE; - - dct = (Block **) malloc(sizeof(Block *) * dcty); - ERRCHK(dct, "malloc"); - for (i = 0; i < dcty; i++) { - dct[i] = (Block *) malloc(sizeof(Block) * dctx); - ERRCHK(dct[i], "malloc"); - } - - dct_data = (dct_data_type **) malloc(sizeof(dct_data_type *) * dcty); - ERRCHK(dct_data, "malloc"); - for (i = 0; i < dcty; i++) { - dct_data[i] = (dct_data_type *) malloc(sizeof(dct_data_type) * dctx); - ERRCHK(dct[i], "malloc"); - } - - dctr = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); - dctb = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); - ERRCHK(dctr, "malloc"); - ERRCHK(dctb, "malloc"); - for (i = 0; i < (dcty >> 1); i++) { - dctr[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); - dctb[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); - ERRCHK(dctr[i], "malloc"); - ERRCHK(dctb[i], "malloc"); - } -} - - - /*======================================================================* * * time_elapsed @@ -994,69 +979,3 @@ int32 time_elapsed(void) { return timeBuffer.tms_utime + timeBuffer.tms_stime; #endif } - - - -void -CalcDistortion(MpegFrame * const current, - int const y, - int const x) { - - int qscale, distort=0; - Block decblk; - FlatBlock fblk; - int datarate = 0; - - for (qscale = 1; qscale < 32; qscale ++) { - distort = 0; - datarate = 0; - Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->y_blocks[y][x], decblk); - - Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->y_blocks[y][x+1], decblk); - - Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->y_blocks[y+1][x], decblk); - - Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->y_blocks[y+1][x+1], decblk); - - Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->cb_blocks[y>>1][x>>1], decblk); - - Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE); - Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); - if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); - mpeg_jrevdct((int16 *)decblk); - distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk); - - if (!collect_distortion_detailed) { - fprintf(distortion_fp, "\t%d\n", distort); - } else if (collect_distortion_detailed == 1) { - fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate); - } else { - fprintf(fp_table_rate[qscale-1], "%d\n", datarate); - fprintf(fp_table_dist[qscale-1], "%d\n", distort); - } - } -} - - - - diff --git a/converter/ppm/ppmtompeg/jpeg.c b/converter/ppm/ppmtompeg/jpeg.c index b51cf083..a703cf39 100644 --- a/converter/ppm/ppmtompeg/jpeg.c +++ b/converter/ppm/ppmtompeg/jpeg.c @@ -15,6 +15,7 @@ * HEADER FILES * *==============*/ #define _XOPEN_SOURCE /* Make sure stdio.h contains fileno() */ +#include <unistd.h> #include <stdio.h> #include "all.h" /* With the lossless jpeg patch applied to the Jpeg library @@ -52,6 +53,17 @@ extern void jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, #define HEADER_SIZE 607 /*JFIF header size used on output images*/ +static int +minDctVScaledSize(struct jpeg_decompress_struct const cinfo) { + +#if JPEG_LIB_VERSION >= 70 + return cinfo.min_DCT_v_scaled_size; +#else + return cinfo.min_DCT_scaled_size; +#endif +} + + /*=======================================================================* * * @@ -416,11 +428,7 @@ ReadJPEG(MpegFrame * const mf, */ /* set parameters for decompression */ -#ifdef JPEG4 - cinfo.want_raw_output = TRUE; -#else cinfo.raw_data_out = TRUE; -#endif cinfo.out_color_space = JCS_YCbCr; /* calculate image output dimensions */ @@ -466,13 +474,7 @@ ReadJPEG(MpegFrame * const mf, /* Make an 8-row-high sample array that will go away when done with image */ -#ifdef JPEG4 - buffer_height = 8; /* could be 2, 4,8 rows high */ -#elif JPEG_LIB_VERSION >= 70 - buffer_height = cinfo.max_v_samp_factor * cinfo.min_DCT_v_scaled_size; -#else - buffer_height = cinfo.max_v_samp_factor * cinfo.min_DCT_scaled_size; -#endif + buffer_height = cinfo.max_v_samp_factor * minDctVScaledSize(cinfo); for(cp=0,compptr = cinfo.comp_info;cp<cinfo.num_components; cp++,compptr++) { @@ -496,11 +498,7 @@ ReadJPEG(MpegFrame * const mf, while (cinfo.output_scanline < cinfo.output_height) { -#ifdef JPEG4 - (void) jpeg_read_raw_scanlines(&cinfo, scanarray, buffer_height); -#else (void) jpeg_read_raw_data(&cinfo, scanarray, buffer_height); -#endif /* alter subsample ratio's if neccessary */ if ((h_samp[0]==2) && (h_samp[1]==1) && (h_samp[2]==1) && diff --git a/converter/ppm/ppmtompeg/mheaders.c b/converter/ppm/ppmtompeg/mheaders.c index 8a51c089..4cfe49ac 100644 --- a/converter/ppm/ppmtompeg/mheaders.c +++ b/converter/ppm/ppmtompeg/mheaders.c @@ -278,24 +278,350 @@ const double VidRateNum[9]={1.0, 23.976, 24.0, 25.0, 29.97, 30.0, 50.0 ,59.94, 60.0}; -/*===============================* - * INTERNAL PROCEDURE prototypes * - *===============================*/ - -static void GenMBAddrIncr _ANSI_ARGS_((BitBucket *bb, uint32 addr_incr)); -static void GenPictHead _ANSI_ARGS_((BitBucket *bb, uint32 temp_ref, - uint32 code_type, uint32 vbv_delay, - int32 full_pel_forw_flag, uint32 forw_f_code, - int32 full_pel_back_flag, uint32 back_f_code, - uint8 *extra_info, uint32 extra_info_size, - uint8 *ext_data, uint32 ext_data_size, - uint8 *user_data, uint32 user_data_size)); -static void GenMBType _ANSI_ARGS_((BitBucket *bb, uint32 pict_code_type, - uint32 mb_quant, uint32 motion_forw, uint32 motion_back, - uint32 mb_pattern, uint32 mb_intra)); -static void GenMotionCode _ANSI_ARGS_((BitBucket * const bb, int32 const vector)); -static void GenBlockPattern _ANSI_ARGS_((BitBucket *bb, - uint32 mb_pattern)); +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * GenMBType + * + * generate macroblock type with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, + mb_pattern, mb_intra) + BitBucket *bbPtr; + uint32 pict_code_type; + uint32 mb_quant; + uint32 motion_forw; + uint32 motion_back; + uint32 mb_pattern; + uint32 mb_intra; +{ + int code; + + switch (pict_code_type) { + case 1: + if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) { + perror("Illegal parameters for macroblock type."); + exit(-1); + } + if (mb_quant) { + Bitio_Write(bbPtr, 0x1, 2); + } else { + Bitio_Write(bbPtr, 0x1, 1); + } + break; + + case 2: + code = 0; + if (mb_quant) { + code += 16; + } + if (motion_forw) { + code += 8; + } + if (motion_back) { + code += 4; + } + if (mb_pattern) { + code += 2; + } + if (mb_intra) { + code += 1; + } + + switch (code) { + case 1: + Bitio_Write(bbPtr, 0x3, 5); + break; + case 2: + Bitio_Write(bbPtr, 0x1, 2); + break; + case 8: + Bitio_Write(bbPtr, 0x1, 3); + break; + case 10: + Bitio_Write(bbPtr, 0x1, 1); + break; + case 17: + Bitio_Write(bbPtr, 0x1, 6); + break; + case 18: + Bitio_Write(bbPtr, 0x1, 5); + break; + case 26: + Bitio_Write(bbPtr, 0x2, 5); + break; + default: + perror("Illegal parameters for macroblock type."); + exit(-1); + break; + } + break; + + case 3: + code = 0; + if (mb_quant) { + code += 16; + } + if (motion_forw) { + code += 8; + } + if (motion_back) { + code += 4; + } + if (mb_pattern) { + code += 2; + } + if (mb_intra) { + code += 1; + } + + switch (code) { + case 12: + Bitio_Write(bbPtr, 0x2, 2); + break; + case 14: + Bitio_Write(bbPtr, 0x3, 2); + break; + case 4: + Bitio_Write(bbPtr, 0x2, 3); + break; + case 6: + Bitio_Write(bbPtr, 0x3, 3); + break; + case 8: + Bitio_Write(bbPtr, 0x2, 4); + break; + case 10: + Bitio_Write(bbPtr, 0x3, 4); + break; + case 1: + Bitio_Write(bbPtr, 0x3, 5); + break; + case 30: + Bitio_Write(bbPtr, 0x2, 5); + break; + case 26: + Bitio_Write(bbPtr, 0x3, 6); + break; + case 22: + Bitio_Write(bbPtr, 0x2, 6); + break; + case 17: + Bitio_Write(bbPtr, 0x1, 6); + break; + default: + perror("Illegal parameters for macroblock type."); + exit(-1); + break; + } + break; + } +} + + +/*===========================================================================* + * + * GenMotionCode + * + * generate motion vector output with given value + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMotionCode(BitBucket * const bbPtr, + int32 const vector) { + + uint32 code, num; + + if ((vector < -16) || (vector > 16)) { + perror("Motion vector out of range."); + fprintf(stderr, "Motion vector out of range: vector = %d\n", vector); + exit(-1); + } + code = mbMotionVectorTable[vector + 16][0]; + num = mbMotionVectorTable[vector + 16][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenBlockPattern + * + * generate macroblock pattern output + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenBlockPattern(bbPtr, mb_pattern) + BitBucket *bbPtr; + uint32 mb_pattern; +{ + uint32 code, num; + + code = mbPatTable[mb_pattern][0]; + num = mbPatTable[mb_pattern][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenMBAddrIncr + * + * generate macroblock address increment output + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMBAddrIncr(bbPtr, addr_incr) + BitBucket *bbPtr; + uint32 addr_incr; +{ + uint32 code; + uint32 num; + + code = mbAddrIncrTable[addr_incr][0]; + num = mbAddrIncrTable[addr_incr][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenPictHead + * + * generate picture header with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag, + forw_f_code, full_pel_back_flag, back_f_code, extra_info, + extra_info_size, ext_data, ext_data_size, user_data, + user_data_size) + BitBucket *bbPtr; + uint32 temp_ref; + uint32 code_type; + uint32 vbv_delay; + int32 full_pel_forw_flag; + uint32 forw_f_code; + int32 full_pel_back_flag; + uint32 back_f_code; + uint8 *extra_info; + uint32 extra_info_size; + uint8 *ext_data; + uint32 ext_data_size; + uint8 *user_data; + uint32 user_data_size; +{ + /* Write picture start code. */ + Bitio_Write(bbPtr, PICT_START_CODE, 32); + + /* Temp reference. */ + Bitio_Write(bbPtr, temp_ref, 10); + + /* Code_type. */ + if (code_type == 0) + code_type = 1; + + Bitio_Write(bbPtr, code_type, 3); + + /* vbv_delay. */ + vbv_delay = 0xffff; /* see page 36 (section 2.4.3.4) */ + Bitio_Write(bbPtr, vbv_delay, 16); + + if ((code_type == 2) || (code_type == 3)) { + + /* Full pel forw flag. */ + + if (full_pel_forw_flag) + Bitio_Write(bbPtr, 0x01, 1); + else + Bitio_Write(bbPtr, 0x00, 1); + + /* Forw f code. */ + + Bitio_Write(bbPtr, forw_f_code, 3); + } + if (code_type == 3) { + + /* Full pel back flag. */ + + if (full_pel_back_flag) + Bitio_Write(bbPtr, 0x01, 1); + else + Bitio_Write(bbPtr, 0x00, 1); + + /* Back f code. */ + + Bitio_Write(bbPtr, back_f_code, 3); + } + /* Extra bit picture info. */ + + if (extra_info != NULL) { + unsigned int i; + for (i = 0; i < extra_info_size; ++i) { + Bitio_Write(bbPtr, 0x01, 1); + Bitio_Write(bbPtr, extra_info[i], 8); + } + } + Bitio_Write(bbPtr, 0x00, 1); + + /* next start code */ + Bitio_BytePad(bbPtr); + + /* Write ext data if present. */ + + if (ext_data != NULL) { + unsigned int i; + + Bitio_Write(bbPtr, EXT_START_CODE, 32); + + for (i = 0; i < ext_data_size; ++i) + Bitio_Write(bbPtr, ext_data[i], 8); + Bitio_BytePad(bbPtr); + } + /* Write user data if present. */ + if (user_data != NULL) { + unsigned int i; + Bitio_Write(bbPtr, USER_START_CODE, 32); + + for (i = 0; i < user_data_size; ++i) + Bitio_Write(bbPtr, user_data[i], 8); + + Bitio_BytePad(bbPtr); + } +} /*=====================* @@ -767,7 +1093,8 @@ if ( addr_incr != 1 ) } /* Generate mb type code. */ - GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, mb_pattern, mb_intra); + GenMBType(bbPtr, pict_code_type, mb_quant, + motion_forw, motion_back, mb_pattern, mb_intra); /* MB quant. */ if (mb_quant) { @@ -831,353 +1158,6 @@ if ( addr_incr != 1 ) } -/*=====================* - * INTERNAL PROCEDURES * - *=====================*/ - -/*===========================================================================* - * - * GenMBType - * - * generate macroblock type with given attributes - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, - mb_pattern, mb_intra) - BitBucket *bbPtr; - uint32 pict_code_type; - uint32 mb_quant; - uint32 motion_forw; - uint32 motion_back; - uint32 mb_pattern; - uint32 mb_intra; -{ - int code; - - switch (pict_code_type) { - case 1: - if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) { - perror("Illegal parameters for macroblock type."); - exit(-1); - } - if (mb_quant) { - Bitio_Write(bbPtr, 0x1, 2); - } else { - Bitio_Write(bbPtr, 0x1, 1); - } - break; - - case 2: - code = 0; - if (mb_quant) { - code += 16; - } - if (motion_forw) { - code += 8; - } - if (motion_back) { - code += 4; - } - if (mb_pattern) { - code += 2; - } - if (mb_intra) { - code += 1; - } - - switch (code) { - case 1: - Bitio_Write(bbPtr, 0x3, 5); - break; - case 2: - Bitio_Write(bbPtr, 0x1, 2); - break; - case 8: - Bitio_Write(bbPtr, 0x1, 3); - break; - case 10: - Bitio_Write(bbPtr, 0x1, 1); - break; - case 17: - Bitio_Write(bbPtr, 0x1, 6); - break; - case 18: - Bitio_Write(bbPtr, 0x1, 5); - break; - case 26: - Bitio_Write(bbPtr, 0x2, 5); - break; - default: - perror("Illegal parameters for macroblock type."); - exit(-1); - break; - } - break; - - case 3: - code = 0; - if (mb_quant) { - code += 16; - } - if (motion_forw) { - code += 8; - } - if (motion_back) { - code += 4; - } - if (mb_pattern) { - code += 2; - } - if (mb_intra) { - code += 1; - } - - switch (code) { - case 12: - Bitio_Write(bbPtr, 0x2, 2); - break; - case 14: - Bitio_Write(bbPtr, 0x3, 2); - break; - case 4: - Bitio_Write(bbPtr, 0x2, 3); - break; - case 6: - Bitio_Write(bbPtr, 0x3, 3); - break; - case 8: - Bitio_Write(bbPtr, 0x2, 4); - break; - case 10: - Bitio_Write(bbPtr, 0x3, 4); - break; - case 1: - Bitio_Write(bbPtr, 0x3, 5); - break; - case 30: - Bitio_Write(bbPtr, 0x2, 5); - break; - case 26: - Bitio_Write(bbPtr, 0x3, 6); - break; - case 22: - Bitio_Write(bbPtr, 0x2, 6); - break; - case 17: - Bitio_Write(bbPtr, 0x1, 6); - break; - default: - perror("Illegal parameters for macroblock type."); - exit(-1); - break; - } - break; - } -} - - -/*===========================================================================* - * - * GenMotionCode - * - * generate motion vector output with given value - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenMotionCode(BitBucket * const bbPtr, - int32 const vector) { - - uint32 code, num; - - if ((vector < -16) || (vector > 16)) { - perror("Motion vector out of range."); - fprintf(stderr, "Motion vector out of range: vector = %d\n", vector); - exit(-1); - } - code = mbMotionVectorTable[vector + 16][0]; - num = mbMotionVectorTable[vector + 16][1]; - - Bitio_Write(bbPtr, code, num); -} - - -/*===========================================================================* - * - * GenBlockPattern - * - * generate macroblock pattern output - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenBlockPattern(bbPtr, mb_pattern) - BitBucket *bbPtr; - uint32 mb_pattern; -{ - uint32 code, num; - - code = mbPatTable[mb_pattern][0]; - num = mbPatTable[mb_pattern][1]; - - Bitio_Write(bbPtr, code, num); -} - - -/*===========================================================================* - * - * GenMBAddrIncr - * - * generate macroblock address increment output - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenMBAddrIncr(bbPtr, addr_incr) - BitBucket *bbPtr; - uint32 addr_incr; -{ - uint32 code; - uint32 num; - - code = mbAddrIncrTable[addr_incr][0]; - num = mbAddrIncrTable[addr_incr][1]; - - Bitio_Write(bbPtr, code, num); -} - - -/*===========================================================================* - * - * GenPictHead - * - * generate picture header with given attributes - * append result to the specified bitstream - * - * RETURNS: nothing - * - * SIDE EFFECTS: none - * - *===========================================================================*/ -static void -GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag, - forw_f_code, full_pel_back_flag, back_f_code, extra_info, - extra_info_size, ext_data, ext_data_size, user_data, - user_data_size) - BitBucket *bbPtr; - uint32 temp_ref; - uint32 code_type; - uint32 vbv_delay; - int32 full_pel_forw_flag; - uint32 forw_f_code; - int32 full_pel_back_flag; - uint32 back_f_code; - uint8 *extra_info; - uint32 extra_info_size; - uint8 *ext_data; - uint32 ext_data_size; - uint8 *user_data; - uint32 user_data_size; -{ - int i; - - /* Write picture start code. */ - Bitio_Write(bbPtr, PICT_START_CODE, 32); - - /* Temp reference. */ - Bitio_Write(bbPtr, temp_ref, 10); - - /* Code_type. */ - if (code_type == 0) { - code_type = 1; - } - Bitio_Write(bbPtr, code_type, 3); - - /* vbv_delay. */ - vbv_delay = 0xffff; /* see page 36 (section 2.4.3.4) */ - Bitio_Write(bbPtr, vbv_delay, 16); - - if ((code_type == 2) || (code_type == 3)) { - - /* Full pel forw flag. */ - - if (full_pel_forw_flag) { - Bitio_Write(bbPtr, 0x01, 1); - } else { - Bitio_Write(bbPtr, 0x00, 1); - } - - /* Forw f code. */ - - Bitio_Write(bbPtr, forw_f_code, 3); - } - if (code_type == 3) { - - /* Full pel back flag. */ - - if (full_pel_back_flag) { - Bitio_Write(bbPtr, 0x01, 1); - } else { - Bitio_Write(bbPtr, 0x00, 1); - } - - /* Back f code. */ - - Bitio_Write(bbPtr, back_f_code, 3); - } - /* Extra bit picture info. */ - - if (extra_info != NULL) { - for (i = 0; i < extra_info_size; i++) { - Bitio_Write(bbPtr, 0x01, 1); - Bitio_Write(bbPtr, extra_info[i], 8); - } - } - Bitio_Write(bbPtr, 0x00, 1); - - /* next start code */ - Bitio_BytePad(bbPtr); - - /* Write ext data if present. */ - - if (ext_data != NULL) { - Bitio_Write(bbPtr, EXT_START_CODE, 32); - - for (i = 0; i < ext_data_size; i++) { - Bitio_Write(bbPtr, ext_data[i], 8); - } - Bitio_BytePad(bbPtr); - } - /* Write user data if present. */ - if (user_data != NULL) { - Bitio_Write(bbPtr, USER_START_CODE, 32); - - for (i = 0; i < user_data_size; i++) { - Bitio_Write(bbPtr, user_data[i], 8); - } - Bitio_BytePad(bbPtr); - } -} - - #ifdef UNUSED_PROCEDURES /* GenMBEnd only used for `D` pictures. Shouldn't really ever be called. */ diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c index fafbb97a..6557f377 100644 --- a/converter/ppm/ppmtompeg/mpeg.c +++ b/converter/ppm/ppmtompeg/mpeg.c @@ -43,8 +43,8 @@ #endif #include <sys/stat.h> -#include "ppm.h" #include "nstring.h" +#include "nsleep.h" #include "mtypes.h" #include "frames.h" @@ -276,9 +276,8 @@ SetReferenceFrameType(const char * const type) { void -SetBitRateFileName(fileName) - char *fileName; -{ +SetBitRateFileName(const char * const fileName) { + strcpy(bitRateFileName, fileName); } @@ -318,7 +317,7 @@ finishFrameOutput(MpegFrame * const frameP, static void outputIFrame(MpegFrame * const frameP, - BitBucket * const bb, + BitBucket * const bbP, int const realStart, int const realEnd, MpegFrame * const pastRefFrameP, @@ -326,7 +325,7 @@ outputIFrame(MpegFrame * const frameP, /* only start a new GOP with I */ /* don't start GOP if only doing frames */ - if ((!separateFiles) && (currentGOP >= gopSize)) { + if (!separateFiles && currentGOP >= gopSize) { boolean const closed = (totalFramesSent == frameP->id || pastRefFrameP == NULL); @@ -344,7 +343,7 @@ outputIFrame(MpegFrame * const frameP, } Mhead_GenSequenceHeader( - bb, Fsize_x, Fsize_y, + bbP, Fsize_x, Fsize_y, /* pratio */ aspectRatio, /* pict_rate */ frameRate, /* bit_rate */ bit_rate, /* buf_size */ buf_size, /* c_param_flag */ 1, @@ -359,7 +358,7 @@ outputIFrame(MpegFrame * const frameP, closed ? "YES" : "NO", frameP->id); ++num_gop; - Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0, + Mhead_GenGOPHeader(bbP, /* drop_frame_flag */ 0, tc_hrs, tc_min, tc_sec, tc_pict, closed, /* broken_link */ 0, /* ext_data */ NULL, /* ext_data_size */ 0, @@ -368,16 +367,16 @@ outputIFrame(MpegFrame * const frameP, if (pastRefFrameP == NULL) SetGOPStartTime(0); else - SetGOPStartTime(pastRefFrameP->id+1); + SetGOPStartTime(pastRefFrameP->id + 1); } - if ((frameP->id >= realStart) && (frameP->id <= realEnd)) - GenIFrame(bb, frameP); + if (frameP->id >= realStart && frameP->id <= realEnd) + GenIFrame(bbP, frameP); - numI--; + --numI; timeMask &= 0x6; - currentGOP++; + ++currentGOP; IncrementTCTime(); } @@ -393,10 +392,10 @@ outputPFrame(MpegFrame * const frameP, if ((frameP->id >= realStart) && (frameP->id <= realEnd)) GenPFrame(bbP, frameP, pastRefFrameP); - numP--; + --numP; timeMask &= 0x5; - currentGOP++; + ++currentGOP; IncrementTCTime(); } @@ -498,6 +497,9 @@ processBFrames(MpegFrame * const pastRefFrameP, But do only those B frames whose frame numbers are within the range 'realStart' through 'realEnd'. + + Output the frames to the output stream 'wholeStreamBbP'. If NULL, + output each frame to its own individual file instead. -----------------------------------------------------------------------------*/ boolean const separateFiles = (wholeStreamBbP == NULL); unsigned int const firstBFrameNum = pastRefFrameP->id + 1; @@ -551,7 +553,7 @@ processBFrames(MpegFrame * const pastRefFrameP, static void processRefFrame(MpegFrame * const frameP, - BitBucket * const bb_arg, + BitBucket * const wholeStreamBbP, int const realStart, int const realEnd, MpegFrame * const pastRefFrameP, @@ -564,26 +566,28 @@ processRefFrame(MpegFrame * const frameP, But only if its frame number is within the range 'realStart' through 'realEnd'. + + Output the frame to the output stream 'wholeStreamBbP'. If NULL, + output it to its own individual file instead. -----------------------------------------------------------------------------*/ if (frameP->id >= realStart && frameP->id <= realEnd) { - boolean separateFiles; - BitBucket * bb; + bool const separateFiles = (wholeStreamBbP == NULL); - separateFiles = (bb_arg == NULL); + BitBucket * bbP; - if ( separateFiles ) - bb = bitioNew(outputFileName, frameP->id, remoteIO); + if (separateFiles) + bbP = bitioNew(outputFileName, frameP->id, remoteIO); else - bb = bb_arg; + bbP = wholeStreamBbP; /* first, output this reference frame */ switch (frameP->type) { case TYPE_IFRAME: - outputIFrame(frameP, bb, realStart, realEnd, pastRefFrameP, + outputIFrame(frameP, bbP, realStart, realEnd, pastRefFrameP, separateFiles); break; case TYPE_PFRAME: - outputPFrame(frameP, bb, realStart, realEnd, pastRefFrameP); + outputPFrame(frameP, bbP, realStart, realEnd, pastRefFrameP); ShowRemainingTime(childProcess); break; default: @@ -593,7 +597,7 @@ processRefFrame(MpegFrame * const frameP, ++(*framesOutputP); - finishFrameOutput(frameP, bb, separateFiles, referenceFrame, + finishFrameOutput(frameP, bbP, separateFiles, referenceFrame, childProcess, remoteIO); } } @@ -702,7 +706,7 @@ readAndSaveFrame(struct inputSource * const inputSourceP, static void doFirstFrameStuff(enum frameContext const context, const char * const userDataFileName, - BitBucket * const bb, + BitBucket * const bbP, int const fsize_x, int const fsize_y, int const aspectRatio, @@ -713,8 +717,12 @@ doFirstFrameStuff(enum frameContext const context, /*---------------------------------------------------------------------------- Do stuff we have to do after reading the first frame in a sequence of frames requested of GenMPEGStream(). + + *bbP is the output stream to which to write any header stuff we have + to write. If 'context' is such that there is no header stuff to write, + then 'bbP' is irrelevant. -----------------------------------------------------------------------------*/ - *inputFrameBitsP = 24*Fsize_x*Fsize_y; + *inputFrameBitsP = 24 * Fsize_x * Fsize_y; SetBlocksPerSlice(); if (context == CONTEXT_WHOLESTREAM) { @@ -722,7 +730,7 @@ doFirstFrameStuff(enum frameContext const context, char * userData; unsigned int userDataSize; - assert(bb != NULL); + assert(bbP != NULL); DBG_PRINT(("Generating sequence header\n")); if (bitstreamMode == FIXED_RATE) { @@ -770,7 +778,7 @@ doFirstFrameStuff(enum frameContext const context, userDataSize = strlen(userData); strfree(userDataString); } - Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, + Mhead_GenSequenceHeader(bbP, Fsize_x, Fsize_y, /* pratio */ aspectRatio, /* pict_rate */ frameRate, /* bit_rate */ bit_rate, @@ -990,13 +998,21 @@ doAFrame(unsigned int const frameNumber, unsigned int * const framesReadP, unsigned int * const framesOutputP, bool * const firstFrameDoneP, - BitBucket * const bbP, + BitBucket * const wholeStreamBbP, unsigned int * const inputFrameBitsP, bool * const endOfStreamP) { /*---------------------------------------------------------------------------- *endOfStreamP returned means we were unable to do a frame because the input stream has ended. In that case, none of the other outputs are valid. + + Process an input frame. This can involve writing its description + to the output stream, saving it for later use, and/or writing + descriptions of previously saved frames to the output stream + because we now have enough information to do so. + + Output the frames to the output stream 'wholeStreamBbP'. If NULL, + output each frame to its own individual file instead. -----------------------------------------------------------------------------*/ char const frameType = FType_Type(frameNumber); @@ -1026,21 +1042,21 @@ doAFrame(unsigned int const frameNumber, *endOfStreamP = FALSE; if (!*firstFrameDoneP) { - doFirstFrameStuff(context, userDataFileName, - bbP, Fsize_x, Fsize_y, aspectRatio, + doFirstFrameStuff(context, userDataFileName, wholeStreamBbP, + Fsize_x, Fsize_y, aspectRatio, frameRate, qtable, niqtable, inputFrameBitsP); *firstFrameDoneP = TRUE; } - processRefFrame(frameP, bbP, frameStart, frameEnd, + processRefFrame(frameP, wholeStreamBbP, frameStart, frameEnd, pastRefFrameP, childProcess, outputFileName, framesReadP, framesOutputP); if (pastRefFrameP) { processBFrames(pastRefFrameP, frameP, realStart, realEnd, inputSourceP, remoteIO, childProcess, - &IOtime, bbP, outputFileName, + &IOtime, wholeStreamBbP, outputFileName, framesReadP, framesOutputP, ¤tGOP); } if (pastRefFrameP != NULL) @@ -1086,17 +1102,20 @@ GenMPEGStream(struct inputSource * const inputSourceP, we stop where the stream ends if that is before 'frameEnd'. -----------------------------------------------------------------------------*/ - BitBucket * bbP; + BitBucket * streamBbP; + /* The output stream to which we write all the frames. NULL + means the frames are going to individual frame files. + */ unsigned int frameNumber; bool endOfStream; bool firstFrameDone; int numBits; unsigned int firstFrame, lastFrame; - /* Frame numbers of the first and last frames we look at. This - could be more than the the frames we actually encode because - we may need context (i.e. to encode a B frame, we need the subsequent - I or P frame). - */ + /* Frame numbers of the first and last frames we look at. + This could be more than the the frames we actually encode + because we may need context (i.e. to encode a B frame, we + need the subsequent I or P frame). + */ unsigned int framesRead; /* Number of frames we have read; for statistical purposes */ MpegFrame * pastRefFrameP; @@ -1150,10 +1169,10 @@ GenMPEGStream(struct inputSource * const inputSourceP, if (showBitRatePerFrame) OpenBitRateFile(); /* May modify showBitRatePerFrame */ - if (context == CONTEXT_WHOLESTREAM || context == CONTEXT_GOP) - bbP = Bitio_New(ofP); + if (context == CONTEXT_JUSTFRAMES) + streamBbP = NULL; else - bbP = NULL; + streamBbP = Bitio_New(ofP); initTCTime(firstFrame); @@ -1171,7 +1190,7 @@ GenMPEGStream(struct inputSource * const inputSourceP, frameStart, frameEnd, realStart, realEnd, childProcess, outputFileName, pastRefFrameP, &pastRefFrameP, - &framesRead, &framesOutput, &firstFrameDone, bbP, + &framesRead, &framesOutput, &firstFrameDone, streamBbP, inputFrameBitsP, &endOfStream); } @@ -1180,10 +1199,10 @@ GenMPEGStream(struct inputSource * const inputSourceP, /* SEQUENCE END CODE */ if (context == CONTEXT_WHOLESTREAM) - Mhead_GenSequenceEnder(bbP); + Mhead_GenSequenceEnder(streamBbP); - if (context == CONTEXT_WHOLESTREAM) - numBits = bbP->cumulativeBits; + if (streamBbP) + numBits = streamBbP->cumulativeBits; else { /* What should the correct value be? Most likely 1. "numBits" is used below, so we need to make sure it's properly initialized @@ -1192,9 +1211,8 @@ GenMPEGStream(struct inputSource * const inputSourceP, numBits = 1; } - if (context != CONTEXT_JUSTFRAMES) { - Bitio_Flush(bbP); - bbP = NULL; + if (streamBbP) { + Bitio_Flush(streamBbP); fclose(ofP); } handleBitRate(realEnd, numBits, childProcess, showBitRatePerFrame); @@ -1662,7 +1680,7 @@ ReadDecodedRefFrame(MpegFrame * const frameP, } if ((fpointer = fopen(fileName, "rb")) == NULL) { - sleep(1); + sleepN(1000); if ((fpointer = fopen(fileName, "rb")) == NULL) { fprintf(stderr, "Cannot open %s\n", fileName); exit(1); diff --git a/converter/ppm/ppmtompeg/noparallel.c b/converter/ppm/ppmtompeg/noparallel.c index 016e3c44..6e6449a4 100644 --- a/converter/ppm/ppmtompeg/noparallel.c +++ b/converter/ppm/ppmtompeg/noparallel.c @@ -163,7 +163,8 @@ MasterServer(struct inputSource * const inputSourceP, void CombineServer(int const numFrames, const char * const masterHostName, - int const masterPortNum) { + int const masterPortNum, + const char* const outputFileName) { pm_error("This version of Ppmtompeg cannot run combine server because " "it does not have socket capability."); diff --git a/converter/ppm/ppmtompeg/parallel.c b/converter/ppm/ppmtompeg/parallel.c index 021e6d2b..e13bf221 100644 --- a/converter/ppm/ppmtompeg/parallel.c +++ b/converter/ppm/ppmtompeg/parallel.c @@ -41,6 +41,7 @@ #include "mallocvar.h" #include "nstring.h" +#include "nsleep.h" #include "pm.h" @@ -128,7 +129,7 @@ boolean niceProcesses = FALSE; boolean forceIalign = FALSE; int machineNumber = -1; boolean remoteIO = FALSE; -bool separateConversion; +boolean separateConversion; /* The I/O server will convert from the input format to the base format, and the slave will convert from the base format to the YUV internal format. If false, the I/O server assumes the input format is the @@ -630,7 +631,7 @@ static int safe_fork(command) /* fork child process and remember its PID * * *===========================================================================*/ void -SetIOConvert(bool const separate) { +SetIOConvert(boolean const separate) { separateConversion = separate; } @@ -648,8 +649,7 @@ SetIOConvert(bool const separate) { * *===========================================================================*/ void -SetParallelPerfect(val) -boolean val; +SetParallelPerfect(boolean val) { parallelPerfect = val; } @@ -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); - sleep(1); + sleepN(1000); } ++attempts; } diff --git a/converter/ppm/ppmtompeg/param.c b/converter/ppm/ppmtompeg/param.c index 5ea69ab6..bb5bc79a 100644 --- a/converter/ppm/ppmtompeg/param.c +++ b/converter/ppm/ppmtompeg/param.c @@ -671,66 +671,66 @@ processParamLine(char const input[], switch(input[0]) { case 'A': - if (STRNEQ(input, "ASPECT_RATIO", 12)) { + if (strneq(input, "ASPECT_RATIO", 12)) { aspectRatio = GetAspectRatio(SkipSpacesTabs(&input[12])); optionSeen[OPTION_ASPECT_RATIO] = TRUE; } break; case 'B': - if (STRNEQ(input, "BQSCALE", 7)) { + if (strneq(input, "BQSCALE", 7)) { SetBQScale(atoi(SkipSpacesTabs(&input[7]))); optionSeen[OPTION_BQSCALE] = TRUE; - } else if (STRNEQ(input, "BASE_FILE_FORMAT", 16)) { + } else if (strneq(input, "BASE_FILE_FORMAT", 16)) { const char * arg = SkipSpacesTabs(&input[16]); SetFileFormat(arg); - if (STRNEQ(arg, "YUV", 3) || STREQ(arg, "Y")) + if (strneq(arg, "YUV", 3) || streq(arg, "Y")) *yuvUsedP = TRUE; optionSeen[OPTION_BASE_FORMAT] = TRUE; - } else if (STRNEQ(input, "BSEARCH_ALG", 11)) { + } else if (strneq(input, "BSEARCH_ALG", 11)) { SetBSearchAlg(SkipSpacesTabs(&input[11])); optionSeen[OPTION_BSEARCH_ALG] = TRUE; - } else if (STRNEQ(input, "BIT_RATE", 8)) { + } else if (strneq(input, "BIT_RATE", 8)) { setBitRate(SkipSpacesTabs(&input[8])); optionSeen[OPTION_BIT_RATE] = TRUE; - } else if (STRNEQ(input, "BUFFER_SIZE", 11)) { + } else if (strneq(input, "BUFFER_SIZE", 11)) { setBufferSize(SkipSpacesTabs(&input[11])); optionSeen[OPTION_BUFFER_SIZE] = TRUE; } break; case 'C': - if (STRNEQ(input, "CDL_FILE", 8)) { + if (strneq(input, "CDL_FILE", 8)) { strcpy(specificsFile, SkipSpacesTabs(&input[8])); specificsOn = TRUE; optionSeen[OPTION_SPECIFICS] = TRUE; - } else if (STRNEQ(input, "CDL_DEFINES", 11)) { + } else if (strneq(input, "CDL_DEFINES", 11)) { strcpy(specificsDefines, SkipSpacesTabs(&input[11])); optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; } break; case 'F': - if (STRNEQ(input, "FRAME_INPUT_DIR", 15)) { + if (strneq(input, "FRAME_INPUT_DIR", 15)) { const char * const arg = SkipSpacesTabs(&input[15]); - if (STRNCASEEQ(arg, "stdin", 5)) + if (strncaseeq(arg, "stdin", 5)) SetStdinInput(frameInputSourceP); strcpy(currentFramePath, arg); - } else if (STRNEQ(input, "FRAME_INPUT", 11)) { + } else if (strneq(input, "FRAME_INPUT", 11)) { ReadInputFileNames(fpointer, "FRAME_END_INPUT", frameInputSourceP->stdinUsed ? NULL : frameInputSourceP); optionSeen[OPTION_FRAME_INPUT] = TRUE; - } else if (STRNEQ(input, "FORCE_I_ALIGN", 13)) { + } else if (strneq(input, "FORCE_I_ALIGN", 13)) { forceIalign = TRUE; - } else if (STRNEQ(input, "FORCE_ENCODE_LAST_FRAME", 23)) { + } else if (strneq(input, "FORCE_ENCODE_LAST_FRAME", 23)) { /* NO-OP. We used to drop trailing B frames by default and you needed this option to change the last frame to I so you could encode all the frames. Now we just do that all the time. Why wouldn't we? */ - } else if (STRNEQ(input, "FRAME_RATE", 10)) { + } else if (strneq(input, "FRAME_RATE", 10)) { frameRate = GetFrameRate(SkipSpacesTabs(&input[10])); frameRateRounded = (int) VidRateNum[frameRate]; if ((frameRate % 3) == 1) @@ -740,21 +740,21 @@ processParamLine(char const input[], break; case 'G': - if (STRNEQ(input, "GOP_SIZE", 8)) { + if (strneq(input, "GOP_SIZE", 8)) { SetGOPSize(atoi(SkipSpacesTabs(&input[8]))); optionSeen[OPTION_GOP] = TRUE; - } else if (STRNEQ(input, "GOP_INPUT_DIR", 13)) { + } else if (strneq(input, "GOP_INPUT_DIR", 13)) { const char * const arg = SkipSpacesTabs(&input[13]); - if (STRNCASEEQ(arg, "stdin", 5)) + if (strncaseeq(arg, "stdin", 5)) SetStdinInput(gopInputSourceP); strcpy(currentGOPPath, arg); - } else if (STRNEQ(input, "GOP_INPUT", 9)) { + } else if (strneq(input, "GOP_INPUT", 9)) { ReadInputFileNames(fpointer, "GOP_END_INPUT", gopInputSourceP->stdinUsed ? NULL : gopInputSourceP); optionSeen[OPTION_GOP_INPUT] = TRUE; - } else if (STRNEQ(input, "GAMMA", 5)) { + } else if (strneq(input, "GAMMA", 5)) { GammaCorrection = TRUE; sscanf(SkipSpacesTabs(&input[5]), "%f", &GammaValue); optionSeen[OPTION_GAMMA] = TRUE; @@ -762,27 +762,27 @@ processParamLine(char const input[], break; case 'I': - if (STRNEQ(input, "IQSCALE", 7)) { + if (strneq(input, "IQSCALE", 7)) { SetIQScale(atoi(SkipSpacesTabs(&input[7]))); optionSeen[OPTION_IQSCALE] = TRUE; - } else if (STRNEQ(input, "INPUT_DIR", 9)) { + } else if (strneq(input, "INPUT_DIR", 9)) { const char * const arg = SkipSpacesTabs(&input[9]); - if (STRNCASEEQ(arg, "stdin", 5)) + if (strncaseeq(arg, "stdin", 5)) SetStdinInput(inputSourceP); strcpy(currentPath, arg); optionSeen[OPTION_INPUT_DIR] = TRUE; - } else if (STRNEQ(input, "INPUT_CONVERT", 13)) { + } else if (strneq(input, "INPUT_CONVERT", 13)) { strcpy(inputConversion, SkipSpacesTabs(&input[13])); optionSeen[OPTION_INPUT_CONVERT] = TRUE; - } else if (STREQ(input, "INPUT")) { + } else if (streq(input, "INPUT")) { ReadInputFileNames(fpointer, "END_INPUT", inputSourceP->stdinUsed ? NULL : inputSourceP); optionSeen[OPTION_INPUT] = TRUE; - } else if (STRNEQ(input, "IO_SERVER_CONVERT", 17)) { + } else if (strneq(input, "IO_SERVER_CONVERT", 17)) { strcpy(ioConversion, SkipSpacesTabs(&input[17])); optionSeen[OPTION_IO_CONVERT] = TRUE; - } else if (STRNEQ(input, "IQTABLE", 7)) { + } else if (strneq(input, "IQTABLE", 7)) { processIqtable(fpointer); optionSeen[OPTION_IQTABLE] = TRUE; @@ -790,12 +790,12 @@ processParamLine(char const input[], break; case 'K': - if (STRNEQ(input, "KEEP_TEMP_FILES", 15)) + if (strneq(input, "KEEP_TEMP_FILES", 15)) keepTempFiles = TRUE; break; case 'N': - if (STRNEQ(input, "NIQTABLE", 8)) { + if (strneq(input, "NIQTABLE", 8)) { readNiqTable(fpointer); optionSeen[OPTION_NIQTABLE] = TRUE; @@ -803,7 +803,7 @@ processParamLine(char const input[], break; case 'O': - if (STRNEQ(input, "OUTPUT", 6)) { + if (strneq(input, "OUTPUT", 6)) { const char * const arg = SkipSpacesTabs(&input[6]); if ( whichGOP == -1 ) strcpy(outputFileName, arg); @@ -815,45 +815,45 @@ processParamLine(char const input[], break; case 'P': - if (STRNEQ(input, "PATTERN", 7)) { + if (strneq(input, "PATTERN", 7)) { SetFramePattern(SkipSpacesTabs(&input[7])); optionSeen[OPTION_PATTERN] = TRUE; - } else if (STRNEQ(input, "PIXEL", 5)) { + } else if (strneq(input, "PIXEL", 5)) { SetPixelSearch(SkipSpacesTabs(&input[5])); optionSeen[OPTION_PIXEL] = TRUE; - } else if (STRNEQ(input, "PQSCALE", 7)) { + } else if (strneq(input, "PQSCALE", 7)) { SetPQScale(atoi(SkipSpacesTabs(&input[7]))); optionSeen[OPTION_PQSCALE] = TRUE; - } else if (STRNEQ(input, "PSEARCH_ALG", 11)) { + } else if (strneq(input, "PSEARCH_ALG", 11)) { SetPSearchAlg(SkipSpacesTabs(&input[11])); optionSeen[OPTION_PSEARCH_ALG] = TRUE; - } else if (STRNEQ(input, "PARALLEL_TEST_FRAMES", 20)) { + } else if (strneq(input, "PARALLEL_TEST_FRAMES", 20)) { SetParallelPerfect(FALSE); parallelTestFrames = atoi(SkipSpacesTabs(&input[20])); - } else if (STRNEQ(input, "PARALLEL_TIME_CHUNKS", 20)) { + } else if (strneq(input, "PARALLEL_TIME_CHUNKS", 20)) { SetParallelPerfect(FALSE); parallelTimeChunks = atoi(SkipSpacesTabs(&input[20])); - } else if (STRNEQ(input, "PARALLEL_CHUNK_TAPER", 20)) { + } else if (strneq(input, "PARALLEL_CHUNK_TAPER", 20)) { SetParallelPerfect(FALSE); parallelTimeChunks = -1; - } else if (STRNEQ(input, "PARALLEL_PERFECT", 16)) { + } else if (strneq(input, "PARALLEL_PERFECT", 16)) { SetParallelPerfect(TRUE); - } else if (STRNEQ(input, "PARALLEL", 8)) { + } else if (strneq(input, "PARALLEL", 8)) { ReadMachineNames(fpointer); optionSeen[OPTION_PARALLEL] = TRUE; } break; case 'R': - if (STRNEQ(input, "RANGE", 5)) { + if (strneq(input, "RANGE", 5)) { processRanges(SkipSpacesTabs(&input[5])); optionSeen[OPTION_RANGE] = TRUE; - } else if (STRNEQ(input, "REFERENCE_FRAME", 15)) { + } else if (strneq(input, "REFERENCE_FRAME", 15)) { SetReferenceFrameType(SkipSpacesTabs(&input[15])); optionSeen[OPTION_REF_FRAME] = TRUE; - } else if (STRNEQ(input, "RSH", 3)) { + } else if (strneq(input, "RSH", 3)) { SetRemoteShell(SkipSpacesTabs(&input[3])); - } else if (STRNEQ(input, "RESIZE", 6)) { + } else if (strneq(input, "RESIZE", 6)) { const char * const arg = SkipSpacesTabs(&input[6]); sscanf(arg, "%dx%d", &outputWidth, &outputHeight); outputWidth &= ~(DCTSIZE * 2 - 1); @@ -863,22 +863,22 @@ processParamLine(char const input[], break; case 'S': - if (STRNEQ(input, "SLICES_PER_FRAME", 16)) { + if (strneq(input, "SLICES_PER_FRAME", 16)) { SetSlicesPerFrame(atoi(SkipSpacesTabs(&input[16]))); optionSeen[OPTION_SPF] = TRUE; - } else if (STRNEQ(input, "SLAVE_CONVERT", 13)) { + } else if (strneq(input, "SLAVE_CONVERT", 13)) { strcpy(slaveConversion, SkipSpacesTabs(&input[13])); optionSeen[OPTION_SLAVE_CONVERT] = TRUE; - } else if (STRNEQ(input, "SPECIFICS_FILE", 14)) { + } else if (strneq(input, "SPECIFICS_FILE", 14)) { strcpy(specificsFile, SkipSpacesTabs(&input[14])); specificsOn = TRUE; optionSeen[OPTION_SPECIFICS] = TRUE; - } else if (STRNEQ(input, "SPECIFICS_DEFINES", 16)) { + } else if (strneq(input, "SPECIFICS_DEFINES", 16)) { strcpy(specificsDefines, SkipSpacesTabs(&input[17])); optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; - } else if (STRNEQ(input, "SEQUENCE_SIZE", 13)) { + } else if (strneq(input, "SEQUENCE_SIZE", 13)) { mult_seq_headers = atoi(SkipSpacesTabs(&input[13])); - } else if (STRNEQ(input, "SIZE", 4)) { + } else if (strneq(input, "SIZE", 4)) { const char * const arg = SkipSpacesTabs(&input[4]); sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight); realWidth = yuvWidth; @@ -889,42 +889,42 @@ processParamLine(char const input[], break; case 'T': - if (STRNEQ(input, "TUNE", 4)) { + if (strneq(input, "TUNE", 4)) { tuneingOn = TRUE; ParseTuneParam(SkipSpacesTabs(&input[4])); } break; case 'U': - if (STRNEQ(input, "USER_DATA", 9)) { + if (strneq(input, "USER_DATA", 9)) { strcpy(userDataFileName, SkipSpacesTabs(&input[9])); optionSeen[OPTION_USER_DATA] = TRUE; } break; case 'W': - if (STRNEQ(input, "WARN_UNDERFLOW", 14)) + if (strneq(input, "WARN_UNDERFLOW", 14)) paramP->warnUnderflow = TRUE; - if (STRNEQ(input, "WARN_OVERFLOW", 13)) + if (strneq(input, "WARN_OVERFLOW", 13)) paramP->warnOverflow = TRUE; break; case 'Y': - if (STRNEQ(input, "YUV_SIZE", 8)) { + if (strneq(input, "YUV_SIZE", 8)) { const char * const arg = SkipSpacesTabs(&input[8]); sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight); realWidth = yuvWidth; realHeight = yuvHeight; Fsize_Validate(&yuvWidth, &yuvHeight); optionSeen[OPTION_YUV_SIZE] = TRUE; - } else if (STRNEQ(input, "Y_SIZE", 6)) { + } else if (strneq(input, "Y_SIZE", 6)) { const char * const arg = SkipSpacesTabs(&input[6]); sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight); realWidth = yuvWidth; realHeight = yuvHeight; Fsize_Validate(&yuvWidth, &yuvHeight); optionSeen[OPTION_YUV_SIZE] = TRUE; - } else if (STRNEQ(input, "YUV_FORMAT", 10)) { + } else if (strneq(input, "YUV_FORMAT", 10)) { strcpy(yuvConversion, SkipSpacesTabs(&input[10])); optionSeen[OPTION_YUV_FORMAT] = TRUE; } @@ -934,26 +934,21 @@ processParamLine(char const input[], -/*===========================================================================* - * - * ReadParamFile - * - * read the parameter file - * function is ENCODE_FRAMES, COMBINE_GOPS, or COMBINE_FRAMES, and - * will slightly modify the procedure's behavior as to what it - * is looking for in the parameter file - * - * SIDE EFFECTS: sets parameters accordingly, as well as machine info for - * parallel execution and input file names - * - *===========================================================================*/ void -ReadParamFile(const char * const fileName, - int const function, - struct params * const paramP) { +ReadParamFile(const char * const fileName, + majorProgramFunction const function, + struct params * const paramP) { +/*---------------------------------------------------------------------------- + Read the parameter file 'fileName' as *paramP. - FILE *fpointer; - char buffer[256]; + 'function' slightly modifies our behavior as to what it is looking for + in the parameter file. + + As a side effect, set machine info for parallel execution and input + file names +-----------------------------------------------------------------------------*/ + FILE * fpointer; + char buffer[256]; bool yuvUsed; struct inputSource * inputSourceP; /* Contents of INPUT section */ diff --git a/converter/ppm/ppmtompeg/pframe.c b/converter/ppm/ppmtompeg/pframe.c index e72fe5d6..de91e32c 100644 --- a/converter/ppm/ppmtompeg/pframe.c +++ b/converter/ppm/ppmtompeg/pframe.c @@ -60,8 +60,6 @@ static int32 totalTime = 0; static int qscaleP; static float totalSNR = 0.0; static float totalPSNR = 0.0; -extern Block **dct, **dctr, **dctb; -extern dct_data_type **dct_data; /*=====================* * INTERNAL PROCEDURES * diff --git a/converter/ppm/ppmtompeg/ppmtompeg.c b/converter/ppm/ppmtompeg/ppmtompeg.c index 2296e2cb..f53ffea9 100644 --- a/converter/ppm/ppmtompeg/ppmtompeg.c +++ b/converter/ppm/ppmtompeg/ppmtompeg.c @@ -33,7 +33,6 @@ #define _BSD_SOURCE /* Make sure strdup() is in string.h */ #include <assert.h> -#include <sys/utsname.h> #include "all.h" #include "mtypes.h" @@ -98,7 +97,7 @@ void init_fdct _ANSI_ARGS_((void)); struct cmdlineInfo { bool childProcess; - int function; + majorProgramFunction function; const char * masterHostname; int masterPortNumber; unsigned int outputFrames; @@ -130,36 +129,33 @@ parseArgs(int const argc, /* parse the arguments */ idx = 1; - while ( idx < argc-1 ) { - if ( argv[idx][0] != '-' ) + while (idx < argc-1) { + if (argv[idx][0] != '-') pm_error("argument '%s', which must be an option because " "it is not the last argument, " "does not start with '-'", argv[idx]); - if ( strcmp(argv[idx], "-stat") == 0 ) { - if ( idx+1 < argc-1 ) { + if (streq(argv[idx], "-stat")) { + if (idx+1 < argc-1) { SetStatFileName(argv[idx+1]); idx += 2; - } else { + } else pm_error("Invalid -stat option"); - } - } else if ( strcmp(argv[idx], "-gop") == 0 ) { - if ((cmdlineP->function != ENCODE_FRAMES) || - (cmdlineP->specificFrames)) + } else if (streq(argv[idx], "-gop")) { + if (cmdlineP->function != ENCODE_FRAMES || + cmdlineP->specificFrames) pm_error("Invalid -gop option"); - if ( idx+1 < argc-1 ) { + if (idx+1 < argc-1) { whichGOP = atoi(argv[idx+1]); idx += 2; - } else { + } else pm_error("Invalid -gop option"); - } - } else if ( strcmp(argv[idx], "-frames") == 0 ) { - if ( (cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) ) { + } else if (streq(argv[idx], "-frames")) { + if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1) pm_error("invalid -frames option"); - } - if ( idx+2 < argc-1 ) { + if (idx+2 < argc-1) { int const frameStart = atoi(argv[idx+1]); int const frameEnd = atoi(argv[idx+2]); @@ -177,23 +173,23 @@ parseArgs(int const argc, idx += 3; } else pm_error("-frames needs to be followed by two values"); - } else if (strcmp(argv[idx], "-combine_gops") == 0) { - if ((cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) || - (cmdlineP->specificFrames)) { + } else if (streq(argv[idx], "-combine_gops")) { + if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1 || + cmdlineP->specificFrames) { pm_error("Invalid -combine_gops option"); } cmdlineP->function = COMBINE_GOPS; - idx++; - } else if (strcmp(argv[idx], "-combine_frames") == 0) { - if ((cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) || - (cmdlineP->specificFrames)) + ++idx; + } else if (streq(argv[idx], "-combine_frames")) { + if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1 || + cmdlineP->specificFrames) pm_error("Invalid -combine_frames option"); cmdlineP->function = COMBINE_FRAMES; - idx++; - } else if ( strcmp(argv[idx], "-child") == 0 ) { - if ( idx+7 < argc-1 ) { + ++idx; + } else if (streq(argv[idx], "-child")) { + if (idx+7 < argc-1) { int combinePortNumber; /* This used to be important information, when the child notified the combine server. Now the master notifies @@ -215,104 +211,94 @@ parseArgs(int const argc, cmdlineP->childProcess = TRUE; idx += 8; - } else if ( strcmp(argv[idx], "-io_server") == 0 ) { - if ( idx+2 < argc-1 ) { - cmdlineP->masterHostname = argv[idx+1]; + } else if (streq(argv[idx], "-io_server")) { + if (idx+2 < argc-1) { + cmdlineP->masterHostname = argv[idx+1]; cmdlineP->masterPortNumber = atoi(argv[idx+2]); - } else { + } else pm_error("Invalid -io_server option"); - } ioServer = TRUE; idx += 3; - } else if ( strcmp(argv[idx], "-output_server") == 0 ) { - if ( idx+3 < argc-1 ) { - cmdlineP->masterHostname = argv[idx+1]; + } else if (streq(argv[idx], "-output_server")) { + if (idx+3 < argc-1) { + cmdlineP->masterHostname = argv[idx+1]; cmdlineP->masterPortNumber = atoi(argv[idx+2]); - cmdlineP->outputFrames = atoi(argv[idx+3]); - } else { + cmdlineP->outputFrames = atoi(argv[idx+3]); + } else pm_error("-output_server option requires 3 option values. " - "You specified %d", argc-1 - idx); - } + "You specified %u", argc-1 - idx); outputServer = TRUE; idx += 4; - } else if ( strcmp(argv[idx], "-decode_server") == 0 ) { - if ( idx+3 < argc-1 ) { - cmdlineP->masterHostname = argv[idx+1]; + } else if (streq(argv[idx], "-decode_server")) { + if (idx+3 < argc-1) { + cmdlineP->masterHostname = argv[idx+1]; cmdlineP->masterPortNumber = atoi(argv[idx+2]); - cmdlineP->outputFrames = atoi(argv[idx+3]); - } else { + cmdlineP->outputFrames = atoi(argv[idx+3]); + } else pm_error("Invalid -decode_server option"); - } cmdlineP->function = COMBINE_FRAMES; decodeServer = TRUE; idx += 4; - } else if ( strcmp(argv[idx], "-nice") == 0 ) { + } else if (streq(argv[idx], "-nice")) { niceProcesses = TRUE; idx++; - } else if ( strcmp(argv[idx], "-max_machines") == 0 ) { - if ( idx+1 < argc-1 ) { + } else if (streq(argv[idx], "-max_machines")) { + if (idx+1 < argc-1) { cmdlineP->maxMachines = atoi(argv[idx+1]); - } else { + } else pm_error("Invalid -max_machines option"); - } idx += 2; - } else if ( strcmp(argv[idx], "-quiet") == 0 ) { - if ( idx+1 < argc-1 ) { + } else if (streq(argv[idx], "-quiet")) { + if (idx+1 < argc-1) quietTime = atoi(argv[idx+1]); - } else { + else pm_error("Invalid -quiet option"); - } idx += 2; - } else if ( strcmp(argv[idx], "-realquiet") == 0 ) { + } else if (streq(argv[idx], "-realquiet")) { realQuiet = TRUE; - idx++; - } else if (( strcmp(argv[idx], "-float_dct") == 0 ) || - ( strcmp(argv[idx], "-float-dct") == 0 )) { + ++idx; + } else if (streq(argv[idx], "-float_dct") || + streq(argv[idx], "-float-dct")) { pureDCT = TRUE; init_idctref(); init_fdct(); - idx++; - } else if ( strcmp(argv[idx], "-no_frame_summary") == 0 ) { - if ( idx < argc-1 ) { + ++idx; + } else if (streq(argv[idx], "-no_frame_summary")) { + if (idx < argc-1) noFrameSummaryOption = TRUE; - } else { + else pm_error("Invalid -no_frame_summary option"); - } - - idx++; - } else if ( strcmp(argv[idx], "-snr") == 0 ) { + ++idx; + } else if (streq(argv[idx], "-snr")) { printSNR = TRUE; - idx++; - } else if ( strcmp(argv[idx], "-mse") == 0 ) { - printSNR = printMSE = TRUE; - idx++; - } else if ( strcmp(argv[idx], "-debug_sockets") == 0 ) { + ++idx; + } else if (streq(argv[idx], "-mse")) { + printSNR = printMSE = TRUE; + ++idx; + } else if (streq(argv[idx], "-debug_sockets")) { debugSockets = TRUE; - idx++; - } else if ( strcmp(argv[idx], "-debug_machines") == 0 ) { + ++idx; + } else if (streq(argv[idx], "-debug_machines")) { debugMachines = TRUE; - idx++; - } else if ( strcmp(argv[idx], "-bit_rate_info") == 0 ) { - if ( idx+1 < argc-1 ) { + ++idx; + } else if (streq(argv[idx], "-bit_rate_info")) { + if (idx+1 < argc-1) { bitRateInfoOption = TRUE; SetBitRateFileName(argv[idx+1]); idx += 2; - } else { + } else pm_error("Invalid -bit_rate_info option"); - } - } else if ( strcmp(argv[idx], "-mv_histogram") == 0 ) { + } else if (streq(argv[idx], "-mv_histogram")) { computeMVHist = TRUE; - idx++; - } else { + ++idx; + } else pm_error("Unrecognized option: '%s'", argv[idx]); - } } - cmdlineP->paramFileName = argv[argc-1]; } @@ -686,8 +672,8 @@ main(int argc, char **argv) { DecodeServer(cmdline.outputFrames, outputFileName, cmdline.masterHostname, cmdline.masterPortNumber); } else { - if ((!cmdline.specificFrames) && - ((numMachines == 0) || (cmdline.function != ENCODE_FRAMES)) ) { + if (!cmdline.specificFrames && + (numMachines == 0 || cmdline.function != ENCODE_FRAMES) ) { ofP = fopen(outputFileName, "wb"); if (ofP == NULL) pm_error("Could not open output file!"); @@ -695,7 +681,7 @@ main(int argc, char **argv) { ofP = NULL; if (cmdline.function == ENCODE_FRAMES) { - if ((numMachines == 0) || (cmdline.specificFrames)) { + if (numMachines == 0 || cmdline.specificFrames) { encodeFrames(params.inputSourceP, cmdline.childProcess, cmdline.masterHostname, cmdline.masterPortNumber, diff --git a/converter/ppm/ppmtompeg/psearch.c b/converter/ppm/ppmtompeg/psearch.c index aea1a29b..83c62d04 100644 --- a/converter/ppm/ppmtompeg/psearch.c +++ b/converter/ppm/ppmtompeg/psearch.c @@ -16,6 +16,8 @@ #include "prototypes.h" #include "fsize.h" #include "param.h" +#include "subsample.h" +#include "block.h" /*==================* diff --git a/converter/ppm/ppmtompeg/rate.c b/converter/ppm/ppmtompeg/rate.c index 3940956c..1a44cb95 100644 --- a/converter/ppm/ppmtompeg/rate.c +++ b/converter/ppm/ppmtompeg/rate.c @@ -50,7 +50,6 @@ #include <assert.h> #include <sys/types.h> -#include <sys/times.h> #include "ppm.h" #include "nstring.h" diff --git a/converter/ppm/ppmtompeg/specifics.c b/converter/ppm/ppmtompeg/specifics.c index c7bbfb5b..38e8fc43 100644 --- a/converter/ppm/ppmtompeg/specifics.c +++ b/converter/ppm/ppmtompeg/specifics.c @@ -47,12 +47,6 @@ #include <string.h> #include "prototypes.h" -/*====================* - * System Information * - *====================*/ - -#define CPP_LOC "/lib/cpp" - /*==================* * GLOBAL VARIABLES * *==================*/ @@ -153,26 +147,27 @@ static char version = -1; * *================================================================ */ -void Specifics_Init() -{ - char command[1100]; - FILE *specificsFP; - - sprintf(command, "/bin/rm -f %s.cpp", specificsFile); - system(command); - sprintf(command, "%s -P %s %s %s.cpp", - CPP_LOC, specificsDefines, specificsFile, specificsFile); - system(command); - strcat(specificsFile, ".cpp"); - if ((specificsFP = fopen(specificsFile, "r")) == NULL) { - fprintf(stderr, "Error with specifics file, cannot open %s\n", specificsFile); - exit(1); - } - printf("Specifics file: %s\n", specificsFile); - Parse_Specifics_File(specificsFP); - sprintf(command, "/bin/rm -f %s.cpp", specificsFile); - system(command); +void +Specifics_Init() { + char command[1100]; + FILE *specificsFP; + + sprintf(command, "rm -f %s.cpp", specificsFile); + system(command); + sprintf(command, "cpp -P %s %s %s.cpp", + specificsDefines, specificsFile, specificsFile); + system(command); + strcat(specificsFile, ".cpp"); + if ((specificsFP = fopen(specificsFile, "r")) == NULL) { + fprintf(stderr, "Error with specifics file, cannot open %s\n", + specificsFile); + exit(1); + } + printf("Specifics file: %s\n", specificsFile); + Parse_Specifics_File(specificsFP); + sprintf(command, "rm -f %s.cpp", specificsFile); + system(command); } diff --git a/converter/ppm/ppmtompeg/subsample.c b/converter/ppm/ppmtompeg/subsample.c index 5ec71814..69401a1d 100644 --- a/converter/ppm/ppmtompeg/subsample.c +++ b/converter/ppm/ppmtompeg/subsample.c @@ -43,6 +43,7 @@ #include "bitio.h" #include "prototypes.h" +#include "subsample.h" static void diff --git a/converter/ppm/ppmtopcx.c b/converter/ppm/ppmtopcx.c index bdcfc5c7..edc44149 100644 --- a/converter/ppm/ppmtopcx.c +++ b/converter/ppm/ppmtopcx.c @@ -15,6 +15,7 @@ */ #include <assert.h> +#include "pm_c_util.h" #include "ppm.h" #include "shhopt.h" #include "mallocvar.h" diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c index e2428fb6..1b9f2d5c 100644 --- a/converter/ppm/ppmtopict.c +++ b/converter/ppm/ppmtopict.c @@ -282,15 +282,8 @@ int i; (void) putc(i & 0xff, fd); } -#if __STDC__ static void putLong( FILE *fd, long i ) -#else /*__STDC__*/ -static void -putLong(fd, i) -FILE *fd; -long i; -#endif /*__STDC__*/ { (void) putc((int)((i >> 24) & 0xff), fd); (void) putc(((int)(i >> 16) & 0xff), fd); @@ -405,7 +398,7 @@ char *packed; *p++ = counttochar(count); packcols = p - packed; /* how many did we write? */ - if (cols > 250) + if (cols > 200) { putShort(fd, packcols); oc = packcols + 2; @@ -443,7 +436,7 @@ char *packed; bzero(aux, cols); /* aux?? */ #endif /*notdef*/ bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT; - if (bc > 250) + if (bc > 200) { putShort(fd, bc); oc = bc + 2; diff --git a/converter/ppm/ppmtopj.c b/converter/ppm/ppmtopj.c index 5d449f7a..d116773f 100644 --- a/converter/ppm/ppmtopj.c +++ b/converter/ppm/ppmtopj.c @@ -121,7 +121,7 @@ char *argv[]; { ++argn; for (r = 0; rmode[r] != NULL; r++) - if (STREQ(rmode[r], argv[argn])) + if (streq(rmode[r], argv[argn])) break; if (rmode[r] != NULL) render_mode = r; @@ -131,9 +131,9 @@ char *argv[]; else if ( pm_keymatch(argv[argn],"-back",2) && argn + 1 < argc ) { ++argn; - if (STREQ(argv[argn], "dark")) + if (streq(argv[argn], "dark")) back_scale = C_BACK_SCALE_DARK; - else if (STREQ(argv[argn], "lite")) + else if (streq(argv[argn], "lite")) back_scale = C_BACK_SCALE_LIGHT; else pm_usage(usage); diff --git a/converter/ppm/ppmtopjxl.c b/converter/ppm/ppmtopjxl.c index 72d299fd..91cd1a45 100644 --- a/converter/ppm/ppmtopjxl.c +++ b/converter/ppm/ppmtopjxl.c @@ -1,4 +1,4 @@ -/* ppmtopcl.c - convert portable pixmap into PCL language for HP PaintJet and +/* ppmtopcl.c - convert PPM into PCL language for HP PaintJet and * PaintJet XL color printers * AJCD 12/3/91 * @@ -17,8 +17,8 @@ #include <string.h> #include "pm_c_util.h" -#include "ppm.h" #include "nstring.h" +#include "ppm.h" #define MAXCOLORS 1024 @@ -106,318 +106,306 @@ putbits(b, 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; + 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; + inrow[num++] = out; + out = xo; + cnt = xc; } } else { /* flush row */ int i; if (cnt) { - inrow[num++] = out; - out = cnt = 0; + 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; - } - } - 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; - } - } - 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; - } - 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; - } - } else { - if (pack) { - printf("0m"); - pack = 0; - } - } + 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; + } + } + 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; + } + } + 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; + } + 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; + } + } else { + if (pack) { + printf("0m"); + pack = 0; + } + } } printf("%dW", num); for (i = 0; i < num; i++) - putchar(pack ? outrow[i] : inrow[i]); + putchar(pack ? outrow[i] : inrow[i]); num = 0; /* new row */ } } + + int -main(argc, argv) - int argc; - char *argv[]; -{ - FILE *ifd; - register pixel **pixels, *pixrow; - register int row, col, bpp, i; - int rows, cols; - pixval maxval; - int bpr, bpg, bpb; - int render; - int colors, pclindex; - colorhist_vector chv; - colorhash_table cht; +main(int argc, const char * argv[]) { + + FILE * ifP; + pixel ** pixels; + unsigned int row; + unsigned int bpp; + int rows, cols; + pixval maxval; + int bpr, bpg, bpb; + int render; + int colors, pclindex; + colorhist_vector chv; + colorhash_table cht; - ppm_init( &argc, argv ); - - while (argc > 1 && argv[1][0] == '-') { - char *c; - for (i = 0; i < sizeof(options)/sizeof(struct options); i++) { - if (pm_keymatch(argv[1], options[i].name, - MIN(strlen(argv[1]), strlen(options[i].name)))) { - switch (options[i].type) { - case DIM: - if (++argv, --argc == 1) - pm_usage(usage); - for (c = argv[1]; ISDIGIT(*c); c++); - if (c[0] == 'p' && c[1] == 't') /* points */ - *(int *)(options[i].value) = atoi(argv[1])*10; - else if (c[0] == 'd' && c[1] == 'p') /* decipoints */ - *(int *)(options[i].value) = atoi(argv[1]); - else if (c[0] == 'i' && c[1] == 'n') /* inches */ - *(int *)(options[i].value) = atoi(argv[1])*720; - else if (c[0] == 'c' && c[1] == 'm') /* centimetres */ - *(int *)(options[i].value) = atoi(argv[1])*283.46457; - else if (!c[0]) /* dots */ - *(int *)(options[i].value) = atoi(argv[1])*4; - else - pm_error("illegal unit of measure %s", c); - break; - case REAL: - if (++argv, --argc == 1) - pm_usage(usage); - *(double *)(options[i].value) = atof(argv[1]); - break; - case BOOL: - *(int *)(options[i].value) = 1; - break; - } - break; - } - } - if (i >= sizeof(options)/sizeof(struct options)) - pm_usage(usage); - argv++; argc--; - } - if (argc > 2) - pm_usage(usage); - else if (argc == 2) - ifd = pm_openr(argv[1]); - else - ifd = stdin ; - - /* validate arguments */ - if (diffuse+cluster+dither > 1) - pm_error("only one of -diffuse, -dither and -cluster may be used"); - render = diffuse ? 4 : dither ? 3 : cluster ? 7 : 0; - - if (xsize != 0.0 && xscale != 0.0) - pm_error("only one of -xsize and -xscale may be used"); - - if (ysize != 0.0 && yscale != 0.0) - pm_error("only one of -ysize and -yscale may be used"); - - pixels = ppm_readppm( ifd, &cols, &rows, &maxval ); - pm_close( ifd ); - - /* limit checks */ - if (cols > PCL_MAXWIDTH || rows > PCL_MAXHEIGHT) - pm_error("image too large; reduce with ppmscale"); - if (maxval > PCL_MAXVAL) - pm_error("color range too large; reduce with ppmcscale"); - - /* Figure out the colormap. */ - fprintf( stderr, "(Computing colormap..." ); fflush( stderr ); - chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors ); - if ( chv == (colorhist_vector) 0 ) - pm_error("too many colors; reduce with pnmquant"); - fprintf( stderr, " Done. %d colors found.)\n", colors ); - - /* And make a hash table for fast lookup. */ - cht = ppm_colorhisttocolorhash( chv, colors ); - - /* work out color downloading mode */ - pclindex = bitsperpixel(colors); - if (pclindex > 8) /* can't use indexed mode */ - pclindex = 0; - else - switch (pclindex) { /* round up to 1,2,4,8 */ - case 0: /* direct mode (no palette) */ - bpp = bitsperpixel(maxval); /* bits per pixel */ - bpg = bpp; bpb = bpp; - bpp = (bpp*3+7)>>3; /* bytes per pixel now */ - bpr = (bpp<<3)-bpg-bpb; - bpp *= cols; /* bytes per row now */ - break; - case 5: pclindex++; - case 6: pclindex++; - case 3: case 7: pclindex++; - default: - bpp = 8/pclindex; - bpp = (cols+bpp-1)/bpp; /* bytes per row */ - } + pm_proginit(&argc, argv); - if ((inrow = (char *)malloc((unsigned)bpp)) == NULL || - (outrow = (char *)malloc((unsigned)bpp*2)) == NULL || - (runcnt = (signed char *)malloc((unsigned)bpp)) == NULL) - pm_error("can't allocate space for row"); - - /* set up image details */ - if (xscale != 0.0) - xsize = cols * xscale * 4; - if (yscale != 0.0) - ysize = rows * yscale * 4; - -#ifdef DEBUG - fprintf(stderr, "dark =%d\n", dark); - fprintf(stderr, "diffuse =%d\n", diffuse); - fprintf(stderr, "dither =%d\n", dither); - fprintf(stderr, "cluster =%d\n", cluster); - fprintf(stderr, "quality =%d\n", quality); - fprintf(stderr, "xsize =%d\n", xsize); - fprintf(stderr, "ysize =%d\n", ysize); - fprintf(stderr, "xshift =%d\n", xshift); - fprintf(stderr, "yshift =%d\n", yshift); - fprintf(stderr, "xscale =%lf\n", xscale); - fprintf(stderr, "yscale =%lf\n", yscale); - fprintf(stderr, "gamma =%lf\n", gamma_val); - fprintf(stderr, "pclindex =%d\n", pclindex); - fprintf(stderr, "nopack =%d\n", nopack); -#endif + while (argc > 1 && argv[1][0] == '-') { + unsigned int i; + for (i = 0; i < sizeof(options)/sizeof(struct options); i++) { + if (pm_keymatch(argv[1], options[i].name, + MIN(strlen(argv[1]), strlen(options[i].name)))) { + const char * c; + switch (options[i].type) { + case DIM: + if (++argv, --argc == 1) + pm_usage(usage); + for (c = argv[1]; ISDIGIT(*c); c++); + if (c[0] == 'p' && c[1] == 't') /* points */ + *(int *)(options[i].value) = atoi(argv[1])*10; + else if (c[0] == 'd' && c[1] == 'p') /* decipoints */ + *(int *)(options[i].value) = atoi(argv[1]); + else if (c[0] == 'i' && c[1] == 'n') /* inches */ + *(int *)(options[i].value) = atoi(argv[1])*720; + else if (c[0] == 'c' && c[1] == 'm') /* centimetres */ + *(int *)(options[i].value) = atoi(argv[1])*283.46457; + else if (!c[0]) /* dots */ + *(int *)(options[i].value) = atoi(argv[1])*4; + else + pm_error("illegal unit of measure %s", c); + break; + case REAL: + if (++argv, --argc == 1) + pm_usage(usage); + *(double *)(options[i].value) = atof(argv[1]); + break; + case BOOL: + *(int *)(options[i].value) = 1; + break; + } + break; + } + } + if (i >= sizeof(options)/sizeof(struct options)) + pm_usage(usage); + argv++; argc--; + } + if (argc > 2) + pm_usage(usage); + else if (argc == 2) + ifP = pm_openr(argv[1]); + else + ifP = stdin ; + + /* validate arguments */ + if (diffuse+cluster+dither > 1) + pm_error("only one of -diffuse, -dither and -cluster may be used"); + render = diffuse ? 4 : dither ? 3 : cluster ? 7 : 0; + + if (xsize != 0.0 && xscale != 0.0) + pm_error("only one of -xsize and -xscale may be used"); + + if (ysize != 0.0 && yscale != 0.0) + pm_error("only one of -ysize and -yscale may be used"); + + pixels = ppm_readppm(ifP, &cols, &rows, &maxval); + pm_close(ifP); + + /* limit checks */ + if (cols > PCL_MAXWIDTH || rows > PCL_MAXHEIGHT) + pm_error("image too large; reduce with ppmscale"); + if (maxval > PCL_MAXVAL) + pm_error("color range too large; reduce with ppmcscale"); - /* write PCL header */ + /* Figure out the colormap. */ + pm_message("Computing colormap..."); + chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors); + if (!chv) + pm_error("too many colors; reduce with pnmquant"); + pm_message("... Done. %u colors found.", colors); + + /* And make a hash table for fast lookup. */ + cht = ppm_colorhisttocolorhash(chv, colors); + + /* work out color downloading mode */ + pclindex = bitsperpixel(colors); + if (pclindex > 8) /* can't use indexed mode */ + pclindex = 0; + else { + switch (pclindex) { /* round up to 1,2,4,8 */ + case 0: /* direct mode (no palette) */ + bpp = bitsperpixel(maxval); /* bits per pixel */ + bpg = bpp; bpb = bpp; + bpp = (bpp*3+7)>>3; /* bytes per pixel now */ + bpr = (bpp<<3)-bpg-bpb; + bpp *= cols; /* bytes per row now */ + break; + case 5: pclindex++; + case 6: pclindex++; + case 3: case 7: pclindex++; + default: + bpp = 8/pclindex; + bpp = (cols+bpp-1)/bpp; /* bytes per row */ + } + } + inrow = (char *)malloc((unsigned)bpp); + outrow = (char *)malloc((unsigned)bpp*2); + runcnt = (signed char *)malloc((unsigned)bpp); + if (inrow == NULL || outrow == NULL || runcnt == NULL) + pm_error("can't allocate space for row"); + + /* set up image details */ + if (xscale != 0.0) + xsize = cols * xscale * 4; + if (yscale != 0.0) + ysize = rows * yscale * 4; + + /* write PCL header */ #if 0 - printf("\033&l26A"); /* paper size */ + printf("\033&l26A"); /* paper size */ #endif - printf("\033*r%ds%dT", cols, rows); /* source width, height */ - if (xshift != 0 || yshift != 0) - printf("\033&a%+dh%+dV", xshift, yshift); /* xshift, yshift */ - if (quality) - printf("\033*o%dQ", quality); /* print quality */ - printf("\033*t"); - if (xsize == 0 && ysize == 0) - printf("180r"); /* resolution */ - else { /* destination width, height */ - if (xsize != 0) - printf("%dh", xsize); - if (ysize != 0) - printf("%dv", ysize); - } - if (gamma_val != 0) - printf("%.3fi", gamma_val); /* gamma correction */ - if (dark) - printf("%dk", dark); /* scaling algorithms */ - printf("%dJ", render); /* rendering algorithm */ - printf("\033*v18W"); /* configure image data */ - putchar(0); /* relative colors */ - putchar(pclindex ? 1 : 3); /* index/direct pixel mode */ - putchar(pclindex); /* ignored in direct pixel mode */ - if (pclindex) { - putchar(0); - putchar(0); - putchar(0); - } else { - putchar(bpr); /* bits per red */ - putchar(bpg); /* bits per green */ - putchar(bpb); /* bits per blue */ - } - putword(maxval); /* max red reference */ - putword(maxval); /* max green reference */ - putword(maxval); /* max blue reference */ - putword(0); /* min red reference */ - putword(0); /* min green reference */ - putword(0); /* min blue reference */ - if (pclindex) { /* set palette */ - for (i = 0; i < colors; i++) { - int r, g, b; - r = PPM_GETR( chv[i].color ); - g = PPM_GETG( chv[i].color ); - b = PPM_GETB( chv[i].color ); - if (i == 0) - printf("\033*v"); - if (r) - printf("%da", r); - if (g) - printf("%db", g); - if (b) - printf("%dc", b); - if (i == colors-1) - printf("%dI", i); /* assign color index */ - else - printf("%di", i); /* assign color index */ - } - } - ppm_freecolorhist( chv ); - - /* start raster graphics at CAP */ - printf("\033*r%dA", (xsize != 0 || ysize != 0) ? 3 : 1); - - for (row = 0; row < rows; row++) { - if (pclindex) { /* indexed color mode */ - int out, cnt; - out = cnt = 0; - for (col = 0, pixrow=pixels[row]; col < cols; col++, pixrow++) { - putbits(ppm_lookupcolor( cht, pixrow ), pclindex); - } - putbits(0, 0); /* flush row */ - } else { /* direct color mode */ - for (col = 0, pixrow=pixels[row]; col < cols; col++, pixrow++) { - putbits(PPM_GETR( *pixrow ), bpr); - putbits(PPM_GETG( *pixrow ), bpg); - putbits(PPM_GETB( *pixrow ), bpb); /* don't need to flush */ - } - putbits(0, 0); /* flush row */ - } - } - printf("\033*rC"); /* end raster graphics */ - exit(0); + printf("\033*r%ds%dT", cols, rows); /* source width, height */ + if (xshift != 0 || yshift != 0) + printf("\033&a%+dh%+dV", xshift, yshift); /* xshift, yshift */ + if (quality) + printf("\033*o%dQ", quality); /* print quality */ + printf("\033*t"); + if (xsize == 0 && ysize == 0) + printf("180r"); /* resolution */ + else { /* destination width, height */ + if (xsize != 0) + printf("%dh", xsize); + if (ysize != 0) + printf("%dv", ysize); + } + if (gamma_val != 0) + printf("%.3fi", gamma_val); /* gamma correction */ + if (dark) + printf("%dk", dark); /* scaling algorithms */ + printf("%dJ", render); /* rendering algorithm */ + printf("\033*v18W"); /* configure image data */ + putchar(0); /* relative colors */ + putchar(pclindex ? 1 : 3); /* index/direct pixel mode */ + putchar(pclindex); /* ignored in direct pixel mode */ + if (pclindex) { + putchar(0); + putchar(0); + putchar(0); + } else { + putchar(bpr); /* bits per red */ + putchar(bpg); /* bits per green */ + putchar(bpb); /* bits per blue */ + } + putword(maxval); /* max red reference */ + putword(maxval); /* max green reference */ + putword(maxval); /* max blue reference */ + putword(0); /* min red reference */ + putword(0); /* min green reference */ + putword(0); /* min blue reference */ + if (pclindex) { /* set palette */ + unsigned int i; + for (i = 0; i < colors; ++i) { + int const r = PPM_GETR( chv[i].color); + int const g = PPM_GETG( chv[i].color); + int const b = PPM_GETB( chv[i].color); + if (i == 0) + printf("\033*v"); + if (r) + printf("%da", r); + if (g) + printf("%db", g); + if (b) + printf("%dc", b); + if (i == colors-1) + printf("%dI", i); /* assign color index */ + else + printf("%di", i); /* assign color index */ + } + } + ppm_freecolorhist(chv); + + /* start raster graphics at CAP */ + printf("\033*r%dA", (xsize != 0 || ysize != 0) ? 3 : 1); + + for (row = 0; row < rows; row++) { + pixel * const pixrow = pixels[row]; + if (pclindex) { /* indexed color mode */ + unsigned int col; + for (col = 0; col < cols; ++col) + putbits(ppm_lookupcolor(cht, &pixrow[col]), pclindex); + putbits(0, 0); /* flush row */ + } else { /* direct color mode */ + unsigned int col; + for (col = 0; col < cols; ++col) { + putbits(PPM_GETR(pixrow[col]), bpr); + putbits(PPM_GETG(pixrow[col]), bpg); + putbits(PPM_GETB(pixrow[col]), bpb); + /* don't need to flush */ + } + putbits(0, 0); /* flush row */ + } + } + printf("\033*rC"); /* end raster graphics */ + + return 0; } diff --git a/converter/ppm/ppmtoterm.c b/converter/ppm/ppmtoterm.c index 72105705..81df614e 100644 --- a/converter/ppm/ppmtoterm.c +++ b/converter/ppm/ppmtoterm.c @@ -21,6 +21,7 @@ #include <string.h> +#include "pm_c_util.h" #include "ppm.h" #include "shhopt.h" diff --git a/converter/ppm/ppmtowinicon.c b/converter/ppm/ppmtowinicon.c index bcaa0e08..1a8cc3a7 100644 --- a/converter/ppm/ppmtowinicon.c +++ b/converter/ppm/ppmtowinicon.c @@ -13,6 +13,7 @@ #include <math.h> #include <string.h> +#include "pm_c_util.h" #include "winico.h" #include "ppm.h" #include "mallocvar.h" diff --git a/converter/ppm/ppmtoxpm.c b/converter/ppm/ppmtoxpm.c index 853ae711..18ea61a8 100644 --- a/converter/ppm/ppmtoxpm.c +++ b/converter/ppm/ppmtoxpm.c @@ -39,6 +39,8 @@ #include <stdio.h> #include <ctype.h> #include <string.h> + +#include "pm_c_util.h" #include "ppm.h" #include "shhopt.h" #include "nstring.h" @@ -138,7 +140,7 @@ parseCommandLine(int argc, char ** argv, /* If output filename not specified, use input filename as default. */ if (nameSpec) cmdlineP->name = nameOpt; - else if (STREQ(cmdlineP->inputFilename, "-")) + else if (streq(cmdlineP->inputFilename, "-")) cmdlineP->name = "noname"; else { static char name[80+1]; diff --git a/converter/ppm/ppmtoyuvsplit.c b/converter/ppm/ppmtoyuvsplit.c index 2dddebfc..e4ffaa3a 100644 --- a/converter/ppm/ppmtoyuvsplit.c +++ b/converter/ppm/ppmtoyuvsplit.c @@ -4,7 +4,7 @@ ** - basename.V : The Chrominance chunk V at 1/4 ** The subsampled U and V values are made by arithmetic mean. ** -** If CCIR601 is defined, the produced YUV triples are scaled again +** The produced YUV triples are scaled again ** to fit into the smaller range of values for this standard. ** ** by A.Beck @@ -20,12 +20,6 @@ ** implied warranty. */ -/* Wether to create YUV in JFIF(JPEG) or CCIR.601(MPEG) scale */ -#define CCIR601 - -/* Wether to use pm_close() or fake it -- don't ask me why */ -/* #define ORIGINAL */ - /* ALPHA Kludge by Franky */ #ifdef __alpha @@ -38,160 +32,151 @@ #include "ppm.h" int -main(argc, argv) -char **argv; -{ - FILE *ifp,*vf,*uf,*yf; - pixel *pixelrow1,*pixelrow2; - register pixel *pP1,*pP2; - int rows, cols, format, row; - register int col; - pixval maxval; - myLONG u,v,y0,y1,y2,y3,u0,u1,u2,u3,v0,v1,v2,v3; - unsigned char *y1buf,*y2buf,*ubuf,*vbuf; - char ufname[256],vfname[256],yfname[256]; - - - ppm_init(&argc, argv); - - if ((argc>3)||(argc<2)) pm_usage("basename [ppmfile]"); - - if (argc == 3) ifp = pm_openr(argv[2]); - else ifp = stdin; - - strcpy(ufname,argv[1]); - strcpy(vfname,argv[1]); - strcpy(yfname,argv[1]); - - strcat(ufname,".U"); - strcat(vfname,".V"); - strcat(yfname,".Y"); - - uf = fopen(ufname,"wb"); - vf = fopen(vfname,"wb"); - yf = fopen(yfname,"wb"); - - if(!(uf && vf && yf)) { - perror("error opening output files"); - exit(0); - } - ppm_readppminit(ifp, &cols, &rows, &maxval, &format); - - if(cols & 1) fprintf(stderr, - "%s: Warning: odd columns count, exceed ignored\n", - argv[0]); - if(rows & 1) fprintf(stderr, - "%s: Warning: odd rows count, exceed ignored\n", - argv[0]); - - pixelrow1 = ((pixel*) pm_allocrow( cols, sizeof(pixel) )); - pixelrow2 = ((pixel*) pm_allocrow( cols, sizeof(pixel) )); - - y1buf = (unsigned char *) pm_allocrow( cols, 1 ); - y2buf = (unsigned char *) pm_allocrow( cols, 1 ); - ubuf = (unsigned char *) pm_allocrow( cols, 1 ); - vbuf = (unsigned char *) pm_allocrow( cols, 1 ); - - for (row = 0; row < (rows & ~1); row += 2) { - unsigned char *y1ptr,*y2ptr,*uptr,*vptr; - - ppm_readppmrow(ifp, pixelrow1, cols, maxval, format); - ppm_readppmrow(ifp, pixelrow2, cols, maxval, format); - - pP1 = pixelrow1; pP2 = pixelrow2; - y1ptr = y1buf; y2ptr = y2buf; vptr = vbuf; uptr = ubuf; - - for (col = 0 ; col < (cols & ~1); col += 2) { - pixval r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3; - - /* first pixel */ - r0 = PPM_GETR(*pP1); - g0 = PPM_GETG(*pP1); - b0 = PPM_GETB(*pP1); - pP1++; - /* 2nd pixel */ - r1 = PPM_GETR(*pP1); - g1 = PPM_GETG(*pP1); - b1 = PPM_GETB(*pP1); - pP1++; - /* 3rd pixel */ - r2 = PPM_GETR(*pP2); - g2 = PPM_GETG(*pP2); - b2 = PPM_GETB(*pP2); - pP2++; - /* 4th pixel */ - r3 = PPM_GETR(*pP2); - g3 = PPM_GETG(*pP2); - b3 = PPM_GETB(*pP2); - pP2++; - - -/* The JFIF RGB to YUV Matrix for $00010000 = 1.0 - -[Y] [19595 38469 7471][R] -[U] = [-11056 -21712 32768][G] -[V] [32768 -27440 -5328][B] +main(int argc, const char ** argv) { + + FILE * ifP; + FILE *vf, *uf, *yf; + pixel *pixelrow1, *pixelrow2; + int rows, cols; + int format; + unsigned int row; + pixval maxval; + unsigned char *y1buf, *y2buf, *ubuf, *vbuf; + char ufname[256], vfname[256], yfname[256]; + + pm_proginit(&argc, argv); + + if ((argc-1 > 2) || (argc-1 < 1)) + pm_error("Wrong number of arguments: %u. " + "Arguments are basename for output files " + "and optional input file name", argc-1); + + if (argc-1 == 2) + ifP = pm_openr(argv[2]); + else + ifP = stdin; + + strcpy(ufname,argv[1]); + strcpy(vfname,argv[1]); + strcpy(yfname,argv[1]); + + strcat(ufname,".U"); + strcat(vfname,".V"); + strcat(yfname,".Y"); + + uf = pm_openw(ufname); + vf = pm_openw(vfname); + yf = pm_openw(yfname); -*/ + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); - y0 = 19595 * r0 + 38469 * g0 + 7471 * b0; - u0 = -11056 * r0 - 21712 * g0 + 32768 * b0; - v0 = 32768 * r0 - 27440 * g0 - 5328 * b0; + if (cols % 2 == 1) + pm_message("Warning: odd columns count %u, excess ignored", cols); - y1 = 19595 * r1 + 38469 * g1 + 7471 * b1; - u1 = -11056 * r1 - 21712 * g1 + 32768 * b1; - v1 = 32768 * r1 - 27440 * g1 - 5328 * b1; + if (rows % 2 == 1) + pm_message("Warning: odd rows count %u, excess ignored", rows); - y2 = 19595 * r2 + 38469 * g2 + 7471 * b2; - u2 = -11056 * r2 - 21712 * g2 + 32768 * b2; - v2 = 32768 * r2 - 27440 * g2 - 5328 * b2; + pixelrow1 = ((pixel*) pm_allocrow(cols, sizeof(pixel))); + pixelrow2 = ((pixel*) pm_allocrow(cols, sizeof(pixel))); - y3 = 19595 * r3 + 38469 * g3 + 7471 * b3; - u3 = -11056 * r3 - 21712 * g3 + 32768 * b3; - v3 = 32768 * r3 - 27440 * g3 - 5328 * b3; + y1buf = (unsigned char *) pm_allocrow(cols, 1); + y2buf = (unsigned char *) pm_allocrow(cols, 1); + ubuf = (unsigned char *) pm_allocrow(cols, 1); + vbuf = (unsigned char *) pm_allocrow(cols, 1); - /* mean the chroma for subsampling */ + for (row = 0; row < (rows & ~1); row += 2) { + unsigned char *y1ptr, *y2ptr, *uptr, *vptr; + pixel *pP1, *pP2; + unsigned int col; - u = (u0+u1+u2+u3)>>2; - v = (v0+v1+v2+v3)>>2; + ppm_readppmrow(ifP, pixelrow1, cols, maxval, format); + ppm_readppmrow(ifP, pixelrow2, cols, maxval, format); -#ifdef CCIR601 + pP1 = &pixelrow1[0]; pP2 = &pixelrow2[0]; + y1ptr = y1buf; y2ptr = y2buf; vptr = vbuf; uptr = ubuf; - y0 = (y0 * 219)/255 + 1048576; - y1 = (y1 * 219)/255 + 1048576; - y2 = (y2 * 219)/255 + 1048576; - y3 = (y3 * 219)/255 + 1048576; + for (col = 0 ; col < (cols & ~1); col += 2) { + pixval r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3; + myLONG u, v, y0, y1, y2, y3, u0, u1, u2, u3, v0, v1, v2, v3; - u = (u * 224)/255 ; - v = (v * 224)/255 ; -#endif + /* first pixel */ + r0 = PPM_GETR(*pP1); + g0 = PPM_GETG(*pP1); + b0 = PPM_GETB(*pP1); + pP1++; + /* 2nd pixel */ + r1 = PPM_GETR(*pP1); + g1 = PPM_GETG(*pP1); + b1 = PPM_GETB(*pP1); + pP1++; + /* 3rd pixel */ + r2 = PPM_GETR(*pP2); + g2 = PPM_GETG(*pP2); + b2 = PPM_GETB(*pP2); + pP2++; + /* 4th pixel */ + r3 = PPM_GETR(*pP2); + g3 = PPM_GETG(*pP2); + b3 = PPM_GETB(*pP2); + pP2++; - *y1ptr++ = (y0 >> 16) ; - *y1ptr++ = (y1 >> 16) ; - *y2ptr++ = (y2 >> 16) ; - *y2ptr++ = (y3 >> 16) ; + /* The JFIF RGB to YUV Matrix for $00010000 = 1.0 + [Y] [19595 38469 7471][R] + [U] = [-11056 -21712 32768][G] + [V] [32768 -27440 -5328][B] - *uptr++ = (u >> 16)+128 ; - *vptr++ = (v >> 16)+128 ; + */ - } - fwrite(y1buf, (cols & ~1), 1, yf); - fwrite(y2buf, (cols & ~1), 1, yf); - fwrite(ubuf, cols/2, 1, uf); - fwrite(vbuf, cols/2, 1, vf); - } + y0 = 19595 * r0 + 38469 * g0 + 7471 * b0; + u0 = -11056 * r0 - 21712 * g0 + 32768 * b0; + v0 = 32768 * r0 - 27440 * g0 - 5328 * b0; -/* I dunno why pm_close sees an error... get rid of it */ + y1 = 19595 * r1 + 38469 * g1 + 7471 * b1; + u1 = -11056 * r1 - 21712 * g1 + 32768 * b1; + v1 = 32768 * r1 - 27440 * g1 - 5328 * b1; -#ifdef ORIGINAL - pm_close(ifp); -#else - if(ifp != stdin) fclose(ifp); -#endif - fclose(yf); - fclose(uf); - fclose(vf); - exit(0); + y2 = 19595 * r2 + 38469 * g2 + 7471 * b2; + u2 = -11056 * r2 - 21712 * g2 + 32768 * b2; + v2 = 32768 * r2 - 27440 * g2 - 5328 * b2; + + y3 = 19595 * r3 + 38469 * g3 + 7471 * b3; + u3 = -11056 * r3 - 21712 * g3 + 32768 * b3; + v3 = 32768 * r3 - 27440 * g3 - 5328 * b3; + + /* mean the chroma for subsampling */ + + u = (u0+u1+u2+u3)>>2; + v = (v0+v1+v2+v3)>>2; + + y0 = (y0 * 219)/255 + 1048576; + y1 = (y1 * 219)/255 + 1048576; + y2 = (y2 * 219)/255 + 1048576; + y3 = (y3 * 219)/255 + 1048576; + + u = (u * 224)/255 ; + v = (v * 224)/255 ; + + *y1ptr++ = (y0 >> 16) ; + *y1ptr++ = (y1 >> 16) ; + *y2ptr++ = (y2 >> 16) ; + *y2ptr++ = (y3 >> 16) ; + + + *uptr++ = (u >> 16)+128 ; + *vptr++ = (v >> 16)+128 ; + + } + fwrite(y1buf, (cols & ~1), 1, yf); + fwrite(y2buf, (cols & ~1), 1, yf); + fwrite(ubuf, cols/2, 1, uf); + fwrite(vbuf, cols/2, 1, vf); + } + + pm_close(ifP); + fclose(yf); + fclose(uf); + fclose(vf); + return 0; } diff --git a/converter/ppm/rawtoppm.c b/converter/ppm/rawtoppm.c index 8d6c3b2c..44e856da 100644 --- a/converter/ppm/rawtoppm.c +++ b/converter/ppm/rawtoppm.c @@ -13,39 +13,148 @@ #include <math.h> #include "ppm.h" -static void dorowskip ARGS(( FILE* ifp, int rowskip )); +enum order { ORD_RGB, ORD_RBG, ORD_GRB, ORD_GBR, ORD_BRG, ORD_BGR }; + +enum interleave { INT_PIX, INT_ROW }; + +static void +dorowskip(FILE * const ifP, + int const rowskip) { + + unsigned int i; + + for (i = 0; i < rowskip; ++i) { + int const val = getc(ifP); + if (val == EOF) + pm_error("EOF / read error"); + } +} + + + +static void +doRowPixInterleave(pixel * const pixrow, + unsigned int const cols, + FILE * const ifP, + enum order const order, + int const rowskip) { + + unsigned int col; + + for (col = 0; col < cols; ++col) { + int const val1 = getc(ifP); + int const val2 = getc(ifP); + int const val3 = getc(ifP); + + if (val1 == EOF) + pm_error("EOF / read error"); + if (val2 == EOF) + pm_error("EOF / read error"); + if (val3 == EOF) + pm_error("EOF / read error"); + + switch (order) { + case ORD_RGB: + PPM_ASSIGN(pixrow[col], val1, val2, val3); + break; + case ORD_RBG: + PPM_ASSIGN(pixrow[col], val1, val3, val2); + break; + case ORD_GRB: + PPM_ASSIGN(pixrow[col], val2, val1, val3); + break; + case ORD_GBR: + PPM_ASSIGN(pixrow[col], val3, val1, val2); + break; + case ORD_BRG: + PPM_ASSIGN(pixrow[col], val2, val3, val1); + break; + case ORD_BGR: + PPM_ASSIGN(pixrow[col], val3, val2, val1); + break; + } + } + dorowskip(ifP, rowskip); +} + + + +static void +doRowRowInterleave(pixel * const pixrow, + unsigned int const cols, + FILE * const ifP, + enum order const order, + int const rowskip, + pixval * const grow1, + pixval * const grow2, + pixval * const grow3) { + + unsigned int col; + + for (col = 0; col < cols; ++col) { + int const val1 = getc(ifP); + if (val1 == EOF) + pm_error("EOF / read error"); + grow1[col] = val1; + } + dorowskip(ifP, rowskip); + for (col = 0; col < cols; ++col) { + int const val2 = getc(ifP); + if (val2 == EOF) + pm_error( "EOF / read error" ); + grow2[col] = val2; + } + dorowskip(ifP, rowskip); + for (col = 0; col < cols; ++col) { + int const val3 = getc(ifP); + if (val3 == EOF) + pm_error( "EOF / read error" ); + grow3[col] = val3; + } + dorowskip(ifP, rowskip); + + for (col = 0; col < cols; ++col) { + switch (order) { + case ORD_RGB: + PPM_ASSIGN(pixrow[col], grow1[col], grow2[col], grow3[col]); + break; + case ORD_RBG: + PPM_ASSIGN(pixrow[col], grow1[col], grow3[col], grow2[col]); + break; + case ORD_GRB: + PPM_ASSIGN(pixrow[col], grow2[col], grow1[col], grow3[col]); + break; + case ORD_GBR: + PPM_ASSIGN(pixrow[col], grow3[col], grow1[col], grow2[col]); + break; + case ORD_BRG: + PPM_ASSIGN(pixrow[col], grow2[col], grow3[col], grow1[col]); + break; + case ORD_BGR: + PPM_ASSIGN(pixrow[col], grow3[col], grow2[col], grow1[col]); + break; + } + } +} + + int -main( argc, argv ) - int argc; - char* argv[]; - { - FILE* ifp; - pixel* pixrow; - register pixel* pP; +main(int argc, const char * argv[]) { + + pixval const maxval = 255; + + FILE * ifP; + pixel * pixrow; int argn, headerskip, rowskip, rows, cols, row, i; - register int col; - int order; -#define ORD_RGB 1 -#define ORD_RBG 2 -#define ORD_GRB 3 -#define ORD_GBR 4 -#define ORD_BRG 5 -#define ORD_BGR 6 -int interleave; -#define INT_PIX 1 -#define INT_ROW 2 - int val1, val2, val3; - gray* grow1; - gray* grow2; - gray* grow3; - register gray* g1P; - register gray* g2P; - register gray* g3P; + enum order order; + enum interleave interleave; + gray * grow1; + gray * grow2; + gray * grow3; const char* const usage = "[-headerskip N] [-rowskip N] [-rgb|-rbg|-grb|-gbr|-brg|-bgr] [-interpixel|-interrow] <width> <height> [rawfile]"; - - ppm_init( &argc, argv ); + pm_proginit(&argc, argv); argn = 1; headerskip = 0; @@ -54,191 +163,90 @@ int interleave; interleave = INT_PIX; while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) - { - if ( pm_keymatch( argv[argn], "-headerskip", 2 ) ) - { - ++argn; - if ( argn >= argc ) - pm_usage( usage ); - headerskip = atoi( argv[argn] ); - } - else if ( pm_keymatch( argv[argn], "-rowskip", 3 ) ) - { - ++argn; - if ( argn >= argc ) - pm_usage( usage ); - rowskip = atoi( argv[argn] ); - } - else if ( pm_keymatch( argv[argn], "-rgb", 3 ) ) - order = ORD_RGB; - else if ( pm_keymatch( argv[argn], "-rbg", 3 ) ) - order = ORD_RBG; - else if ( pm_keymatch( argv[argn], "-grb", 3 ) ) - order = ORD_GRB; - else if ( pm_keymatch( argv[argn], "-gbr", 3 ) ) - order = ORD_GBR; - else if ( pm_keymatch( argv[argn], "-brg", 3 ) ) - order = ORD_BRG; - else if ( pm_keymatch( argv[argn], "-bgr", 3 ) ) - order = ORD_BGR; - else if ( pm_keymatch( argv[argn], "-interpixel", 7 ) ) - interleave = INT_PIX; - else if ( pm_keymatch( argv[argn], "-interrow", 7 ) ) - interleave = INT_ROW; - else - pm_usage( usage ); - ++argn; - } + { + if ( pm_keymatch( argv[argn], "-headerskip", 2 ) ) + { + ++argn; + if ( argn >= argc ) + pm_usage( usage ); + headerskip = atoi( argv[argn] ); + } + else if ( pm_keymatch( argv[argn], "-rowskip", 3 ) ) + { + ++argn; + if ( argn >= argc ) + pm_usage( usage ); + rowskip = atoi( argv[argn] ); + } + else if ( pm_keymatch( argv[argn], "-rgb", 3 ) ) + order = ORD_RGB; + else if ( pm_keymatch( argv[argn], "-rbg", 3 ) ) + order = ORD_RBG; + else if ( pm_keymatch( argv[argn], "-grb", 3 ) ) + order = ORD_GRB; + else if ( pm_keymatch( argv[argn], "-gbr", 3 ) ) + order = ORD_GBR; + else if ( pm_keymatch( argv[argn], "-brg", 3 ) ) + order = ORD_BRG; + else if ( pm_keymatch( argv[argn], "-bgr", 3 ) ) + order = ORD_BGR; + else if ( pm_keymatch( argv[argn], "-interpixel", 7 ) ) + interleave = INT_PIX; + else if ( pm_keymatch( argv[argn], "-interrow", 7 ) ) + interleave = INT_ROW; + else + pm_usage( usage ); + ++argn; + } if ( argn + 2 > argc ) - pm_usage( usage ); - - cols = atoi( argv[argn++] ); - rows = atoi( argv[argn++] ); - if ( cols <= 0 || rows <= 0 ) - pm_usage( usage ); + pm_usage( usage ); + + cols = pm_parse_width(argv[argn++]); + rows = pm_parse_height(argv[argn++]); if ( argn < argc ) - { - ifp = pm_openr( argv[argn] ); - ++argn; - } + { + ifP = pm_openr( argv[argn] ); + ++argn; + } else - ifp = stdin; + ifP = stdin; if ( argn != argc ) - pm_usage( usage ); - - ppm_writeppminit( stdout, cols, rows, (pixval) 255, 0 ); - pixrow = ppm_allocrow( cols ); - - if ( interleave == INT_ROW ) - { - grow1 = pgm_allocrow( cols ); - grow2 = pgm_allocrow( cols ); - grow3 = pgm_allocrow( cols ); - } - - for ( i = 0; i < headerskip; ++i ) - { - val1 = getc( ifp ); - if ( val1 == EOF ) - pm_error( "EOF / read error" ); - } - - for ( row = 0; row < rows; ++row) - { - switch ( interleave ) - { - case INT_PIX: - for ( col = 0, pP = pixrow; col < cols; ++col, ++pP ) - { - val1 = getc( ifp ); - if ( val1 == EOF ) - pm_error( "EOF / read error" ); - val2 = getc( ifp ); - if ( val2 == EOF ) - pm_error( "EOF / read error" ); - val3 = getc( ifp ); - if ( val3 == EOF ) - pm_error( "EOF / read error" ); - switch ( order ) - { - case ORD_RGB: - PPM_ASSIGN( *pP, val1, val2, val3 ); - break; - case ORD_RBG: - PPM_ASSIGN( *pP, val1, val3, val2 ); - break; - case ORD_GRB: - PPM_ASSIGN( *pP, val2, val1, val3 ); - break; - case ORD_GBR: - PPM_ASSIGN( *pP, val3, val1, val2 ); - break; - case ORD_BRG: - PPM_ASSIGN( *pP, val2, val3, val1 ); - break; - case ORD_BGR: - PPM_ASSIGN( *pP, val3, val2, val1 ); - break; - } - } - dorowskip( ifp, rowskip ); - break; - - case INT_ROW: - for ( col = 0, g1P = grow1; col < cols; ++col, ++g1P ) - { - val1 = getc( ifp ); - if ( val1 == EOF ) - pm_error( "EOF / read error" ); - *g1P = val1; - } - dorowskip( ifp, rowskip ); - for ( col = 0, g2P = grow2; col < cols; ++col, ++g2P ) - { - val2 = getc( ifp ); - if ( val2 == EOF ) - pm_error( "EOF / read error" ); - *g2P = val2; - } - dorowskip( ifp, rowskip ); - for ( col = 0, g3P = grow3; col < cols; ++col, ++g3P ) - { - val3 = getc( ifp ); - if ( val3 == EOF ) - pm_error( "EOF / read error" ); - *g3P = val3; - } - dorowskip( ifp, rowskip ); - for ( col = 0, pP = pixrow, g1P = grow1, g2P = grow2, g3P = grow3; - col < cols; ++col, ++pP, ++g1P, ++g2P, ++g3P ) - { - switch ( order ) - { - case ORD_RGB: - PPM_ASSIGN( *pP, *g1P, *g2P, *g3P ); - break; - case ORD_RBG: - PPM_ASSIGN( *pP, *g1P, *g3P, *g2P ); - break; - case ORD_GRB: - PPM_ASSIGN( *pP, *g2P, *g1P, *g3P ); - break; - case ORD_GBR: - PPM_ASSIGN( *pP, *g3P, *g1P, *g2P ); - break; - case ORD_BRG: - PPM_ASSIGN( *pP, *g2P, *g3P, *g1P ); - break; - case ORD_BGR: - PPM_ASSIGN( *pP, *g3P, *g2P, *g1P ); - break; - } - } - break; - } - ppm_writeppmrow( stdout, pixrow, cols, (pixval) 255, 0 ); - } - - pm_close( ifp ); - pm_close( stdout ); + pm_usage( usage ); - exit( 0 ); + ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0); + pixrow = ppm_allocrow(cols); + + if (interleave == INT_ROW) { + grow1 = pgm_allocrow(cols); + grow2 = pgm_allocrow(cols); + grow3 = pgm_allocrow(cols); } -static void -dorowskip( ifp, rowskip ) - FILE* ifp; - int rowskip; - { - int i, val; - - for ( i = 0; i < rowskip; ++i ) - { - val = getc( ifp ); - if ( val == EOF ) - pm_error( "EOF / read error" ); - } + for (i = 0; i < headerskip; ++i) { + int const val = getc(ifP); + if (val == EOF) + pm_error("EOF / read error"); + } + + for (row = 0; row < rows; ++row) { + switch (interleave) { + case INT_PIX: + doRowPixInterleave(pixrow, cols, ifP, order, rowskip); + break; + + case INT_ROW: + doRowRowInterleave(pixrow, cols, ifP, order, rowskip, + grow1, grow2, grow3); + break; + } + ppm_writeppmrow(stdout, pixrow, cols, maxval, 0); + } + + pm_close( ifP ); + pm_close( stdout ); + + exit( 0 ); } diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c index 6b51f291..ad16a649 100644 --- a/converter/ppm/sldtoppm.c +++ b/converter/ppm/sldtoppm.c @@ -66,15 +66,9 @@ struct svector { struct spoint t; /* To point */ }; -static int extend ARGS((smallint ch)); -static int sli ARGS((void)); -static int slib ARGS((void)); -static void vscale ARGS((int *px, int *py)); -static void slider ARGS((void (*slvec) ARGS((struct svector *vec, int color)), - void (*slflood) ARGS((struct spolygon *poly, int color)) )); -static void slidefind ARGS((char *sname, int dironly, int ucasen)); -static void draw ARGS((struct svector *vec, int color)); -static void flood ARGS((struct spolygon *const poly, int const color)); +typedef void (slvecfn)(struct svector * vec, int color); +typedef void (slfloodfn)(struct spolygon * poly, int color); + static int ixdots, iydots; /* Screen size in dots */ static FILE *slfile; /* Slide file descriptor */ @@ -104,21 +98,26 @@ static int adjust = FALSE; /* Adjust to correct aspect ratio ? */ static struct slhead slfrof; /* Slide file header */ static long xfac, yfac; /* Aspect ratio scale factors */ -static int sdrawkcab; /* Slide drawing kinematic conversion of - ass-backwards data flag */ +static int sdrawkcab; + /* Slide drawing kinematic conversion of ass-backwards data flag */ + + /* EXTEND -- Turn a smallint into an int with sign extension, whether - or not that happens automatically. */ + or not that happens automatically. +*/ -static int extend(smallint ch) -{ +static int +extend(smallint ch) { return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch)); } + + /* SLI -- Input word from slide file */ -static int sli() -{ +static int +sli(void) { short wd; if (fread(&wd, sizeof wd, 1, slfile) != 1) { @@ -131,10 +130,12 @@ static int sli() return wd; } + + /* SLIB -- Input byte from slide file */ -static int slib() -{ +static int +slib(void) { smallint ch = 0; if (fread(&ch, sizeof ch, 1, slfile) != 1) { @@ -143,25 +144,171 @@ static int slib() return extend(ch); } + + /* VSCALE -- scale screen coordinates for mismatched display. */ -static void vscale(px, py) - int *px, *py; -{ +static void +vscale(int * const px, + int * const py) { + *px = (((unsigned) *px) * xfac) >> 16; *py = (((unsigned) *py) * yfac) >> 16; } + + +/* SLIDEFIND -- Find a slide in a library or, if DIRONLY is + nonzero, print a directory listing of the library. + If UCASEN is nonzero, the requested slide name is + converted to upper case. */ + +static void +slidefind(const char * const sname, + bool const dironly, + bool const ucasen) { + + char uname[32]; + unsigned char libent[36]; + long pos; + + if (dironly) + pm_message("Slides in library:"); + else { + int i; + const char * ip; + + ip = sname; /* initial value */ + + for (i = 0; i < 31; i++) { + char ch = *ip++; + if (ch == EOS) + break; + if (ucasen && ISLOWER(ch)) + ch = TOUPPER(ch); + uname[i] = ch; + } + uname[i] = EOS; + } + + /* Read slide library header and verify. */ + + if ((fread(libent, 32, 1, slfile) != 1) || + (!streq((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) { + pm_error("not an AutoCAD slide library file."); + } + pos = 32; + + /* Search for a slide with the requested name. */ + + while (TRUE) { + if ((fread(libent, 36, 1, slfile) != 1) || + (strlen((char *)libent) == 0)) { + if (dironly) { + return; + } + pm_error("slide %s not in library.", sname); + } + pos += 36; + if (dironly) { + pm_message(" %s", libent); + } else if (streq((char *)libent, uname)) { + long dpos = (((((libent[35] << 8) | libent[34]) << 8) | + libent[33]) << 8) | libent[32]; + if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) { + dpos -= pos; + + while (dpos-- > 0) + getc(slfile); + } + break; + } + } +} + + + +/* DRAW -- Draw a vector in the given AutoCAD color. */ + +static slvecfn draw; + +static void +draw(struct svector * vec, + int color) { + + pixel rgbcolor; + + if (blither) { + pm_message("Vector (%d, %d) - (%d, %d) Color %d", + vec->f.x, vec->f.y, vec->t.x, vec->t.y, color); + } + assert(vec->f.x >= 0 && vec->f.x < pixcols); + assert(vec->f.y >= 0 && vec->f.y < pixrows); + assert(vec->t.x >= 0 && vec->t.x < pixcols); + assert(vec->t.y >= 0 && vec->t.y < pixrows); + PPM_ASSIGN(rgbcolor, + acadcol[color][0], acadcol[color][1], acadcol[color][2]); + ppmd_line(pixels, pixcols, pixrows, pixmaxval, + vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y, + PPMD_NULLDRAWPROC, + (char *) &rgbcolor); +} + + + +/* FLOOD -- Draw a filled polygon. */ + +static slfloodfn flood; + +static void +flood(struct spolygon * const poly, + int const color) { + + unsigned int i; + struct fillobj * handle; + pixel rgbcolor; + + handle = ppmd_fill_create(); + + if (blither) { + unsigned int i; + pm_message("Polygon: %d points, fill type %d, color %d", + poly->npoints, poly->fill, color); + for (i = 0; i < poly->npoints; i++) { + pm_message(" Point %d: (%d, %d)", i + 1, + poly->pt[i].x, poly->pt[i].y); + } + } + + PPM_ASSIGN(rgbcolor, + acadcol[color][0], acadcol[color][1], acadcol[color][2]); + for (i = 0; i < poly->npoints; i++) { + assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols); + assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows); + ppmd_line(pixels, pixcols, pixrows, pixmaxval, + poly->pt[i].x, iydots - poly->pt[i].y, + poly->pt[(i + 1) % poly->npoints].x, + iydots - poly->pt[(i + 1) % poly->npoints].y, + ppmd_fill_drawproc, handle); + } + ppmd_fill(pixels, pixcols, pixrows, pixmaxval, + handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor); + + ppmd_fill_destroy(handle); +} + + + /* SLIDER -- Read slide file. This is called with the name of the file to be read and function pointers to the routines which process vectors and polygon fill requests respectively. */ -static void slider(slvec, slflood) - void (*slvec) ARGS((struct svector *vec, int color)); - void (*slflood) ARGS((struct spolygon *poly, int color)); -{ +static void +slider(slvecfn slvec, + slfloodfn slflood) { + int i, rescale; unsigned char ubfr[4]; /* Utility character buffer */ int lx, ly; /* Last x and y point */ @@ -174,14 +321,14 @@ static void slider(slvec, slflood) short rtest; /* Value to test byte reversal */ short btest = 0x1234; /* Value to test byte-reversal */ static struct slhead slhi = /* Master slide header sample */ - {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0}; + {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0}; int curcolor = 7; /* Current vector color */ pixel rgbcolor; /* Pixel used to clear pixmap */ - + lx = ly = 32000; - + /* Process the header of the slide file. */ - + sdrawkcab = FALSE; /* Initially guess byte order is OK */ fread(slfrof.slh, 17, 1, slfile); fread(&slfrof.sntype, sizeof(char), 1, slfile); @@ -194,48 +341,46 @@ static void slider(slvec, slflood) /* Verify that slide format is compatible with this program. */ - if (STREQ(slfrof.slh, slhi.slh)) { + if (streq(slfrof.slh, slhi.slh)) pm_error("this is not an AutoCAD slide file."); - } /* Verify that the number format and file level in the header are compatible. All slides written by versions of AutoCAD released since September of 1987 are compatible with this format. */ - if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel)) { + if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel)) pm_error("incompatible slide file format"); - } /* Build SDSAR value from long scaled version. */ - + ldsar = 0L; - for (i = 3; i >= 0; i--) { - ldsar = (ldsar << 8) | ubfr[i]; - } + for (i = 3; i >= 0; --i) + ldsar = (ldsar << 8) | ubfr[i]; slfrof.sdsar = ((double) ldsar) / 1E7; - + /* Examine the byte order test value. If it's backwards, set the byte-reversal flag and correct all of the values we've read in - so far. */ + so far. + */ if (btest != rtest) { - sdrawkcab = TRUE; + sdrawkcab = TRUE; #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8) - rshort(slfrof.sxdots); - rshort(slfrof.sydots); - rshort(slfrof.shwfill); + rshort(slfrof.sxdots); + rshort(slfrof.sydots); + rshort(slfrof.shwfill); #undef rshort } - + /* Dump the header if we're blithering. */ if (blither || info) { pm_message("Slide file type %d, level %d, hwfill type %d.", - slfrof.sntype, slfrof.slevel, slfrof.shwfill); + slfrof.sntype, slfrof.slevel, slfrof.shwfill); pm_message("Original screen size %dx%d, aspect ratio %.3f.", - slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar); + slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar); pm_message("Byte order is %s.", - sdrawkcab ? "being reversed" : "the same"); + sdrawkcab ? "being reversed" : "the same"); } /* If the display aspect ratio indicates that the pixels on the @@ -246,405 +391,284 @@ static void slider(slvec, slflood) We always correct the aspect ratio by adjusting the width of the image. This guarantees that output from the SHADE command, which is essentially scan-line data written in vector form, - will not be corrupted. */ + will not be corrupted. + */ dsar = ((double) slfrof.sxdots) / slfrof.sydots; if (fabs(slfrof.sdsar - dsar) > 0.0001) { - if (adjust) { - ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5; - iydots = slfrof.sydots; - dsar = ((double) ixdots) / iydots; + if (adjust) { + ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5; + iydots = slfrof.sydots; + dsar = ((double) ixdots) / iydots; + } else { + pm_message("Warning - pixels on source screen were non-square. " + "Specifying -adjust will correct image width " + "to compensate."); + ixdots = slfrof.sxdots; + iydots = slfrof.sydots; + dsar = slfrof.sdsar; + } } else { - pm_message("Warning - pixels on source screen were non-square."); - pm_message(" Specifying -adjust will correct image width to compensate."); + /* Source pixels were square. */ ixdots = slfrof.sxdots; iydots = slfrof.sydots; dsar = slfrof.sdsar; - } - } else { - /* Source pixels were square. */ - ixdots = slfrof.sxdots; - iydots = slfrof.sydots; - dsar = slfrof.sdsar; - adjust = FALSE; /* Mark no adjustment needed */ + adjust = FALSE; /* Mark no adjustment needed */ } /* If there's a uniform scale factor specified, apply it. */ if (uscale > 0) { - ixdots = (ixdots * uscale) + 0.5; - iydots = (iydots * uscale) + 0.5; + ixdots = (ixdots * uscale) + 0.5; + iydots = (iydots * uscale) + 0.5; } /* If the image is to be stretched to a given width, set the output image sizes accordingly. If only a height or width is given, scale the other direction proportionally to preserve the - aspect ratio. */ + aspect ratio. + */ if (sxsize > 0) { - if (sysize > 0) { - iydots = sysize - 1; - } else { - iydots = ((((long) iydots) * (sxsize - 1)) + - (iydots / 2)) / ixdots; - } - ixdots = sxsize - 1; - } else if (sysize > 0) { - if (sxsize > 0) { + if (sysize > 0) { + iydots = sysize - 1; + } else { + iydots = ((((long) iydots) * (sxsize - 1)) + + (iydots / 2)) / ixdots; + } ixdots = sxsize - 1; - } else { - ixdots = ((((long) ixdots) * (sysize - 1)) + - (ixdots / 2)) / iydots; - } - iydots = sysize - 1; + } else if (sysize > 0) { + if (sxsize > 0) { + ixdots = sxsize - 1; + } else { + ixdots = ((((long) ixdots) * (sysize - 1)) + + (ixdots / 2)) / iydots; + } + iydots = sysize - 1; } - + if (adjust) { - pm_message( + pm_message( "Resized from %dx%d to %dx%d to correct pixel aspect ratio.", - slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1); + slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1); } - + /* Allocate image buffer and clear it to black. */ - + pixels = ppm_allocarray(pixcols = ixdots + 1, pixrows = iydots + 1); PPM_ASSIGN(rgbcolor, 0, 0, 0); ppmd_filledrectangle(pixels, pixcols, pixrows, pixmaxval, 0, 0, pixcols, pixrows, PPMD_NULLDRAWPROC, (char *) &rgbcolor); - + if ((rescale = slfrof.sxdots != ixdots || - slfrof.sydots != iydots || - slfrof.sdsar != dsar) != 0) { - + slfrof.sydots != iydots || + slfrof.sdsar != dsar) != 0) { + /* Rescale all coords. so they'll look (more or less) - right on this display. */ - - xfac = (ixdots + 1) * 0x10000L; - xfac /= (long) (slfrof.sxdots + 1); - yfac = (iydots + 1) * 0x10000L; - yfac /= (long) (slfrof.sydots + 1); - if (dsar < slfrof.sdsar) { - yfac = yfac * dsar / slfrof.sdsar; - } else { - xfac = xfac * slfrof.sdsar / dsar; - } + right on this display. + */ + + xfac = (ixdots + 1) * 0x10000L; + xfac /= (long) (slfrof.sxdots + 1); + yfac = (iydots + 1) * 0x10000L; + yfac /= (long) (slfrof.sydots + 1); + if (dsar < slfrof.sdsar) { + yfac = yfac * dsar / slfrof.sdsar; + } else { + xfac = xfac * slfrof.sdsar / dsar; + } } poly.npoints = 0; /* No flood in progress. */ - + while ((cw = sli()) != 0xFC00) { - switch (cw & 0xFF00) { + switch (cw & 0xFF00) { case 0xFB00: /* Short vector compressed */ - vec.f.x = lx + extend(cw & 0xFF); - vec.f.y = ly + slib(); - vec.t.x = lx + slib(); - vec.t.y = ly + slib(); - lx = vec.f.x; - ly = vec.f.y; - if (rescale) { - vscale(&vec.f.x, &vec.f.y); - vscale(&vec.t.x, &vec.t.y); - } - (*slvec)(&vec, curcolor);/* Draw vector on screen */ - slx = vec.f.x; /* Save scaled point */ - sly = vec.f.y; - break; - + vec.f.x = lx + extend(cw & 0xFF); + vec.f.y = ly + slib(); + vec.t.x = lx + slib(); + vec.t.y = ly + slib(); + lx = vec.f.x; + ly = vec.f.y; + if (rescale) { + vscale(&vec.f.x, &vec.f.y); + vscale(&vec.t.x, &vec.t.y); + } + (*slvec)(&vec, curcolor);/* Draw vector on screen */ + slx = vec.f.x; /* Save scaled point */ + sly = vec.f.y; + break; + case 0xFC00: /* End of file */ - break; - + break; + case 0xFD00: /* Flood command */ - vec.f.x = sli(); - vec.f.y = sli(); - if ((int) vec.f.y < 0) { /* start or end */ - if (poly.npoints != 0) { /* end? */ - if (poly.npoints > 2 && poly.npoints < 11) { - (*slflood)(&poly, curcolor); - } else { - pm_error("Bad polygon vertex count (%d)", - poly.npoints); - } - poly.npoints = 0; - } else { - poly.fill = -vec.f.y; /* Start */ + vec.f.x = sli(); + vec.f.y = sli(); + if ((int) vec.f.y < 0) { /* start or end */ + if (poly.npoints != 0) { /* end? */ + if (poly.npoints > 2 && poly.npoints < 11) { + (*slflood)(&poly, curcolor); + } else { + pm_error("Bad polygon vertex count (%d)", + poly.npoints); + } + poly.npoints = 0; + } else { + poly.fill = -vec.f.y; /* Start */ + } + } else { /* Polygon vertex */ + if (poly.npoints < 10) { + if (rescale) { + vscale(&vec.f.x, &vec.f.y); + } + poly.pt[poly.npoints].x = vec.f.x; + poly.pt[poly.npoints].y = vec.f.y; + } + poly.npoints++; } - } else { /* Polygon vertex */ - if (poly.npoints < 10) { + break; + + case 0xFE00: /* Common endpoint compressed */ + vec.f.x = lx + extend(cw & 0xFF); + vec.f.y = ly + slib(); + lx = vec.f.x; + ly = vec.f.y; + vec.t.x = slx; + vec.t.y = sly; if (rescale) { vscale(&vec.f.x, &vec.f.y); } - poly.pt[poly.npoints].x = vec.f.x; - poly.pt[poly.npoints].y = vec.f.y; - } - poly.npoints++; - } - break; - - case 0xFE00: /* Common endpoint compressed */ - vec.f.x = lx + extend(cw & 0xFF); - vec.f.y = ly + slib(); - lx = vec.f.x; - ly = vec.f.y; - vec.t.x = slx; - vec.t.y = sly; - if (rescale) { - vscale(&vec.f.x, &vec.f.y); - } - (*slvec)(&vec, curcolor);/* Draw vector */ - slx = vec.f.x; /* Save scaled point */ - sly = vec.f.y; - break; - + (*slvec)(&vec, curcolor);/* Draw vector */ + slx = vec.f.x; /* Save scaled point */ + sly = vec.f.y; + break; + case 0xFF00: /* Change color */ - curcolor = cw & 0xFF; - break; + curcolor = cw & 0xFF; + break; default: /* Co-ordinates */ - lx = vec.f.x = cw; - ly = vec.f.y = sli(); - vec.t.x = sli(); - vec.t.y = sli(); - if (rescale) { - vscale(&vec.f.x, &vec.f.y); - vscale(&vec.t.x, &vec.t.y); - } - (*slvec)(&vec, curcolor); - slx = vec.f.x; /* Save scaled point */ - sly = vec.f.y; - break; - } - } -} - -/* SLIDEFIND -- Find a slide in a library or, if DIRONLY is - nonzero, print a directory listing of the library. - If UCASEN is nonzero, the requested slide name is - converted to upper case. */ - -static void slidefind(sname, dironly, ucasen) - char *sname; - int dironly, ucasen; -{ - char uname[32]; - unsigned char libent[36]; - long pos; - - if (dironly) { - pm_message("Slides in library:"); - } else { - int i; - char *ip = sname; - - for (i = 0; i < 31; i++) { - char ch = *ip++; - if (ch == EOS) { - break; - } - if (ucasen && ISLOWER(ch)) { - ch = TOUPPER(ch); - } - uname[i] = ch; - } - uname[i] = EOS; - } - - /* Read slide library header and verify. */ - - if ((fread(libent, 32, 1, slfile) != 1) || - (!STREQ((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) { - pm_error("not an AutoCAD slide library file."); - } - pos = 32; - - /* Search for a slide with the requested name. */ - - while (TRUE) { - if ((fread(libent, 36, 1, slfile) != 1) || - (strlen((char *)libent) == 0)) { - if (dironly) { - return; - } - pm_error("slide %s not in library.", sname); - } - pos += 36; - if (dironly) { - pm_message(" %s", libent); - } else if (STREQ((char *)libent, uname)) { - long dpos = (((((libent[35] << 8) | libent[34]) << 8) | - libent[33]) << 8) | libent[32]; - if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) { - dpos -= pos; - - while (dpos-- > 0) { - (void) getc(slfile); - } + lx = vec.f.x = cw; + ly = vec.f.y = sli(); + vec.t.x = sli(); + vec.t.y = sli(); + if (rescale) { + vscale(&vec.f.x, &vec.f.y); + vscale(&vec.t.x, &vec.t.y); + } + (*slvec)(&vec, curcolor); + slx = vec.f.x; /* Save scaled point */ + sly = vec.f.y; + break; } - break; - } } } -/* DRAW -- Draw a vector in the given AutoCAD color. */ - -static void draw(vec, color) - struct svector *vec; - int color; -{ - pixel rgbcolor; - - if (blither) { - pm_message("Vector (%d, %d) - (%d, %d) Color %d", - vec->f.x, vec->f.y, vec->t.x, vec->t.y, color); - } - assert(vec->f.x >= 0 && vec->f.x < pixcols); - assert(vec->f.y >= 0 && vec->f.y < pixrows); - assert(vec->t.x >= 0 && vec->t.x < pixcols); - assert(vec->t.y >= 0 && vec->t.y < pixrows); - PPM_ASSIGN(rgbcolor, - acadcol[color][0], acadcol[color][1], acadcol[color][2]); - ppmd_line(pixels, pixcols, pixrows, pixmaxval, - vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y, - PPMD_NULLDRAWPROC, - (char *) &rgbcolor); -} - -/* FLOOD -- Draw a filled polygon. */ - -static void -flood(struct spolygon * const poly, - int const color) { - - int i; - struct fillobj * handle; - pixel rgbcolor; - - handle = ppmd_fill_create(); - - if (blither) { - pm_message("Polygon: %d points, fill type %d, color %d", - poly->npoints, poly->fill, color); - for (i = 0; i < poly->npoints; i++) { - pm_message(" Point %d: (%d, %d)", i + 1, - poly->pt[i].x, poly->pt[i].y); - } - } - - PPM_ASSIGN(rgbcolor, - acadcol[color][0], acadcol[color][1], acadcol[color][2]); - for (i = 0; i < poly->npoints; i++) { - assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols); - assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows); - ppmd_line(pixels, pixcols, pixrows, pixmaxval, - poly->pt[i].x, iydots - poly->pt[i].y, - poly->pt[(i + 1) % poly->npoints].x, - iydots - poly->pt[(i + 1) % poly->npoints].y, - ppmd_fill_drawproc, handle); - } - ppmd_fill(pixels, pixcols, pixrows, pixmaxval, - handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor); - ppmd_fill_destroy(handle); -} /* Main program. */ -int main(argc, argv) - int argc; - char *argv[]; -{ +int +main(int argc, + char * argv[]) { + int argn; const char * const usage = "[-verbose] [-info] [-adjust] [-scale <s>]\n\ - [-dir] [-lib|-Lib <name>]\n\ - [-xsize|-width <x>] [-ysize|-height <y>] [sldfile]"; +[-dir] [-lib|-Lib <name>]\n\ +[-xsize|-width <x>] [-ysize|-height <y>] [sldfile]"; int scalespec = FALSE, widspec = FALSE, hgtspec = FALSE, dironly = FALSE, - ucasen; - char *slobber = (char *) 0; /* Slide library item */ + ucasen; + const char * slobber; /* Slide library item */ + slobber = NULL; + ppm_init(&argc, argv); argn = 1; while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { if (pm_keymatch(argv[argn], "-verbose", 2)) { - blither = TRUE; + blither = TRUE; } else if (pm_keymatch(argv[argn], "-adjust", 2)) { - adjust = TRUE; + adjust = TRUE; } else if (pm_keymatch(argv[argn], "-dir", 2)) { - dironly = TRUE; + dironly = TRUE; } else if (pm_keymatch(argv[argn], "-info", 2)) { - info = TRUE; + info = TRUE; } else if (pm_keymatch(argv[argn], "-lib", 2)) { - if (slobber != (char *) 0) { + if (slobber) pm_error("already specified a library item"); - } ucasen = argv[argn][1] != 'L'; - argn++; - if (argn == argc) { - pm_usage(usage); - } - slobber = argv[argn]; + argn++; + if (argn == argc) { + pm_usage(usage); + } + slobber = argv[argn]; } else if (pm_keymatch(argv[argn], "-scale", 2)) { - if (scalespec) { + if (scalespec) { pm_error("already specified a scale factor"); - } - argn++; + } + argn++; if ((argn == argc) || (sscanf(argv[argn], "%lf", &uscale) != 1)) - pm_usage(usage); - if (uscale <= 0.0) { + pm_usage(usage); + if (uscale <= 0.0) { pm_error("scale factor must be greater than 0"); - } - scalespec = TRUE; + } + scalespec = TRUE; } else if (pm_keymatch(argv[argn], "-xsize", 2) || pm_keymatch(argv[argn], "-width", 2)) { - if (widspec) { + if (widspec) { pm_error("already specified a width/xsize"); - } - argn++; + } + argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1)) - pm_usage(usage); - widspec = TRUE; + pm_usage(usage); + widspec = TRUE; } else if (pm_keymatch(argv[argn], "-ysize", 2) || pm_keymatch(argv[argn], "-height", 2)) { - if (hgtspec) { + if (hgtspec) { pm_error("already specified a height/ysize"); + } + argn++; + if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) + pm_usage(usage); + hgtspec = TRUE; + } else { + pm_usage(usage); } argn++; - if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) - pm_usage(usage); - hgtspec = TRUE; - } else { - pm_usage(usage); - } - argn++; } /* If a file name is specified, open it. Otherwise read from - standard input. */ + standard input. + */ if (argn < argc) { - slfile = pm_openr(argv[argn]); - argn++; + slfile = pm_openr(argv[argn]); + argn++; } else { - slfile = stdin; + slfile = stdin; } - + if (argn != argc) { /* Extra bogus arguments ? */ - pm_usage(usage); + pm_usage(usage); } - + /* If we're extracting an item from a slide library, position the - input stream to the start of the chosen slide. */ - - if (dironly || (slobber != (char *) 0)) { - slidefind(slobber, dironly, ucasen); - } - + input stream to the start of the chosen slide. + */ + + if (dironly || slobber) + slidefind(slobber, dironly, ucasen); + if (!dironly) { - slider(draw, flood); - ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE); + slider(draw, flood); + ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE); } pm_close(slfile); pm_close(stdout); - exit(0); + + return 0; } diff --git a/converter/ppm/spctoppm.c b/converter/ppm/spctoppm.c index 3eea7821..d2a48187 100644 --- a/converter/ppm/spctoppm.c +++ b/converter/ppm/spctoppm.c @@ -165,15 +165,8 @@ DoBitmap( ifp ) sscreen[i] = ( screen[i<<1] << 8 ) + ( 0xff & screen[(i<<1)+1] ); } -#if __STDC__ static void DoChar( int n, char c ) -#else /*__STDC__*/ -static void -DoChar( n, c ) - int n; - char c; -#endif /*__STDC__*/ { int i; diff --git a/converter/ppm/tgatoppm.c b/converter/ppm/tgatoppm.c index 8a559848..f8538214 100644 --- a/converter/ppm/tgatoppm.c +++ b/converter/ppm/tgatoppm.c @@ -16,6 +16,8 @@ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #include <string.h> + +#include "pm_c_util.h" #include "ppm.h" #include "tga.h" #include "shhopt.h" @@ -81,7 +83,7 @@ parseCommandLine(int argc, char ** argv, "is the input file specification"); if (alpha_spec && - STREQ(cmdlineP->alpha_filename, "-")) + streq(cmdlineP->alpha_filename, "-")) cmdlineP->alpha_stdout = 1; else cmdlineP->alpha_stdout = 0; diff --git a/converter/ppm/winicontoppm.c b/converter/ppm/winicontoppm.c index 2d9de567..ad859c94 100644 --- a/converter/ppm/winicontoppm.c +++ b/converter/ppm/winicontoppm.c @@ -21,6 +21,7 @@ #include <string.h> #include <assert.h> +#include "pm_c_util.h" #include "ppm.h" #include "shhopt.h" #include "nstring.h" @@ -572,7 +573,7 @@ trimOutputName(const char inputName[]) * oh, for =~ ... :) */ char * outFile = strdup(inputName); - if (STREQ(outFile + (strlen (outFile) - 4), ".ppm")) { + if (streq(outFile + (strlen (outFile) - 4), ".ppm")) { *(outFile + (strlen (outFile) - 4)) = 0; } return outFile; @@ -828,7 +829,7 @@ main(int argc, char *argv[]) { pm_message("-bestqual doesn't make sense with -allicons. " "Ignoring -bestqual."); - if (STREQ(cmdline.outputFilespec, "-")) + if (streq(cmdline.outputFilespec, "-")) outputFileBase = NULL; else outputFileBase = trimOutputName(cmdline.outputFilespec); diff --git a/converter/ppm/ximtoppm.c b/converter/ppm/ximtoppm.c index 28c9b674..15589c16 100644 --- a/converter/ppm/ximtoppm.c +++ b/converter/ppm/ximtoppm.c @@ -14,6 +14,8 @@ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #include <string.h> + +#include "pm_c_util.h" #include "ppm.h" #include "xim.h" #include "shhopt.h" @@ -69,7 +71,7 @@ parseCommandLine(int argc, char ** argv, "is the input file specification"); if (cmdlineP->alpha_filename && - STREQ(cmdlineP->alpha_filename, "-")) + streq(cmdlineP->alpha_filename, "-")) cmdlineP->alpha_stdout = TRUE; else cmdlineP->alpha_stdout = FALSE; diff --git a/converter/ppm/xpmtoppm.c b/converter/ppm/xpmtoppm.c index 9dddfd83..5884d3d4 100644 --- a/converter/ppm/xpmtoppm.c +++ b/converter/ppm/xpmtoppm.c @@ -33,6 +33,7 @@ #include <string.h> +#include "pm_c_util.h" #include "ppm.h" #include "shhopt.h" #include "nstring.h" @@ -104,7 +105,7 @@ parse_command_line(int argc, char ** argv, "is the input file specification"); if (cmdline_p->alpha_filename && - STREQ(cmdline_p->alpha_filename, "-")) + streq(cmdline_p->alpha_filename, "-")) cmdline_p->alpha_stdout = TRUE; else cmdline_p->alpha_stdout = FALSE; @@ -293,7 +294,7 @@ interpretXpm3ColorTableLine(char line[], int const seqNum, number if so) */ for (key = 1; - key <= NKEYS && !STREQ(xpmColorKeys[key - 1], str2); + key <= NKEYS && !streq(xpmColorKeys[key - 1], str2); key++); isKey = (key <= NKEYS); @@ -483,15 +484,15 @@ readXpm1Header(FILE * const stream, int * const widthP, int * const heightP, t1 = str1; else ++t1; - if (STREQ(t1, "format")) + if (streq(t1, "format")) format = v; - else if (STREQ(t1, "width")) + else if (streq(t1, "width")) *widthP = v; - else if (STREQ(t1, "height")) + else if (streq(t1, "height")) *heightP = v; - else if (STREQ(t1, "ncolors")) + else if (streq(t1, "ncolors")) *ncolorsP = v; - else if (STREQ(t1, "pixel")) + else if (streq(t1, "pixel")) *chars_per_pixelP = v; } else if (!strncmp(line, "static char", 11)) { if ((t1 = strrchr(line, '_')) == NULL) diff --git a/converter/ppm/xvminitoppm.c b/converter/ppm/xvminitoppm.c index 935ab177..d76bea87 100644 --- a/converter/ppm/xvminitoppm.c +++ b/converter/ppm/xvminitoppm.c @@ -12,6 +12,7 @@ #include <assert.h> #include <string.h> +#include <errno.h> #include "pm_c_util.h" #include "nstring.h" @@ -61,7 +62,8 @@ getLine(FILE * const ifP, rc = fgets(buf, size, ifP); if (rc == NULL) { if (ferror(ifP)) - pm_perror("read error"); + pm_error("read error. fgets() failed, errno=%d (%s)", + errno, strerror(errno)); else pm_error("unexpected EOF"); } @@ -107,16 +109,16 @@ readXvHeader(FILE * const ifP, getLine(ifP, buf, sizeof(buf)); - if (!STRNEQ(buf, "P7 332", 6)) + if (!strneq(buf, "P7 332", 6)) pm_error("Input is not a XV thumbnail picture. It does not " "begin with the characters 'P7 332'."); endOfComments = FALSE; while (!endOfComments) { getLine(ifP, buf, sizeof(buf)); - if (STRNEQ(buf, "#END_OF_COMMENTS", 16)) + if (strneq(buf, "#END_OF_COMMENTS", 16)) endOfComments = TRUE; - else if (STRNEQ(buf, "#BUILTIN", 8)) + else if (strneq(buf, "#BUILTIN", 8)) pm_error("This program does not know how to " "convert builtin XV thumbnail pictures"); } diff --git a/converter/ppm/yuvsplittoppm.c b/converter/ppm/yuvsplittoppm.c index 0f5e19a3..b3088812 100644 --- a/converter/ppm/yuvsplittoppm.c +++ b/converter/ppm/yuvsplittoppm.c @@ -20,6 +20,8 @@ */ #include <string.h> + +#include "pm_c_util.h" #include "ppm.h" #include "nstring.h" #include "shhopt.h" |