From c5a8ccd7cf841ae491e905b709cb702f3c86bedf Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sun, 25 Jan 2009 19:13:21 +0000 Subject: Move stuff into new editor/specialty/ directory git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@831 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/Makefile | 28 +- editor/pamdeinterlace.c | 132 -------- editor/pammixinterlace.c | 344 -------------------- editor/pamoil.c | 137 -------- editor/pampop9.c | 108 ------- editor/pbmlife.c | 114 ------- editor/pgmabel.c | 316 ------------------ editor/pgmbentley.c | 74 ----- editor/pgmmorphconv.c | 253 --------------- editor/pnmindex.c | 639 ------------------------------------- editor/ppm3d.c | 307 ------------------ editor/ppmglobe.c | 172 ---------- editor/ppmntsc.c | 499 ----------------------------- editor/ppmrelief.c | 90 ------ editor/ppmshift.c | 132 -------- editor/ppmspread.c | 117 ------- editor/ppmtv.c | 105 ------ editor/specialty/Makefile | 55 ++++ editor/specialty/pamdeinterlace.c | 132 ++++++++ editor/specialty/pammixinterlace.c | 344 ++++++++++++++++++++ editor/specialty/pamoil.c | 137 ++++++++ editor/specialty/pampop9.c | 108 +++++++ editor/specialty/pbmlife.c | 114 +++++++ editor/specialty/pgmabel.c | 316 ++++++++++++++++++ editor/specialty/pgmbentley.c | 74 +++++ editor/specialty/pgmmorphconv.c | 253 +++++++++++++++ editor/specialty/pnmindex.c | 639 +++++++++++++++++++++++++++++++++++++ editor/specialty/ppm3d.c | 307 ++++++++++++++++++ editor/specialty/ppmglobe.c | 172 ++++++++++ editor/specialty/ppmntsc.c | 499 +++++++++++++++++++++++++++++ editor/specialty/ppmrelief.c | 90 ++++++ editor/specialty/ppmshift.c | 132 ++++++++ editor/specialty/ppmspread.c | 117 +++++++ editor/specialty/ppmtv.c | 105 ++++++ 34 files changed, 3606 insertions(+), 3555 deletions(-) delete mode 100644 editor/pamdeinterlace.c delete mode 100644 editor/pammixinterlace.c delete mode 100644 editor/pamoil.c delete mode 100644 editor/pampop9.c delete mode 100644 editor/pbmlife.c delete mode 100644 editor/pgmabel.c delete mode 100644 editor/pgmbentley.c delete mode 100644 editor/pgmmorphconv.c delete mode 100644 editor/pnmindex.c delete mode 100644 editor/ppm3d.c delete mode 100644 editor/ppmglobe.c delete mode 100644 editor/ppmntsc.c delete mode 100644 editor/ppmrelief.c delete mode 100644 editor/ppmshift.c delete mode 100644 editor/ppmspread.c delete mode 100644 editor/ppmtv.c create mode 100644 editor/specialty/Makefile create mode 100644 editor/specialty/pamdeinterlace.c create mode 100644 editor/specialty/pammixinterlace.c create mode 100644 editor/specialty/pamoil.c create mode 100644 editor/specialty/pampop9.c create mode 100644 editor/specialty/pbmlife.c create mode 100644 editor/specialty/pgmabel.c create mode 100644 editor/specialty/pgmbentley.c create mode 100644 editor/specialty/pgmmorphconv.c create mode 100644 editor/specialty/pnmindex.c create mode 100644 editor/specialty/ppm3d.c create mode 100644 editor/specialty/ppmglobe.c create mode 100644 editor/specialty/ppmntsc.c create mode 100644 editor/specialty/ppmrelief.c create mode 100644 editor/specialty/ppmshift.c create mode 100644 editor/specialty/ppmspread.c create mode 100644 editor/specialty/ppmtv.c diff --git a/editor/Makefile b/editor/Makefile index 6e311e3e..931237b2 100644 --- a/editor/Makefile +++ b/editor/Makefile @@ -7,6 +7,8 @@ VPATH=.:$(SRCDIR)/$(SUBDIR) include $(BUILDDIR)/config.mk +SUBDIRS = specialty + # We tend to separate out the build targets so that we don't have # any more dependencies for a given target than it really needs. # That way, if there is a problem with a dependency, we can still @@ -15,24 +17,23 @@ include $(BUILDDIR)/config.mk # build. PORTBINARIES = pamaddnoise pambackground pamcomp pamcut \ - pamdeinterlace pamdice pamditherbw pamedge \ + pamdice pamditherbw pamedge \ pamenlarge \ - pamflip pamfunc pammasksharpen pammixinterlace \ - pamoil pamperspective pampop9 \ + pamflip pamfunc pammasksharpen \ + pamperspective \ pamscale pamstretch pamthreshold pamundice \ - pbmclean pbmlife pbmmask pbmpscale pbmreduce \ - pgmabel pgmbentley pgmdeshadow pgmenhance \ - pgmmedian pgmmorphconv \ + pbmclean pbmmask pbmpscale pbmreduce \ + pgmdeshadow pgmenhance \ + pgmmedian \ pnmalias pnmcat pnmcomp pnmconvol pnmcrop \ pnmgamma \ - pnmhisteq pnmindex pnminvert pnmmontage \ + pnmhisteq pnminvert pnmmontage \ pnmnlfilt pnmnorm pnmpad pnmpaste \ pnmremap pnmrotate \ pnmscale pnmscalefixed pnmshear pnmsmooth pnmstitch pnmtile \ - ppm3d ppmbrighten ppmchange ppmcolormask \ + ppmbrighten ppmchange ppmcolormask \ ppmdim ppmdist ppmdither ppmdraw \ - ppmflash ppmglobe ppmlabel ppmmix \ - ppmntsc ppmrelief ppmshift ppmspread ppmtv + ppmflash ppmlabel ppmmix \ # We don't include programs that have special library dependencies in the # merge scheme, because we don't want those dependencies to prevent us @@ -51,7 +52,7 @@ OBJECTS = $(BINARIES:%=%.o) MERGE_OBJECTS = $(MERGEBINARIES:%=%.o2) .PHONY: all -all: $(BINARIES) +all: $(BINARIES) $(SUBDIRS:%=%/all) include $(SRCDIR)/common.mk @@ -60,15 +61,10 @@ install.bin: install.bin.local .PHONY: install.bin.local install.bin.local: $(PKGDIR)/bin # Remember that $(SYMLINK) might just be a copy command. -# backward compatibility: program used to be named pnmnoraw # backward compatibility: program used to be pnminterp cd $(PKGDIR)/bin ; \ rm -f pnminterp; \ $(SYMLINK) pamstretch$(EXE) pnminterp -# pamoil replaced pgmoil in June 2001. - cd $(PKGDIR)/bin ; \ - rm -f pgmoil ; \ - $(SYMLINK) pamoil$(EXE) pgmoil # In March 2002, pnmnorm replaced ppmnorm and pgmnorm cd $(PKGDIR)/bin ; \ rm -f ppmnorm ; \ diff --git a/editor/pamdeinterlace.c b/editor/pamdeinterlace.c deleted file mode 100644 index 9ed1d8eb..00000000 --- a/editor/pamdeinterlace.c +++ /dev/null @@ -1,132 +0,0 @@ -/****************************************************************************** - pamdeinterlace -******************************************************************************* - De-interlace an image, i.e. select every 2nd row. - - By Bryan Henderson, San Jose, CA 2001.11.11. - - Contributed to the public domain. -******************************************************************************/ - -#include "pam.h" -#include "shhopt.h" -#include "mallocvar.h" - -enum evenodd {EVEN, ODD}; - -struct cmdlineInfo { - /* All the information the user supplied in the command line, - in a form easy for the program to use. - */ - const char *inputFilespec; /* Filespecs of input files */ - enum evenodd rowsToTake; -}; - - -static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo *cmdlineP) { -/*---------------------------------------------------------------------------- - Note that the file spec array we return is stored in the storage that - was passed to us as the argv array. ------------------------------------------------------------------------------*/ - optStruct3 opt; /* set by OPTENT3 */ - optEntry *option_def; - unsigned int option_def_index; - - unsigned int takeeven, takeodd; - - MALLOCARRAY_NOFAIL(option_def, 100); - - option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "takeeven", OPT_FLAG, NULL, &takeeven, 0); - OPTENT3(0, "takeodd", OPT_FLAG, NULL, &takeodd, 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); - /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - - if (takeeven && takeodd) - pm_error("You cannot specify both -takeeven and -takeodd options."); - - if (takeodd) - cmdlineP->rowsToTake = ODD; - else - cmdlineP->rowsToTake = EVEN; - - if (argc-1 < 1) - cmdlineP->inputFilespec = "-"; - else if (argc-1 == 1) - cmdlineP->inputFilespec = argv[1]; - else - pm_error("You specified too many arguments (%d). The only " - "argument is the optional input file specification.", - argc-1); -} - - - - - -int -main(int argc, char *argv[]) { - - FILE * ifP; - tuple * tuplerow; /* Row from input image */ - unsigned int row; - struct cmdlineInfo cmdline; - struct pam inpam; - struct pam outpam; - - pnm_init( &argc, argv ); - - parseCommandLine(argc, argv, &cmdline); - - ifP = pm_openr(cmdline.inputFilespec); - - pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); - - tuplerow = pnm_allocpamrow(&inpam); - - outpam = inpam; /* Initial value -- most fields should be same */ - outpam.file = stdout; - if (inpam.height % 2 == 0) - outpam.height = inpam.height / 2; - else { - if (cmdline.rowsToTake == ODD) - outpam.height = inpam.height / 2; - else - outpam.height = inpam.height / 2 + 1; - } - - pnm_writepaminit(&outpam); - - { - unsigned int modulusToTake; - /* The row number mod 2 of the rows that are supposed to go into - the output. - */ - - switch (cmdline.rowsToTake) { - case EVEN: modulusToTake = 0; break; - case ODD: modulusToTake = 1; break; - default: pm_error("INTERNAL ERROR: invalid rowsToTake"); - } - - /* Read input and write out rows extracted from it */ - for (row = 0; row < inpam.height; row++) { - pnm_readpamrow(&inpam, tuplerow); - if (row % 2 == modulusToTake) - pnm_writepamrow(&outpam, tuplerow); - } - } - pnm_freepamrow(tuplerow); - pm_close(inpam.file); - pm_close(outpam.file); - - return 0; -} - diff --git a/editor/pammixinterlace.c b/editor/pammixinterlace.c deleted file mode 100644 index f22563f6..00000000 --- a/editor/pammixinterlace.c +++ /dev/null @@ -1,344 +0,0 @@ -/****************************************************************************** - pammixinterlace -******************************************************************************* - De-interlace an image by merging adjacent rows. - - Copyright (C) 2007 Bruce Guenter, FutureQuest, Inc. - - 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. - -******************************************************************************/ - -#define _BSD_SOURCE /* Make sure strcaseeq() is in nstring.h */ - -#include - -#include "mallocvar.h" -#include "nstring.h" -#include "shhopt.h" -#include "pam.h" - - - -static sample -clamp(sample const val, - sample const maxval) { - - return val < 0 ? 0 : val > maxval ? maxval : val; -} - - - -static bool -distant(long const above, - long const mid, - long const below) { - - return abs(mid - (above + below) / 2) > abs(above - below); -} - - - -static void -filterLinearBlend(tuple * const outputrow, - tuple ** const tuplerowWindow, - unsigned int const width, - unsigned int const depth, - bool const adaptive, - sample const maxval) { - - unsigned int col; - - for (col = 0; col < width; ++col) { - unsigned int plane; - - for (plane = 0; plane < depth; ++plane) { - long const above = tuplerowWindow[0][col][plane]; - long const mid = tuplerowWindow[1][col][plane]; - long const below = tuplerowWindow[2][col][plane]; - - sample out; - - if (!adaptive || distant(above, mid, below)) - out = (above + mid * 2 + below) / 4; - else - out = mid; - - outputrow[col][plane] = out; - } - } -} - - - -static void -filterFfmpeg(tuple * const outputrow, - tuple ** const tuplerowWindow, - unsigned int const width, - unsigned int const depth, - bool const adaptive, - sample const maxval) { - - unsigned int col; - - for (col = 0; col < width; ++col) { - unsigned int plane; - - for (plane = 0; plane < depth; ++plane) { - long const above = tuplerowWindow[1][col][plane]; - long const mid = tuplerowWindow[2][col][plane]; - long const below = tuplerowWindow[3][col][plane]; - - sample out; - - if (!adaptive || distant(above, mid, below)) { - long const a = (- (long)tuplerowWindow[0][col][plane] - + above * 4 - + mid * 2 - + below * 4 - - (long)tuplerowWindow[4][col][plane]) / 8; - out = clamp(a, maxval); - } else - out = mid; - - outputrow[col][plane] = out; - } - } -} - - - -static void -filterFIR(tuple * const outputrow, - tuple ** const tuplerowWindow, - unsigned int const width, - unsigned int const depth, - bool const adaptive, - sample const maxval) { - - unsigned int col; - - for (col = 0; col < width; ++col) { - unsigned int plane; - - for (plane = 0; plane < depth; ++plane) { - - long const above = tuplerowWindow[1][col][plane]; - long const mid = tuplerowWindow[2][col][plane]; - long const below = tuplerowWindow[3][col][plane]; - - sample out; - - if (!adaptive || distant(above, mid, below)) { - long const a = (- (long)tuplerowWindow[0][col][plane] - + above * 2 - + mid * 6 - + below * 2 - - (long)tuplerowWindow[4][col][plane]) / 8; - out = clamp(a, maxval); - } else - out = mid; - - outputrow[col][plane] = out; - } - } -} - - - -struct filter { - const char * name; /* The command-line name of the filter */ - unsigned int rows; /* The number of rows the filter operates on */ - void (*filter)(tuple *, tuple **, - unsigned int width, unsigned int depth, - bool adaptive, sample maxval); -}; - -static struct filter filters[] = { - { "fir", 5, filterFIR }, /* FIR is cleanest and default filter */ - { "ffmpeg", 5, filterFfmpeg }, - { "linear", 3, filterLinearBlend }, -}; - -struct cmdlineInfo { - /* All the information the user supplied in the command line, - in a form easy for the program to use. - */ - const char * inputFileName; /* Names of input files */ - struct filter * filterP; - unsigned int adaptive; -}; - - - -static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { -/*---------------------------------------------------------------------------- - Note that the file spec array we return is stored in the storage that - was passed to us as the argv array. ------------------------------------------------------------------------------*/ - optStruct3 opt; /* set by OPTENT3 */ - optEntry * option_def; - unsigned int option_def_index; - const char * filterName; - unsigned int filterSpec; - - MALLOCARRAY_NOFAIL(option_def, 100); - - option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "filter", OPT_STRING, &filterName, &filterSpec, 0); - OPTENT3(0, "adaptive", OPT_FLAG, NULL, &cmdlineP->adaptive, 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); - /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - - if (!filterSpec) - cmdlineP->filterP = &filters[0]; - else { - unsigned int i; - cmdlineP->filterP = NULL; - for (i = 0; i < sizeof filters / sizeof(struct filter); ++i) { - if (strcaseeq(filterName, filters[i].name)) { - cmdlineP->filterP = &filters[i]; - break; - } - } - if (!cmdlineP->filterP) - pm_error("The filter name '%s' is not known.", filterName); - } - - if (argc-1 < 1) - cmdlineP->inputFileName = "-"; - else if (argc-1 == 1) - cmdlineP->inputFileName = argv[1]; - else - pm_error("You specified too many arguments (%d). The only " - "argument is the optional input file specification.", - argc-1); -} - - - -static void -allocateRowWindowBuffer(struct pam * const pamP, - tuple ** const tuplerowWindow, - unsigned int const rows) { - - unsigned int row; - - for (row = 0; row < rows; ++row) - tuplerowWindow[row] = pnm_allocpamrow(pamP); -} - - - -static void -freeRowWindowBuffer(tuple ** const tuplerowWindow, - unsigned int const rows) { - - unsigned int row; - - for (row = 0; row < rows; ++row) - pnm_freepamrow(tuplerowWindow[row]); -} - - - -static void -slideWindowDown(tuple ** const tuplerowWindow, - unsigned int const rows) { -/*---------------------------------------------------------------------------- - Slide the rows-line tuple row window tuplerowWindow[] down one by moving - pointers. ------------------------------------------------------------------------------*/ - tuple * const oldrow0 = tuplerowWindow[0]; - - unsigned int i; - - for (i = 0; i < rows-1; ++i) - tuplerowWindow[i] = tuplerowWindow[i+1]; - - tuplerowWindow[i] = oldrow0; -} - - - -int -main(int argc, char *argv[]) { - - FILE * ifP; - struct cmdlineInfo cmdline; - struct pam inpam; - struct pam outpam; - tuple * tuplerowWindow[5]; - tuple * outputrow; - unsigned int rows; - - pnm_init(&argc, argv); - - parseCommandLine(argc, argv, &cmdline); - - rows = cmdline.filterP->rows; - - ifP = pm_openr(cmdline.inputFileName); - - pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); - - outpam = inpam; /* Initial value -- most fields should be same */ - outpam.file = stdout; - - pnm_writepaminit(&outpam); - - allocateRowWindowBuffer(&inpam, tuplerowWindow, rows); - outputrow = pnm_allocpamrow(&outpam); - - if (inpam.height < rows) { - unsigned int row; - pm_message("WARNING: Image height less than %d. No mixing done.", - rows); - for (row = 0; row < inpam.height; ++row) { - pnm_readpamrow(&inpam, tuplerowWindow[0]); - pnm_writepamrow(&outpam, tuplerowWindow[0]); - } - } else { - unsigned int row; - - for (row = 0; row < rows-1; ++row) - pnm_readpamrow(&inpam, tuplerowWindow[row]); - - /* Pass through first unfilterable rows */ - for (row = 0; row < rows/2; ++row) - pnm_writepamrow(&outpam, tuplerowWindow[row]); - - for (row = rows / 2 + 1; row < inpam.height - rows / 2 + 1; ++row) { - pnm_readpamrow(&inpam, tuplerowWindow[rows-1]); - cmdline.filterP->filter(outputrow, tuplerowWindow, - inpam.width, inpam.depth, - cmdline.adaptive, inpam.maxval); - pnm_writepamrow(&outpam, outputrow); - - slideWindowDown(tuplerowWindow, rows); - } - - /* Pass through last rows */ - for (row = rows/2; row < rows-1; ++row) - pnm_writepamrow(&outpam, tuplerowWindow[row]); - } - - freeRowWindowBuffer(tuplerowWindow, rows); - pnm_freepamrow(outputrow); - pm_close(inpam.file); - pm_close(outpam.file); - - return 0; -} diff --git a/editor/pamoil.c b/editor/pamoil.c deleted file mode 100644 index 6cb8d3ac..00000000 --- a/editor/pamoil.c +++ /dev/null @@ -1,137 +0,0 @@ -/* pgmoil.c - read a portable pixmap and turn into an oil painting -** -** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com) -** Shamelessly butchered into a color version by Chris Sheppard -** 2001 -** -** Permission to use, copy, modify, and distribute this software and its -** documentation for any purpose and without fee is hereby granted, provided -** that the above copyright notice appear in all copies and that both that -** copyright notice and this permission notice appear in supporting -** documentation. This software is provided "as is" without express or -** implied warranty. -*/ - -#include -#include -#include -#include "pam.h" -#include "mallocvar.h" - -static void -convertRow(struct pam const inpam, tuple ** const tuples, - tuple * const tuplerow, int const row, int const smearFactor, - int * const hist) { - - int sample; - for (sample = 0; sample < inpam.depth; sample++) { - int col; - for (col = 0; col < inpam.width; ++col) { - int i; - int drow; - int modalval; - /* The sample value that occurs most often in the neighborhood - of the pixel being examined - */ - - /* Compute hist[] - frequencies, in the neighborhood, of each - sample value - */ - for (i = 0; i <= inpam.maxval; ++i) hist[i] = 0; - - for (drow = row - smearFactor; drow <= row + smearFactor; ++drow) { - if (drow >= 0 && drow < inpam.height) { - int dcol; - for (dcol = col - smearFactor; - dcol <= col + smearFactor; - ++dcol) { - if ( dcol >= 0 && dcol < inpam.width ) - ++hist[tuples[drow][dcol][sample]]; - } - } - } - { - /* Compute modalval */ - int sampleval; - int maxfreq; - - maxfreq = 0; - modalval = 0; - - for (sampleval = 0; sampleval <= inpam.maxval; ++sampleval) { - if (hist[sampleval] > maxfreq) { - maxfreq = hist[sampleval]; - modalval = sampleval; - } - } - } - tuplerow[col][sample] = modalval; - } - } -} - - - -int -main(int argc, char *argv[] ) { - struct pam inpam, outpam; - FILE* ifp; - tuple ** tuples; - tuple * tuplerow; - int * hist; - /* A buffer for the convertRow subroutine to use */ - int argn; - int row; - int smearFactor; - const char* const usage = "[-n ] [ppmfile]"; - - ppm_init( &argc, argv ); - - argn = 1; - smearFactor = 3; /* DEFAULT VALUE */ - - /* Check for options. */ - if ( argn < argc && argv[argn][0] == '-' ) { - if ( argv[argn][1] == 'n' ) { - ++argn; - if ( argn == argc || sscanf(argv[argn], "%d", &smearFactor) != 1 ) - pm_usage( usage ); - } else - pm_usage( usage ); - ++argn; - } - if ( argn < argc ) { - ifp = pm_openr( argv[argn] ); - ++argn; - } else - ifp = stdin; - - if ( argn != argc ) - pm_usage( usage ); - - tuples = pnm_readpam(ifp, &inpam, PAM_STRUCT_SIZE(tuple_type)); - pm_close(ifp); - - MALLOCARRAY(hist, inpam.maxval + 1); - if (hist == NULL) - pm_error("Unable to allocate memory for histogram."); - - outpam = inpam; outpam.file = stdout; - - pnm_writepaminit(&outpam); - - tuplerow = pnm_allocpamrow(&inpam); - - for (row = 0; row < inpam.height; ++row) { - convertRow(inpam, tuples, tuplerow, row, smearFactor, hist); - pnm_writepamrow(&outpam, tuplerow); - } - - pnm_freepamrow(tuplerow); - free(hist); - pnm_freepamarray(tuples, &inpam); - - pm_close(stdout); - exit(0); -} - diff --git a/editor/pampop9.c b/editor/pampop9.c deleted file mode 100644 index d6c61e4f..00000000 --- a/editor/pampop9.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * (c) Robert Tinsley, 2003 (http://www.thepoacher.net/contact) - * - * Released under the GPL (http://www.fsf.org/licenses/gpl.txt) - * - * - * CHANGES - * - * v1.00 2003-02-28 Original version - * - * v1.10 2003-03-02 - * + changed to use pam_* routines rather than ppm_* - * + changed to use pm_* rather than fopen()/fclose() - * + renamed from ppmgrid to pampup9 - * + wrote a man-page (actually, html) - * - * Changes by Bryan Henderson for inclusion in the Netpbm package (fully - * exploiting Netpbm library). Renamed to Pampop9. March 2003. - * - */ - -#include -#include /* atoi() */ - -#include "pam.h" - -static const char * const copyright = - "(c) Robert Tinsley 2003 (http://www.thepoacher.net/contact)"; - -static const char *usagestr = "pnmfile|- xtiles ytiles xdelta ydelta"; - -int main(int argc, char *argv[]) -{ - const char *filename = "-"; - int xtiles, ytiles, xdelta, ydelta; - FILE *fp; - - struct pam spam, dpam; - tuple **spix, *dpix; - int xtilesize, ytilesize, sx, sy, dx, dy, p; - - - - pnm_init(&argc, argv); - - if (argc-1 != 5) { - pm_error("Wrong number of arguments. Program requires 5 arguments; " - "you supplied %d. Usage: %s", argc-1, usagestr); - } - - filename = argv[1]; - xtiles = atoi(argv[2]); - ytiles = atoi(argv[3]); - xdelta = atoi(argv[4]); - ydelta = atoi(argv[5]); - - if (filename == NULL || *filename == '\0' - || xtiles <= 0 || ytiles <= 0 || xdelta < 0 || ydelta < 0) - pm_error("invalid argument"); - - /* read src pam */ - - fp = pm_openr(filename); - - spix = pnm_readpam(fp, &spam, PAM_STRUCT_SIZE(tuple_type)); - - pm_close(fp); - - /* init dst pam */ - - xtilesize = spam.width - (xtiles - 1) * xdelta; - ytilesize = spam.height - (ytiles - 1) * ydelta; - - if (xtilesize <= 0) - pm_error("xtilesize must be positive. You specified %d", xtilesize); - if (ytilesize <= 0) - pm_error("ytilesize must be positive. You specified %d", ytilesize); - - dpam = spam; - dpam.file = stdout; - dpam.width = xtiles * xtilesize; - dpam.height = ytiles * ytilesize; - - dpix = pnm_allocpamrow(&dpam); - - pnm_writepaminit(&dpam); - - /* generate dst pam */ - - for (dy = 0; dy < dpam.height; dy++) { - sy = ((int) (dy / ytilesize)) * ydelta + (dy % ytilesize); - for (dx = 0; dx < dpam.width; dx++) { - sx = ((int) (dx / xtilesize)) * xdelta + (dx % xtilesize); - for (p = 0; p < spam.depth; ++p) { - dpix[dx][p] = spix[sy][sx][p]; - } - } - pnm_writepamrow(&dpam, dpix); - } - - /* all done */ - - pnm_freepamarray(spix, &spam); - pnm_freepamrow(dpix); - - exit(EXIT_SUCCESS); -} diff --git a/editor/pbmlife.c b/editor/pbmlife.c deleted file mode 100644 index be34cc69..00000000 --- a/editor/pbmlife.c +++ /dev/null @@ -1,114 +0,0 @@ -/* pbmlife.c - read a portable bitmap and apply Conway's rules of Life to it -** -** Copyright (C) 1988,1 1991 by Jef Poskanzer. -** -** Permission to use, copy, modify, and distribute this software and its -** documentation for any purpose and without fee is hereby granted, provided -** that the above copyright notice appear in all copies and that both that -** copyright notice and this permission notice appear in supporting -** documentation. This software is provided "as is" without express or -** implied warranty. -*/ - -#include "pbm.h" - -int -main( argc, argv ) -int argc; -char* argv[]; - { - FILE* ifp; - bit* prevrow; - bit* thisrow; - bit* nextrow; - bit* temprow; - register bit* newrow; - int rows, cols, row; - register int col, count; - int format; - - - pbm_init( &argc, argv ); - - if ( argc > 2 ) - pm_usage( "[pbmfile]" ); - - if ( argc == 2 ) - ifp = pm_openr( argv[1] ); - else - ifp = stdin; - - pbm_readpbminit( ifp, &cols, &rows, &format ); - prevrow = pbm_allocrow( cols ); - thisrow = pbm_allocrow( cols ); - nextrow = pbm_allocrow( cols ); - - pbm_writepbminit( stdout, cols, rows, 0 ); - newrow = pbm_allocrow( cols ); - - pbm_readpbmrow( ifp, nextrow, cols, format ); - - for ( row = 0; row < rows; ++row ) - { - temprow = prevrow; - prevrow = thisrow; - thisrow = nextrow; - nextrow = temprow; - if ( row < rows - 1 ) - pbm_readpbmrow( ifp, nextrow, cols, format ); - - for ( col = 0; col < cols; ++col ) - { - /* Check the neighborhood, with an unrolled double loop. */ - count = 0; - if ( row > 0 ) - { - /* upper left */ - if ( col > 0 && prevrow[col - 1] == PBM_WHITE ) - ++count; - /* upper center */ - if ( prevrow[col] == PBM_WHITE ) - ++count; - /* upper right */ - if ( col < cols - 1 && prevrow[col + 1] == PBM_WHITE ) - ++count; - } - /* left */ - if ( col > 0 && thisrow[col - 1] == PBM_WHITE ) - ++count; - /* right */ - if ( col < cols - 1 && thisrow[col + 1] == PBM_WHITE ) - ++count; - if ( row < rows - 1 ) - { - /* lower left */ - if ( col > 0 && nextrow[col - 1] == PBM_WHITE ) - ++count; - /* lower center */ - if ( nextrow[col] == PBM_WHITE ) - ++count; - /* lower right */ - if ( col < cols - 1 && nextrow[col + 1] == PBM_WHITE ) - ++count; - } - - /* And compute the new value. */ - if ( thisrow[col] == PBM_WHITE ) - if ( count == 2 || count == 3 ) - newrow[col] = PBM_WHITE; - else - newrow[col] = PBM_BLACK; - else - if ( count == 3 ) - newrow[col] = PBM_WHITE; - else - newrow[col] = PBM_BLACK; - } - pbm_writepbmrow( stdout, newrow, cols, 0 ); - } - - pm_close( ifp ); - pm_close( stdout ); - - exit( 0 ); - } diff --git a/editor/pgmabel.c b/editor/pgmabel.c deleted file mode 100644 index 4914c4be..00000000 --- a/editor/pgmabel.c +++ /dev/null @@ -1,316 +0,0 @@ -/* pgmabel.c - read a portable graymap and making the deconvolution -** -** Deconvolution of an axial-symmetric image of an rotation symmetrical -** process by solving the linear equation system with y-Axis as -** symmetry-line -** -** Copyright (C) 1997-2006 by German Aerospace Research establishment -** -** Author: Volker Schmidt -** lefti@voyager.boerde.de -** -** 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. -** -** $HISTORY: -** -** 24 Jan 2002 : 001.009 : some optimzization -** 22 Jan 2002 : 001.008 : some stupid calculations changed -** 08 Aug 2001 : 001.007 : new usage (netpbm-conform) -** 27 Jul 1998 : 001.006 : First try of error correction -** 26 Mar 1998 : 001.005 : Calculating the dl's before transformation -** 06 Feb 1998 : 001.004 : Include of a logo in the upper left edge -** 26 Nov 1997 : 001.003 : Some bug fixes and reading only lines -** 25 Nov 1997 : 001.002 : include of pixsize for getting scale invariant -** 03 Sep 1997 : 001.001 : only define for PID2 -** 03 Sep 1997 : 001.000 : First public release -** 21 Aug 1997 : 000.909 : Recalculate the streching-factor -** 20 Aug 1997 : 000.908 : -left and -right for calculating only one side -** 20 Aug 1997 : 000.906 : correction of divisor, include of -factor -** 15 Aug 1997 : 000.905 : Include of -help and -axis -*/ - -static const char* const version="$VER: pgmabel 1.009 (24 Jan 2002)"; - -#include -#include /* for calloc */ -#include "pgm.h" -#include "mallocvar.h" - -#ifndef PID2 /* PI/2 (on AMIGA always defined) */ -#define PID2 1.57079632679489661923 -#endif - -#define TRUE 1 -#define FALSE 0 - -/* some global variables */ -static double *aldl, *ardl; /* pointer for weighting factors */ - -/* ---------------------------------------------------------------------------- -** procedure for calculating the sum of the calculated surfaces with the -** weight of the surface -** n <- index of end point of the summation -** N <- width of the calculated row -** xr <- array of the calculated elements of the row -** adl <- pre-calculated surface coefficient for each segment -*/ -static double -Sum ( int n, double *xr, int N, double *adl) -{ - int k; - double result=0.0; - - if (n==0) return(0.0); /* outer ring is 0 per definition */ - for (k=0 ; k<=(n-1) ; k++) - { - result += xr[k] * ( adl[k*N+n] - adl[(k+1)*N+n]); -/* result += xr[k] * ( dr(k,n+0.5,N) - dr(k+1,n+0.5,N)); */ - } - return(result); -} - -/* ---------------------------------------------------------------------------- -** procedure for calculating the surface coefficient for the Integration -** R, N <- indizes of the coefficient -** r <- radial position of the center of the surface -*/ -static double -dr ( int R, double r, int N) -{ - double a; - double b; - a=(double) N-R ; - b=(double) N-r ; - return(sqrt(a*a-b*b)); -} - -/* ---------------------------------------------------------------------------- -** procedure for making the Abel integration for deconvolution of the image -** y <-> array with values for deconvolution and results -** N <- width of the array -** adl <- array with pre-calculated weighting factors -*/ -static void -abel ( float *y, int N, double *adl) -{ - register int n; - double *rho, *rhop; /* results and new index */ - float *yp; /* new indizes for the y-array */ - - MALLOCARRAY(rho, N); - if( !rho ) - pm_error( "out of memory" ); - rhop = rho; - yp = y; - - for (n=0 ; n 2) rhop[n-1] = (rho[n-2]+rho[n-1]+rho[n])/3.0; stabilization*/ - } - for (n=0 ; n=1 )&&( n0?temp:0); - } - for ( col = midcol; col < cols; ++col ) /* right side */ - { - trow[cols-col-1] = (float) (grayorig[col]); - } - if ( right ) abel(trow,(cols-midcol),ardl); /* deconvolution */ - for ( col = midcol; col < cols; ++col) /* writing right side */ - { - temp = (int)(trow[cols-col-1]/r_div); - temp = (temp>0?temp:0); - grayrow[col] = temp; - } - pgm_writepgmrow( stdout, grayrow, cols, maxval, 0 ); /* saving row */ - } - pm_close( ifp ); - pm_close( stdout ); /* closing output */ - free( trow ); /* deconvolution is done, clear memory */ - pgm_freerow( grayorig ); - pgm_freerow( grayrow ); - free(aldl); - free(ardl); /* all used memory freed (i hope) */ - exit( 0 ); /* end of procedure */ -} - diff --git a/editor/pgmbentley.c b/editor/pgmbentley.c deleted file mode 100644 index aed92074..00000000 --- a/editor/pgmbentley.c +++ /dev/null @@ -1,74 +0,0 @@ -/* pgmbentley.c - read a portable graymap and smear it according to brightness -** -** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com) -** -** Permission to use, copy, modify, and distribute this software and its -** documentation for any purpose and without fee is hereby granted, provided -** that the above copyright notice appear in all copies and that both that -** copyright notice and this permission notice appear in supporting -** documentation. This software is provided "as is" without express or -** implied warranty. -*/ - -#include - -#include "pm_c_util.h" -#include "pgm.h" - - -static unsigned int const N = 4; - - -int -main(int argc, const char * argv[]) { - - FILE * ifP; - int rows, cols; - gray maxval; - gray ** gin; - gray ** gout; - unsigned int row; - const char * inputFileName; - - pm_proginit(&argc, argv); - - if (argc-1 < 1) - inputFileName = "-"; - else { - inputFileName = argv[1]; - - if (argc-1 > 1) - pm_error("There are no options and only one argument. " - "You specified %u", argc-1); - } - ifP = pm_openr(inputFileName); - - gin = pgm_readpgm(ifP, &cols, &rows, &maxval); - - pm_close(ifP); - - gout = pgm_allocarray(cols, rows); - - for (row = 0; row < rows; ++row) { - unsigned int col; - for (col = 0; col < cols; ++col) - gout[row][col] = 0; - } - - for (row = 0; row < rows; ++row) { - unsigned int col; - - for (col = 0; col < cols; ++col) { - unsigned int const brow = MIN(rows-1, row + gin[row][col] / N); - - gout[brow][col] = gin[row][col]; - } - } - - pgm_writepgm(stdout, gout, cols, rows, maxval, 0); - - pm_close(stdout); - pgm_freearray(gout, rows); - - return 0; -} diff --git a/editor/pgmmorphconv.c b/editor/pgmmorphconv.c deleted file mode 100644 index abc4e718..00000000 --- a/editor/pgmmorphconv.c +++ /dev/null @@ -1,253 +0,0 @@ -/* pgmmorphconv.c - morphological convolutions on a graymap: dilation and -** erosion -** -** Copyright (C) 2000 by Luuk van Dijk/Mind over Matter -** -** Based on -** pnmconvol.c - general MxN convolution on a portable anymap -** -** Copyright (C) 1989, 1991 by Jef Poskanzer. -** -** Permission to use, copy, modify, and distribute this software and its -** documentation for any purpose and without fee is hereby granted, provided -** that the above copyright notice appear in all copies and that both that -** copyright notice and this permission notice appear in supporting -** documentation. This software is provided "as is" without express or -** implied warranty. -*/ - -#include "pm_c_util.h" -#include "pgm.h" - - -/************************************************************ - * Dilate - ************************************************************/ - -static int -dilate( bit** template, int trowso2, int tcolso2, - gray** in_image, gray** out_image, - int rows, int cols ){ - - int c, r, tc, tr; - int templatecount; - gray source; - - for( c=0; c0)?0:-tr) ; r< ((tr>0)?(rows-tr):rows) ; ++r ){ - for( c= ((tc>0)?0:-tc) ; c< ((tc>0)?(cols-tc):cols) ; ++c ){ - source = in_image[r+tr][c+tc]; - out_image[r][c] = MAX(source, out_image[r][c]); - } /* for c */ - } /* for r */ - } /* for tr */ - } /* for tc */ - - return templatecount; - -} /* dilate */ - - - -/************************************************************ - * Erode: same as dilate except !!!! - ************************************************************/ - -static int -erode( bit** template, int trowso2, int tcolso2, - gray** in_image, gray** out_image, - int rows, int cols ){ - - int c, r, tc, tr; - int templatecount; - gray source; - - for( c=0; c0)?0:-tr) ; r< ((tr>0)?(rows-tr):rows) ; ++r ){ - for( c= ((tc>0)?0:-tc) ; c< ((tc>0)?(cols-tc):cols) ; ++c ){ - - source = in_image[r+tr][c+tc]; - out_image[r][c] = MIN(source, out_image[r][c]); - - } /* for c */ - } /* for r */ - - - - } /* for tr */ - } /* for tc */ - - return templatecount; - -} /* erode */ - - - -/************************************************************ - * Main - ************************************************************/ - - -int main( int argc, char* argv[] ){ - - int argn; - char operation; - const char* usage = "-dilate|-erode|-open|-close [pgmfile]"; - - FILE* tifp; /* template */ - int tcols, trows; - int tcolso2, trowso2; - bit** template; - - - FILE* ifp; /* input image */ - int cols, rows; - gray maxval; - - gray** in_image; - gray** out_image; - - int templatecount=0; - - pgm_init( &argc, argv ); - - /* - * parse arguments - */ - - ifp = stdin; - operation = 'd'; - - argn=1; - - if( argn == argc ) pm_usage( usage ); - - if( pm_keymatch( argv[argn], "-erode", 2 )) { operation='e'; argn++; } - else - if( pm_keymatch( argv[argn], "-dilate", 2 )) { operation='d'; argn++; } - else - if( pm_keymatch( argv[argn], "-open", 2 )) { operation='o'; argn++; } - else - if( pm_keymatch( argv[argn], "-close", 2 )) { operation='c'; argn++; } - - if( argn == argc ) pm_usage( usage ); - - tifp = pm_openr( argv[argn++] ); - - if( argn != argc ) ifp = pm_openr( argv[argn++] ); - - if( argn != argc ) pm_usage( usage ); - - - /* - * Read in the template matrix. - */ - - template = pbm_readpbm( tifp, &tcols, &trows ); - pm_close( tifp ); - - if( tcols % 2 != 1 || trows % 2 != 1 ) - pm_error("the template matrix must have an odd number of " - "rows and columns" ); - - /* the reason is that we want the middle pixel to be the origin */ - tcolso2 = tcols / 2; /* template coords run from -tcols/2 .. 0 .. +tcols/2 */ - trowso2 = trows / 2; - -#if 0 - fprintf(stderr, "template: %d x %d\n", trows, tcols); - fprintf(stderr, "half: %d x %d\n", trowso2, tcolso2); -#endif - - /* - * Read in the image - */ - - in_image = pgm_readpgm( ifp, &cols, &rows, &maxval); - - if( cols < tcols || rows < trows ) - pm_error("the image is smaller than the convolution matrix" ); - -#if 0 - fprintf(stderr, "image: %d x %d (%d)\n", rows, cols, maxval); -#endif - - /* - * Allocate output buffer and initialize with min or max value - */ - - out_image = pgm_allocarray( cols, rows ); - - if( operation == 'd' ){ - templatecount = dilate(template, trowso2, tcolso2, - in_image, out_image, rows, cols); - } - else if( operation == 'e' ){ - templatecount = erode(template, trowso2, tcolso2, - in_image, out_image, rows, cols); - } - else if( operation == 'o' ){ - gray ** eroded_image; - eroded_image = pgm_allocarray( cols, rows ); - templatecount = erode(template, trowso2, tcolso2, - in_image, eroded_image, rows, cols); - templatecount = dilate(template, trowso2, tcolso2, - eroded_image, out_image, rows, cols); - pgm_freearray( eroded_image, rows ); - } - else if( operation == 'c' ){ - gray ** dilated_image; - dilated_image = pgm_allocarray( cols, rows ); - templatecount = dilate(template, trowso2, tcolso2, - in_image, dilated_image, rows, cols); - templatecount = erode(template, trowso2, tcolso2, - dilated_image, out_image, rows, cols); - pgm_freearray( dilated_image, rows ); - } - - if(templatecount == 0 ) pm_error( "The template was empty!" ); - - pgm_writepgm( stdout, out_image, cols, rows, maxval, 1 ); - - pgm_freearray( out_image, rows ); - pgm_freearray( in_image, rows ); - pm_close( ifp ); - - exit( 0 ); - -} /* main */ - diff --git a/editor/pnmindex.c b/editor/pnmindex.c deleted file mode 100644 index 7b405ef3..00000000 --- a/editor/pnmindex.c +++ /dev/null @@ -1,639 +0,0 @@ -/*============================================================================ - pnmindex -============================================================================== - - build a visual index of a bunch of PNM images - - This used to be a C shell program, and then a BASH program. Neither - were portable enough, and the program is too complex for either of - those languages anyway, so now it's in C. - - By Bryan Henderson 2005.04.24. - - Contributed to the public domain by its author. - -============================================================================*/ - -#define _BSD_SOURCE /* Make sure strdup is in string.h */ - -#include -#include -#include -#include -#include - - -#include "pm_config.h" -#include "shhopt.h" -#include "mallocvar.h" -#include "nstring.h" -#include "pnm.h" - -struct cmdlineInfo { - /* All the information the user supplied in the command line, - in a form easy for the program to use. - */ - unsigned int inputFileCount; - const char ** inputFileName; - unsigned int size; - unsigned int across; - unsigned int colors; - unsigned int black; - unsigned int noquant; - const char * title; - unsigned int verbose; -}; - -static bool verbose; - - - -static void PM_GNU_PRINTF_ATTR(1,2) -systemf(const char * const fmt, - ...) { - - va_list varargs; - - size_t dryRunLen; - - va_start(varargs, fmt); - - vsnprintfN(NULL, 0, fmt, varargs, &dryRunLen); - - va_end(varargs); - - if (dryRunLen + 1 < dryRunLen) - /* arithmetic overflow */ - pm_error("Command way too long"); - else { - size_t const allocSize = dryRunLen + 1; - char * shellCommand; - shellCommand = malloc(allocSize); - if (shellCommand == NULL) - pm_error("Can't get storage for %u-character command", - allocSize); - else { - va_list varargs; - size_t realLen; - int rc; - - va_start(varargs, fmt); - - vsnprintfN(shellCommand, allocSize, fmt, varargs, &realLen); - - assert(realLen == dryRunLen); - va_end(varargs); - - if (verbose) - pm_message("shell cmd: %s", shellCommand); - - rc = system(shellCommand); - if (rc != 0) - pm_error("shell command '%s' failed. rc %d", - shellCommand, rc); - - strfree(shellCommand); - } - } -} - - - -static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { - - unsigned int option_def_index; - optEntry *option_def; - /* Instructions to optParseOptions3 on how to parse our options. - */ - optStruct3 opt; - - unsigned int quant; - unsigned int sizeSpec, colorsSpec, acrossSpec, titleSpec; - - MALLOCARRAY_NOFAIL(option_def, 100); - - option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "black", OPT_FLAG, NULL, - &cmdlineP->black, 0); - OPTENT3(0, "noquant", OPT_FLAG, NULL, - &cmdlineP->noquant, 0); - OPTENT3(0, "quant", OPT_FLAG, NULL, - &quant, 0); - OPTENT3(0, "verbose", OPT_FLAG, NULL, - &cmdlineP->verbose, 0); - OPTENT3(0, "size", OPT_UINT, &cmdlineP->size, - &sizeSpec, 0); - OPTENT3(0, "colors", OPT_UINT, &cmdlineP->colors, - &colorsSpec, 0); - OPTENT3(0, "across", OPT_UINT, &cmdlineP->across, - &acrossSpec, 0); - OPTENT3(0, "title", OPT_STRING, &cmdlineP->title, - &titleSpec, 0); - - opt.opt_table = option_def; - opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ - opt.allowNegNum = FALSE; - - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); - /* Uses and sets argc, argv, and some of *cmdline_p and others. */ - - if (quant && cmdlineP->noquant) - pm_error("You can't specify both -quant and -noquat"); - - if (!colorsSpec) - cmdlineP->colors = 256; - - if (!sizeSpec) - cmdlineP->size = 100; - - if (!acrossSpec) - cmdlineP->across = 6; - - if (!titleSpec) - cmdlineP->title = NULL; - - if (colorsSpec && cmdlineP->noquant) - pm_error("-colors doesn't make any sense with -noquant"); - - if (argc-1 < 1) - pm_error("You must name at least one file that contains an image " - "to go into the index"); - - cmdlineP->inputFileCount = argc-1; - - MALLOCARRAY_NOFAIL(cmdlineP->inputFileName, cmdlineP->inputFileCount); - - { - unsigned int i; - for (i = 0; i < cmdlineP->inputFileCount; ++i) { - cmdlineP->inputFileName[i] = strdup(argv[i+1]); - if (cmdlineP->inputFileName[i] == NULL) - pm_error("Unable to allocate memory for a file name"); - } - } -} - - - -static void -freeCmdline(struct cmdlineInfo const cmdline) { - - unsigned int i; - - for (i = 0; i < cmdline.inputFileCount; ++i) - strfree(cmdline.inputFileName[i]); - - free(cmdline.inputFileName); - -} - - - -static void -makeTempDir(const char ** const tempDirP) { - - const char * const tmpdir = getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp"; - - const char * mytmpdir; - int rc; - - asprintfN(&mytmpdir, "%s/pnmindex_%d", tmpdir, getpid()); - - rc = pm_mkdir(mytmpdir, 0700); - if (rc != 0) - pm_error("Unable to create temporary file directory '%s'. mkdir() " - "fails with errno %d (%s)", - mytmpdir, errno, strerror(errno)); - - *tempDirP = mytmpdir; -} - - - -static void -removeTempDir(const char * const tempDir) { - - int rc; - - rc = rmdir(tempDir); - if (rc != 0) - pm_error("Failed to remove temporary file directory '%s'. " - "rmdir() fails with errno %d (%s)", - tempDir, errno, strerror(errno)); -} - - -static const char * -rowFileName(const char * const dirName, - unsigned int const row) { - - const char * fileName; - - asprintfN(&fileName, "%s/pi.%u", dirName, row); - - return fileName; -} - - - -static void -makeTitle(const char * const title, - unsigned int const rowNumber, - bool const blackBackground, - const char * const tempDir) { - - const char * const invertStage = blackBackground ? "| pnminvert " : ""; - - const char * fileName; - - fileName = rowFileName(tempDir, rowNumber); - - /* This quoting is not adequate. We really should do this without - a shell at all. - */ - systemf("pbmtext \"%s\" " - "%s" - "> %s", - title, invertStage, fileName); - - strfree(fileName); -} - - - -static void -copyImage(const char * const inputFileName, - const char * const outputFileName) { - - systemf("cat %s > %s", inputFileName, outputFileName); -} - - - -static void -copyScaleQuantImage(const char * const inputFileName, - const char * const outputFileName, - int const format, - unsigned int const size, - unsigned int const quant, - unsigned int const colors) { - - const char * scaleCommand; - - switch (PNM_FORMAT_TYPE(format)) { - case PBM_TYPE: - asprintfN(&scaleCommand, - "pamscale -quiet -xysize %u %u %s " - "| pgmtopbm > %s", - size, size, inputFileName, outputFileName); - break; - - case PGM_TYPE: - asprintfN(&scaleCommand, - "pamscale -quiet -xysize %u %u %s >%s", - size, size, inputFileName, outputFileName); - break; - - case PPM_TYPE: - if (quant) - asprintfN(&scaleCommand, - "pamscale -quiet -xysize %u %u %s " - "| pnmquant -quiet %u > %s", - size, size, inputFileName, colors, outputFileName); - else - asprintfN(&scaleCommand, - "pamscale -quiet -xysize %u %u %s >%s", - size, size, inputFileName, outputFileName); - break; - default: - pm_error("Unrecognized Netpbm format: %d", format); - } - - systemf("%s", scaleCommand); - - strfree(scaleCommand); -} - - - -static int -formatTypeMax(int const typeA, - int const typeB) { - - if (typeA == PPM_TYPE || typeB == PPM_TYPE) - return PPM_TYPE; - else if (typeA == PGM_TYPE || typeB == PGM_TYPE) - return PGM_TYPE; - else - return PBM_TYPE; -} - - - -static const char * -thumbnailFileName(const char * const dirName, - unsigned int const row, - unsigned int const col) { - - const char * fileName; - - asprintfN(&fileName, "%s/pi.%u.%u", dirName, row, col); - - return fileName; -} - - - -static const char * -thumbnailFileList(const char * const dirName, - unsigned int const row, - unsigned int const cols) { - - unsigned int const maxListSize = 4096; - - char * list; - unsigned int col; - - list = malloc(maxListSize); - if (list == NULL) - pm_error("Unable to allocate %u bytes for file list", maxListSize); - - list[0] = '\0'; - - for (col = 0; col < cols; ++col) { - const char * const fileName = thumbnailFileName(dirName, row, col); - - if (strlen(list) + strlen(fileName) + 1 > maxListSize - 1) - pm_error("File name list too long for this program to handle."); - else { - strcat(list, " "); - strcat(list, fileName); - } - strfree(fileName); - } - - return list; -} - - - -static void -makeImageFile(const char * const thumbnailFileName, - const char * const inputFileName, - bool const blackBackground, - const char * const outputFileName) { - - const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; - const char * const invertStage = blackBackground ? "| pnminvert " : ""; - - systemf("pbmtext \"%s\" " - "%s" - "| pnmcat %s -topbottom %s - " - "> %s", - inputFileName, invertStage, blackWhiteOpt, - thumbnailFileName, outputFileName); -} - - - -static void -makeThumbnail(const char * const inputFileName, - unsigned int const size, - bool const black, - bool const quant, - unsigned int const colors, - const char * const tempDir, - unsigned int const row, - unsigned int const col, - int * const formatP) { - - FILE * ifP; - int imageCols, imageRows, format; - xelval maxval; - const char * tmpfile; - const char * fileName; - - ifP = pm_openr(inputFileName); - pnm_readpnminit(ifP, &imageCols, &imageRows, &maxval, &format); - pm_close(ifP); - - asprintfN(&tmpfile, "%s/pi.tmp", tempDir); - - if (imageCols < size && imageRows < size) - copyImage(inputFileName, tmpfile); - else - copyScaleQuantImage(inputFileName, tmpfile, format, - size, quant, colors); - - fileName = thumbnailFileName(tempDir, row, col); - - makeImageFile(tmpfile, inputFileName, black, fileName); - - unlink(tmpfile); - - strfree(fileName); - strfree(tmpfile); - - *formatP = format; -} - - - -static void -unlinkThumbnailFiles(const char * const dirName, - unsigned int const row, - unsigned int const cols) { - - unsigned int col; - - for (col = 0; col < cols; ++col) { - const char * const fileName = thumbnailFileName(dirName, row, col); - - unlink(fileName); - - strfree(fileName); - } -} - - - -static void -unlinkRowFiles(const char * const dirName, - unsigned int const rows) { - - unsigned int row; - - for (row = 0; row < rows; ++row) { - const char * const fileName = rowFileName(dirName, row); - - unlink(fileName); - - strfree(fileName); - } -} - - - -static void -combineIntoRowAndDelete(unsigned int const row, - unsigned int const cols, - int const maxFormatType, - bool const blackBackground, - bool const quant, - unsigned int const colors, - const char * const tempDir) { - - const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; - - const char * fileName; - const char * quantStage; - const char * fileList; - - fileName = rowFileName(tempDir, row); - - unlink(fileName); - - if (maxFormatType == PPM_TYPE && quant) - asprintfN(&quantStage, "| pnmquant -quiet %u ", colors); - else - quantStage = strdup(""); - - fileList = thumbnailFileList(tempDir, row, cols); - - systemf("pnmcat %s -leftright -jbottom %s " - "%s" - ">%s", - blackWhiteOpt, fileList, quantStage, fileName); - - strfree(fileList); - strfree(quantStage); - strfree(fileName); - - unlinkThumbnailFiles(tempDir, row, cols); -} - - - -static const char * -rowFileList(const char * const dirName, - unsigned int const rows) { - - unsigned int const maxListSize = 4096; - - unsigned int row; - char * list; - - list = malloc(maxListSize); - if (list == NULL) - pm_error("Unable to allocate %u bytes for file list", maxListSize); - - list[0] = '\0'; - - for (row = 0; row < rows; ++row) { - const char * const fileName = rowFileName(dirName, row); - - if (strlen(list) + strlen(fileName) + 1 > maxListSize - 1) - pm_error("File name list too long for this program to handle."); - - else { - strcat(list, " "); - strcat(list, fileName); - } - strfree(fileName); - } - - return list; -} - - - -static void -writeRowsAndDelete(unsigned int const rows, - int const maxFormatType, - bool const blackBackground, - bool const quant, - unsigned int const colors, - const char * const tempDir) { - - const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; - - const char * quantStage; - const char * fileList; - - if (maxFormatType == PPM_TYPE && quant) - asprintfN(&quantStage, "| pnmquant -quiet %u ", colors); - else - quantStage = strdup(""); - - fileList = rowFileList(tempDir, rows); - - systemf("pnmcat %s -topbottom %s %s", - blackWhiteOpt, fileList, quantStage); - - strfree(fileList); - strfree(quantStage); - - unlinkRowFiles(tempDir, rows); -} - - - -int -main(int argc, char *argv[]) { - struct cmdlineInfo cmdline; - const char * tempDir; - int maxFormatType; - unsigned int colsInRow; - unsigned int rowsDone; - unsigned int i; - - pnm_init(&argc, argv); - - parseCommandLine(argc, argv, &cmdline); - - verbose = cmdline.verbose; - - makeTempDir(&tempDir); - - maxFormatType = PBM_TYPE; - colsInRow = 0; - rowsDone = 0; - - if (cmdline.title) - makeTitle(cmdline.title, rowsDone++, cmdline.black, tempDir); - - for (i = 0; i < cmdline.inputFileCount; ++i) { - const char * const inputFileName = cmdline.inputFileName[i]; - - int format; - - makeThumbnail(inputFileName, cmdline.size, cmdline.black, - !cmdline.noquant, cmdline.colors, tempDir, - rowsDone, colsInRow, &format); - - maxFormatType = formatTypeMax(maxFormatType, PNM_FORMAT_TYPE(format)); - - ++colsInRow; - if (colsInRow >= cmdline.across || i == cmdline.inputFileCount-1) { - combineIntoRowAndDelete( - rowsDone, colsInRow, maxFormatType, - cmdline.black, !cmdline.noquant, cmdline.colors, - tempDir); - ++rowsDone; - colsInRow = 0; - } - } - - writeRowsAndDelete(rowsDone, maxFormatType, cmdline.black, - !cmdline.noquant, cmdline.colors, tempDir); - - removeTempDir(tempDir); - - freeCmdline(cmdline); - - pm_close(stdout); - - return 0; -} diff --git a/editor/ppm3d.c b/editor/ppm3d.c deleted file mode 100644 index 6f317a0b..00000000 --- a/editor/ppm3d.c +++ /dev/null @@ -1,307 +0,0 @@ -/*============================================================================= - ppmto3d -=============================================================================== - This program converts two PPM images into an anaglyph stereogram image PPM. - (for viewing with red/blue 3D glasses). - -=============================================================================*/ - -#include - -#include "shhopt.h" -#include "mallocvar.h" -#include "ppm.h" -#include "lum.h" - - - -struct cmdlineInfo { - /* All the information the user supplied in the command line, - in a form easy for the program to use. - */ - const char * leftInputFileName; /* '-' if stdin */ - const char * rghtInputFileName; /* '-' if stdin */ - int offset; - unsigned int color; -}; - - - -static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { -/*---------------------------------------------------------------------------- - parse program command line described in Unix standard form by argc - and argv. Return the information in the options as *cmdlineP. - - If command line is internally inconsistent (invalid options, etc.), - issue error message to stderr and abort program. - - Note that the strings we return are stored in the storage that - was passed to us as the argv array. We also trash *argv. ------------------------------------------------------------------------------*/ - optEntry * option_def; - /* Instructions to optParseOptions3 on how to parse our options. - */ - optStruct3 opt; - - unsigned int option_def_index; - unsigned int offsetSpec; - const char * offsetArg; - - MALLOCARRAY_NOFAIL(option_def, 100); - - option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "color", OPT_FLAG, NULL, - &cmdlineP->color, 0); - OPTENT3(0, "offset", OPT_INT, &cmdlineP->offset, - &offsetSpec, 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); - /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - - if (argc-1 < 2) - pm_error("You must specify at least two arguments: left and right " - "input file names. You specified %u", argc-1); - else { - cmdlineP->leftInputFileName = argv[1]; - cmdlineP->rghtInputFileName = argv[2]; - - if (argc-1 > 2) { - offsetArg = argv[3]; - - if (argc-1 > 3) - pm_error("Program takes at most 3 arguments: left and " - "right input file names and offset. " - "You specified %u", argc-1); - } else - offsetArg = NULL; - } - - if (offsetArg && offsetSpec) - pm_error("You cannot specify both -offset and the offset " - "argument (i.e. with -offset, there is at most " - "two arguments: left and right input file names"); - else if (!offsetArg && !offsetSpec) - cmdlineP->offset = 0; - else if (offsetArg) - cmdlineP->offset = atoi(offsetArg); -} - - - -static void -computeGrayscaleRow(const pixel * const inputRow, - gray * const outputRow, - pixval const maxval, - unsigned int const cols) { - - if (maxval <= 255) { - unsigned int col; - /* Use fast approximation to 0.299 r + 0.587 g + 0.114 b. */ - for (col = 0; col < cols; ++col) - outputRow[col] = ppm_fastlumin(inputRow[col]); - } else { - unsigned int col; - /* Can't use fast approximation, so fall back on floats. */ - for (col = 0; col < cols; ++col) - outputRow[col] = PPM_LUMIN(inputRow[col]) + 0.5; - } -} - - - -static void -compute3dRowMono(gray * const lGrayrow, - gray * const rGrayrow, - pixel * const pixelrow, - unsigned int const cols, - int const offset) { - - unsigned int col; - gray * lgP; - gray * rgP; - pixel * pP; - - assert(abs(offset) <= cols); - - for (col = 0, pP = pixelrow, lgP = lGrayrow, rgP = rGrayrow; - col < cols + offset; - ++col) { - - if ((int)col < offset/2) - ++lgP; - else if ((int)col < offset) { - PPM_ASSIGN(*pP, 0, *lgP, *lgP); - ++lgP; - ++pP; - } else if (col < cols) { - PPM_ASSIGN(*pP, *rgP, *lgP, *lgP); - ++lgP; - ++rgP; - ++pP; - } else if (col < cols + offset/2) { - PPM_ASSIGN(*pP, *rgP, 0, 0); - ++rgP; - ++pP; - } else { - assert(col < cols + offset); - ++rgP; - } - } -} - - - -static void -compute3dRowColor(pixel * const lPixelrow, - pixel * const rPixelrow, - pixel * const pixelrow, - unsigned int const cols, - unsigned int const offset) { - - unsigned int col; - pixel * lP; - pixel * rP; - pixel * pP; - - assert(abs(offset) <= cols); - - for (col = 0, pP = pixelrow, lP = lPixelrow, rP = rPixelrow; - col < cols + offset; - ++col) { - - if ((int)col < offset/2) - ++lP; - else if ((int)col < offset) { - PPM_ASSIGN(*pP, 0, PPM_GETG(*lP), PPM_GETB(*lP)); - ++lP; - ++pP; - } else if (col < cols) { - PPM_ASSIGN(*pP, PPM_GETR(*rP), PPM_GETG(*lP), PPM_GETB(*lP)); - ++lP; - ++rP; - ++pP; - } else if (col < cols + offset/2) { - PPM_ASSIGN(*pP, PPM_GETR(*rP), 0, 0); - ++rP; - ++pP; - } else { - assert(col < cols + offset); - ++rP; - } - } -} - - - -static void -write3dRaster(FILE * const ofP, - FILE * const lIfP, - FILE * const rIfP, - unsigned int const cols, - unsigned int const rows, - pixval const maxval, - int const lFormat, - int const rFormat, - int const offset, - bool const color) { - - pixel * lPixelrow; - gray * lGrayrow; - pixel * rPixelrow; - gray * rGrayrow; - pixel * pixelrow; - - unsigned int row; - - assert(abs(offset) < cols); - - lPixelrow = ppm_allocrow (cols); - lGrayrow = pgm_allocrow (cols); - rPixelrow = ppm_allocrow (cols); - rGrayrow = pgm_allocrow (cols); - pixelrow = ppm_allocrow (cols); - - for (row = 0; row < rows; ++row) { - ppm_readppmrow(lIfP, lPixelrow, cols, maxval, lFormat); - ppm_readppmrow(rIfP, rPixelrow, cols, maxval, rFormat); - - computeGrayscaleRow(lPixelrow, lGrayrow, maxval, cols); - computeGrayscaleRow(rPixelrow, rGrayrow, maxval, cols); - - if (color) - compute3dRowColor(lPixelrow, rPixelrow, pixelrow, cols, offset); - else - compute3dRowMono(lGrayrow, rGrayrow, pixelrow, cols, offset); - - ppm_writeppmrow(ofP, pixelrow, cols, maxval, 0); - } - - ppm_freerow(pixelrow); - pgm_freerow(rGrayrow); - ppm_freerow(rPixelrow); - pgm_freerow(lGrayrow); - ppm_freerow(lPixelrow); -} - - - -int -main(int argc, char *argv[]) { - - struct cmdlineInfo cmdline; - FILE * lIfP; - FILE * rIfP; - - int cols, rows; - pixval maxval; - - int lRows, lCols; - int lFormat; - pixval lMaxval; - - int rRows, rCols; - int rFormat; - pixval rMaxval; - - ppm_init(&argc, argv); - - parseCommandLine(argc, argv, &cmdline); - - lIfP = pm_openr(cmdline.leftInputFileName); - rIfP = pm_openr(cmdline.rghtInputFileName); - - ppm_readppminit(lIfP, &lCols, &lRows, &lMaxval, &lFormat); - ppm_readppminit(rIfP, &rCols, &rRows, &rMaxval, &rFormat); - - if ((lCols != rCols) || (lRows != rRows) || - (lMaxval != rMaxval) || - (PPM_FORMAT_TYPE(lFormat) != PPM_FORMAT_TYPE(rFormat))) - pm_error ("Pictures are not of same size and format"); - - cols = lCols; - rows = lRows; - maxval = lMaxval; - - if (abs(cmdline.offset) >= cols) - pm_error("Magnitude of -offset (%u columns) is not less than " - "width of images " - "(%u columns)", abs(cmdline.offset), cols); - - ppm_writeppminit(stdout, cols, rows, maxval, 0); - - write3dRaster(stdout, lIfP, rIfP, cols, rows, maxval, - lFormat, rFormat, cmdline.offset, cmdline.color); - - pm_close(lIfP); - pm_close(rIfP); - pm_close(stdout); - - return 0; -} - diff --git a/editor/ppmglobe.c b/editor/ppmglobe.c deleted file mode 100644 index ee1a57c3..00000000 --- a/editor/ppmglobe.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * This code written 2003 - * by Max Gensthaler - * Distributed under the Gnu Public License (GPL) - * - * Gensthaler called it 'ppmglobemap'. - * - * Translations of comments and C dialect by Bryan Henderson May 2003. - */ - - -#define _XOPEN_SOURCE /* get M_PI in math.h */ -#include -#include -#include -#include - -#include "ppm.h" -#include "colorname.h" -#include "shhopt.h" -#include "mallocvar.h" - - -struct cmdlineInfo { - /* All the information the user supplied in the command line, - in a form easy for the program to use. - */ - const char * inputFileName; /* Filename of input files */ - unsigned int stripcount; - const char * background; - unsigned int closeok; -}; - - - -static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { -/*---------------------------------------------------------------------------- - Note that the file spec array we return is stored in the storage that - was passed to us as the argv array. ------------------------------------------------------------------------------*/ - optEntry *option_def; - /* Instructions to optParseOptions3 on how to parse our options. - */ - optStruct3 opt; - - unsigned int option_def_index; - - unsigned int backgroundSpec; - - MALLOCARRAY_NOFAIL(option_def, 100); - - option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "background", OPT_STRING, &cmdlineP->background, - &backgroundSpec, 0); - OPTENT3(0, "closeok", OPT_FLAG, NULL, - &cmdlineP->closeok, 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); - /* Uses and sets argc, argv, and some of *cmdlineP and others. */ - - if (!backgroundSpec) - cmdlineP->background = NULL; - - if (argc - 1 < 1) - pm_error("You must specify at least one argument: the strip count"); - else { - int const stripcount = atoi(argv[1]); - if (stripcount <= 0) - pm_error("The strip count must be positive. You specified %d", - stripcount); - - cmdlineP->stripcount = stripcount; - - if (argc-1 < 2) - cmdlineP->inputFileName = "-"; - else - cmdlineP->inputFileName = argv[2]; - - if (argc - 1 > 2) - pm_error("There are at most two arguments: strip count " - "and input file name. " - "You specified %u", argc-1); - } -} - - - -int -main(int argc, char *argv[]) { - - struct cmdlineInfo cmdline; - FILE * ifP; - pixel ** srcPixels; - pixel ** dstPixels; - int srcCols, srcRows; - unsigned int dstCols, dstRows; - pixval srcMaxval, dstMaxval; - unsigned int stripWidth; - /* Width in pixels of each strip. In the output image, this means - the rectangular strip in which the lens-shaped foreground strip - is placed.. - */ - unsigned int row; - pixel backgroundColor; - - ppm_init(&argc, argv); - - parseCommandLine(argc, argv, &cmdline); - - ifP = pm_openr(cmdline.inputFileName); - - srcPixels = ppm_readppm(ifP, &srcCols, &srcRows, &srcMaxval); - - pm_close(ifP); - - stripWidth = srcCols / cmdline.stripcount; - - if (stripWidth < 1) - pm_error("You asked for %u strips, but the image is only " - "%u pixels wide, so that is impossible.", - cmdline.stripcount, srcCols); - - dstCols = stripWidth * cmdline.stripcount; - dstRows = srcRows; - dstMaxval = srcMaxval; - - if (cmdline.background == NULL) - PPM_ASSIGN(backgroundColor, 0, 0, 0); - else - pm_parse_dictionary_name(cmdline.background, - dstMaxval, cmdline.closeok, - &backgroundColor); - - dstPixels = ppm_allocarray(dstCols, dstRows); - - for (row = 0; row < dstRows; ++row) { - double const factor = sin(M_PI * row / dstRows); - /* Amount by which we squeeze the foreground image of each - strip in this row. - */ - int const stripBorder = (int)((stripWidth*(1.0-factor)/2.0) + 0.5); - /* Distance from the edge (either one) of a strip to the - foreground image within that strip -- i.e. number of pixels - of background color, which User will cut out with scissors - after he prints the image. - */ - unsigned int dstCol; - - for (dstCol = 0; dstCol < dstCols; ++dstCol) { - if (dstCol % stripWidth < stripBorder - || dstCol % stripWidth >= stripWidth - stripBorder) - dstPixels[row][dstCol] = backgroundColor; - else { - unsigned int const leftEdge = - (dstCol / stripWidth) * stripWidth; - unsigned int const srcCol = leftEdge + - (int)((dstCol % stripWidth - stripBorder) / factor + 0.5); - dstPixels[row][dstCol] = srcPixels[row][srcCol]; - } - } - } - - ppm_writeppm(stdout, dstPixels, dstCols, dstRows, dstMaxval, 0); - - return 0; -} diff --git a/editor/ppmntsc.c b/editor/ppmntsc.c deleted file mode 100644 index b9f2ac2f..00000000 --- a/editor/ppmntsc.c +++ /dev/null @@ -1,499 +0,0 @@ -/* This is ppmntsc.c, a program to adjust saturation values in an image - so they are legal for NTSC or PAL. - - It is derived from the program rlelegal.c, dated June 5, 1995, - which is described below and propagates that program's copyright. - The derivation was done by Bryan Henderson on 2000.04.21 to convert - it from operating on the RLE format to operating on the PPM format - and to rewrite it in a cleaner style, taking advantage of modern C - compiler technology. -*/ - - -/* - * This software is copyrighted as noted below. It may be freely copied, - * modified, and redistributed, provided that the copyright notice is - * preserved on all copies. - * - * There is no warranty or other guarantee of fitness for this software, - * it is provided solely "as is". Bug reports or fixes may be sent - * to the author, who may or may not act on them as he desires. - * - * You may not include this software in a program or other software product - * without supplying the source, or without informing the end-user that the - * source is available for no extra charge. - * - * If you modify this software, you should include a notice giving the - * name of the person performing the modification, the date of modification, - * and the reason for such modification. - */ - -/* - * rlelegal.c - Make RGB colors legal in the YIQ or YUV color systems. - * - * Author: Wes Barris - * Minnesota Supercomputer Center, Inc. - * Date: Fri Oct 15, 1993 - * @Copyright, Research Equipment Inc., d/b/a Minnesota Supercomputer - * Center, Inc., 1993 - - */ - -#define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ -#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ - -#include -#include -#include -#include "ppm.h" -#include "mallocvar.h" -#include "shhopt.h" - -#define TRUE 1 -#define FALSE 0 - -enum legalize {RAISE_SAT, LOWER_SAT, ALREADY_LEGAL}; - /* The actions that make a legal pixel */ - -struct cmdlineInfo { - /* All the information the user supplied in the command line, - in a form easy for the program to use. - */ - const char * inputFilename; - unsigned int verbose; - unsigned int debug; - unsigned int pal; - enum {ALL, LEGAL_ONLY, ILLEGAL_ONLY, CORRECTED_ONLY} output; -}; - - - - -static void -rgbtoyiq(const int r, const int g, const int b, - double * const y_p, - double * const i_p, - double * const q_p) { - - *y_p = .299*(r/255.0) + .587*(g/255.0) + .114*(b/255.0); - *i_p = .596*(r/255.0) - .274*(g/255.0) - .322*(b/255.0); - *q_p = .211*(r/255.0) - .523*(g/255.0) + .312*(b/255.0); -} - - - -static void -yiqtorgb(const double y, const double i, const double q, - int * const r_p, int * const g_p, int * const b_p) { - *r_p = 255.0*(1.00*y + .9562*i + .6214*q); - *g_p = 255.0*(1.00*y - .2727*i - .6468*q); - *b_p = 255.0*(1.00*y -1.1037*i +1.7006*q); -} - - - -static void -rgbtoyuv(const int r, const int g, const int b, - double * const y_p, - double * const u_p, - double * const v_p) { - *y_p = .299*(r/255.0) + .587*(g/255.0) + .114*(b/255.0); - *u_p = -.147*(r/255.0) - .289*(g/255.0) + .437*(b/255.0); - *v_p = .615*(r/255.0) - .515*(g/255.0) - .100*(b/255.0); -} - - - -static void -yuvtorgb(const double y, const double u, const double v, - int * const r_p, int * const g_p, int * const b_p) { - - *r_p = 255.0*(1.00*y + .0000*u +1.1398*v); - *g_p = 255.0*(1.00*y - .3938*u - .5805*v); - *b_p = 255.0*(1.00*y +2.0279*u + .0000*v); -} - - - -static void -make_legal_yiq(const double y, const double i, const double q, - double * const y_new_p, - double * const i_new_p, - double * const q_new_p, - enum legalize * const action_p - ) { - - double sat_old, sat_new; - /* - * I and Q are legs of a right triangle. Saturation is the hypotenuse. - */ - sat_old = sqrt(i*i + q*q); - if (y+sat_old > 1.0) { - const double diff = 0.5*((y+sat_old) - 1.0); - *y_new_p = y - diff; - sat_new = 1.0 - *y_new_p; - *i_new_p = i*(sat_new/sat_old); - *q_new_p = q*(sat_new/sat_old); - *action_p = LOWER_SAT; - } else if (y-sat_old <= -0.251) { - const double diff = 0.5*((sat_old-y) - 0.251); - *y_new_p = y + diff; - sat_new = 0.250 + *y_new_p; - *i_new_p = i*(sat_new/sat_old); - *q_new_p = q*(sat_new/sat_old); - *action_p = RAISE_SAT; - } else { - *y_new_p = y; - *i_new_p = i; - *q_new_p = q; - *action_p = ALREADY_LEGAL; - } - return; -} - - - -static void -make_legal_yuv(const double y, const double u, const double v, - double * const y_new_p, - double * const u_new_p, - double * const v_new_p, - enum legalize * const action_p - ) { - - double sat_old, sat_new; - /* - * U and V are legs of a right triangle. Saturation is the hypotenuse. - */ - sat_old = sqrt(u*u + v*v); - if (y+sat_old >= 1.334) { - const double diff = 0.5*((y+sat_old) - 1.334); - *y_new_p = y - diff; - sat_new = 1.333 - *y_new_p; - *u_new_p = u*(sat_new/sat_old); - *v_new_p = v*(sat_new/sat_old); - *action_p = LOWER_SAT; - } else if (y-sat_old <= -0.339) { - const double diff = 0.5*((sat_old-y) - 0.339); - *y_new_p = y + diff; - sat_new = 0.338 + *y_new_p; - *u_new_p = u*(sat_new/sat_old); - *v_new_p = v*(sat_new/sat_old); - *action_p = RAISE_SAT; - } else { - *u_new_p = u; - *v_new_p = v; - *action_p = ALREADY_LEGAL; - } - return; -} - - - -static void -make_legal_yiq_i(const int r_in, const int g_in, const int b_in, - int * const r_out_p, - int * const g_out_p, - int * const b_out_p, - enum legalize * const action_p - ) { - - double y, i, q; - double y_new, i_new, q_new; - /* - * Convert to YIQ and compute the new saturation. - */ - rgbtoyiq(r_in, g_in, b_in, &y, &i, &q); - make_legal_yiq(y, i, q, &y_new, &i_new, &q_new, action_p); - if (*action_p != ALREADY_LEGAL) - /* - * Given the new I and Q, compute new RGB values. - */ - yiqtorgb(y_new, i_new, q_new, r_out_p, g_out_p, b_out_p); - else { - *r_out_p = r_in; - *g_out_p = g_in; - *b_out_p = b_in; - } - return; -} - - - -static void -make_legal_yuv_i(const int r_in, const int g_in, const int b_in, - int * const r_out_p, - int * const g_out_p, - int * const b_out_p, - enum legalize * const action_p - ){ - - double y, u, v; - double y_new, u_new, v_new; - /* - * Convert to YUV and compute the new saturation. - */ - rgbtoyuv(r_in, g_in, b_in, &y, &u, &v); - make_legal_yuv(y, u, v, &y_new, &u_new, &v_new, action_p); - if (*action_p != ALREADY_LEGAL) - /* - * Given the new U and V, compute new RGB values. - */ - yuvtorgb(y_new, u_new, v_new, r_out_p, g_out_p, b_out_p); - else { - *r_out_p = r_in; - *g_out_p = g_in; - *b_out_p = b_in; - } - return; -} - - - -static void -make_legal_yiq_b(const pixel input, - pixel * const output_p, - enum legalize * const action_p) { - - - int ir_in, ig_in, ib_in; - int ir_out, ig_out, ib_out; - - ir_in = (int)PPM_GETR(input); - ig_in = (int)PPM_GETG(input); - ib_in = (int)PPM_GETB(input); - - make_legal_yiq_i(ir_in, ig_in, ib_in, &ir_out, &ig_out, &ib_out, action_p); - - PPM_ASSIGN(*output_p, ir_out, ig_out, ib_out); - - return; -} - - - -static void -make_legal_yuv_b(const pixel input, - pixel * const output_p, - enum legalize * const action_p) { - - int ir_in, ig_in, ib_in; - int ir_out, ig_out, ib_out; - - ir_in = (int)PPM_GETR(input); - ig_in = (int)PPM_GETG(input); - ib_in = (int)PPM_GETB(input); - make_legal_yuv_i(ir_in, ig_in, ib_in, &ir_out, &ig_out, &ib_out, action_p); - - PPM_ASSIGN(*output_p, ir_out, ig_out, ib_out); - - return; -} - - - -static void -report_mapping(const pixel old_pixel, const pixel new_pixel) { -/*---------------------------------------------------------------------------- - Assuming old_pixel and new_pixel are input and output pixels, - tell the user that we changed a pixel to make it legal, if in fact we - did and it isn't the same change that we just reported. ------------------------------------------------------------------------------*/ - static pixel last_changed_pixel; - static int first_time = TRUE; - - if (!PPM_EQUAL(old_pixel, new_pixel) && - (first_time || PPM_EQUAL(old_pixel, last_changed_pixel))) { - pm_message("Mapping %d %d %d -> %d %d %d\n", - PPM_GETR(old_pixel), - PPM_GETG(old_pixel), - PPM_GETB(old_pixel), - PPM_GETR(new_pixel), - PPM_GETG(new_pixel), - PPM_GETB(new_pixel) - ); - - last_changed_pixel = old_pixel; - first_time = FALSE; - } -} - - - -static void -convert_one_image(FILE * const ifp, struct cmdlineInfo const cmdline, - bool * const eofP, - int * const hicountP, int * const locountP) { - - /* Parameters of input image: */ - int rows, cols; - pixval maxval; - int format; - - ppm_readppminit(ifp, &cols, &rows, &maxval, &format); - ppm_writeppminit(stdout, cols, rows, maxval, FALSE); - { - pixel* const input_row = ppm_allocrow(cols); - pixel* const output_row = ppm_allocrow(cols); - pixel last_illegal_pixel; - /* Value of the illegal pixel we most recently processed */ - pixel black; - /* A constant - black pixel */ - - PPM_ASSIGN(black, 0, 0, 0); - - PPM_ASSIGN(last_illegal_pixel, 0, 0, 0); /* initial value */ - { - int row; - - *hicountP = 0; *locountP = 0; /* initial values */ - - for (row = 0; row < rows; ++row) { - int col; - ppm_readppmrow(ifp, input_row, cols, maxval, format); - for (col = 0; col < cols; ++col) { - pixel corrected; - /* Corrected or would-be corrected value for pixel */ - enum legalize action; - /* What action was used to make pixel legal */ - if (cmdline.pal) - make_legal_yuv_b(input_row[col], - &corrected, - &action); - else - make_legal_yiq_b(input_row[col], - &corrected, - &action); - - if (action == LOWER_SAT) - (*hicountP)++; - if (action == RAISE_SAT) - (*locountP)++; - if (cmdline.debug) report_mapping(input_row[col], - corrected); - switch (cmdline.output) { - case ALL: - output_row[col] = corrected; - break; - case LEGAL_ONLY: - output_row[col] = (action == ALREADY_LEGAL) ? - input_row[col] : black; - break; - case ILLEGAL_ONLY: - output_row[col] = (action != ALREADY_LEGAL) ? - input_row[col] : black; - break; - case CORRECTED_ONLY: - output_row[col] = (action != ALREADY_LEGAL) ? - corrected : black; - break; - } - } - ppm_writeppmrow(stdout, output_row, cols, maxval, FALSE); - } - } - ppm_freerow(output_row); - ppm_freerow(input_row); - } -} - - -static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { -/*---------------------------------------------------------------------------- - Note that many of the strings that this function returns in the - *cmdlineP structure are actually in the supplied argv array. And - sometimes, one of these strings is actually just a suffix of an entry - in argv! ------------------------------------------------------------------------------*/ - optStruct3 opt; - optEntry *option_def; - /* Instructions to OptParseOptions on how to parse our options. - */ - unsigned int option_def_index; - unsigned int legalonly, illegalonly, correctedonly; - - MALLOCARRAY(option_def, 100); - - option_def_index = 0; /* incremented by OPTENTRY */ - OPTENT3('v', "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); - OPTENT3('V', "debug", OPT_FLAG, NULL, &cmdlineP->debug, 0); - OPTENT3('p', "pal", OPT_FLAG, NULL, &cmdlineP->pal, 0); - OPTENT3('l', "legalonly", OPT_FLAG, NULL, &legalonly, 0); - OPTENT3('i', "illegalonly", OPT_FLAG, NULL, &illegalonly, 0); - OPTENT3('c', "correctedonly", OPT_FLAG, NULL, &correctedonly, 0); - - opt.opt_table = option_def; - opt.short_allowed = TRUE; - opt.allowNegNum = FALSE; - - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); - - if (argc - 1 == 0) - cmdlineP->inputFilename = "-"; /* he wants stdin */ - else if (argc - 1 == 1) - cmdlineP->inputFilename = argv[1]; - else - pm_error("Too many arguments. The only arguments accepted " - "are the mask color and optional input file specification"); - - if (legalonly + illegalonly + correctedonly > 1) - pm_error("--legalonly, --illegalonly, and --correctedonly are " - "conflicting options. Specify at most one of these."); - - if (legalonly) - cmdlineP->output = LEGAL_ONLY; - else if (illegalonly) - cmdlineP->output = ILLEGAL_ONLY; - else if (correctedonly) - cmdlineP->output = CORRECTED_ONLY; - else - cmdlineP->output = ALL; -} - - - -int -main(int argc, char **argv) { - - struct cmdlineInfo cmdline; - FILE * ifP; - int total_hicount, total_locount; - int image_count; - - bool eof; - - ppm_init(&argc, argv); - - parseCommandLine(argc, argv, &cmdline); - - ifP = pm_openr(cmdline.inputFilename); - - image_count = 0; /* initial value */ - total_hicount = 0; /* initial value */ - total_locount = 0; /* initial value */ - - eof = FALSE; - while (!eof) { - int hicount, locount; - convert_one_image(ifP, cmdline, &eof, &hicount, &locount); - image_count++; - total_hicount += hicount; - total_locount += locount; - ppm_nextimage(ifP, &eof); - } - - - if (cmdline.verbose) { - pm_message("%d images processed.", image_count); - pm_message("%d pixels were above the saturation limit.", - total_hicount); - pm_message("%d pixels were below the saturation limit.", - total_locount); - } - - pm_close(ifP); - - return 0; -} diff --git a/editor/ppmrelief.c b/editor/ppmrelief.c deleted file mode 100644 index 5e0669c3..00000000 --- a/editor/ppmrelief.c +++ /dev/null @@ -1,90 +0,0 @@ -/* ppmrelief.c - generate a relief map of a portable pixmap -** -** Copyright (C) 1990 by Wilson H. Bent, Jr. -** -** Permission to use, copy, modify, and distribute this software and its -** documentation for any purpose and without fee is hereby granted, provided -** that the above copyright notice appear in all copies and that both that -** copyright notice and this permission notice appear in supporting -** documentation. This software is provided "as is" without express or -** implied warranty. -*/ - -#include -#include "ppm.h" - -int -main(int argc, char * argv[]) { - - FILE* ifp; - pixel** inputbuf; - pixel* outputrow; - int argn, rows, cols, format, row; - register int col; - pixval maxval, mv2; - const char* const usage = "[ppmfile]"; - - ppm_init( &argc, argv ); - - argn = 1; - - if ( argn != argc ) { - ifp = pm_openr( argv[argn] ); - ++argn; - } else - ifp = stdin; - - if ( argn != argc ) - pm_usage( usage ); - - ppm_readppminit( ifp, &cols, &rows, &maxval, &format ); - mv2 = maxval / 2; - - /* Allocate space for 3 input rows, plus an output row. */ - inputbuf = ppm_allocarray( cols, 3 ); - outputrow = ppm_allocrow( cols ); - - ppm_writeppminit( stdout, cols, rows, maxval, 0 ); - - /* Read in the first two rows. */ - ppm_readppmrow( ifp, inputbuf[0], cols, maxval, format ); - ppm_readppmrow( ifp, inputbuf[1], cols, maxval, format ); - - /* Write out the first row, all zeros. */ - for ( col = 0; col < cols; ++col ) - PPM_ASSIGN( outputrow[col], 0, 0, 0 ); - ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 ); - - /* Now the rest of the image - read in the 3rd row of inputbuf, - ** and convolve with the first row into the output buffer. - */ - for ( row = 2 ; row < rows; ++row ) { - pixval r, g, b; - int rowa, rowb; - - rowa = row % 3; - rowb = (row + 2) % 3; - ppm_readppmrow( ifp, inputbuf[rowa], cols, maxval, format ); - - for ( col = 0; col < cols - 2; ++col ) { - r = PPM_GETR( inputbuf[rowa][col] ) + - ( mv2 - PPM_GETR( inputbuf[rowb][col + 2] ) ); - g = PPM_GETG( inputbuf[rowa][col] ) + - ( mv2 - PPM_GETG( inputbuf[rowb][col + 2] ) ); - b = PPM_GETB( inputbuf[rowa][col] ) + - ( mv2 - PPM_GETB( inputbuf[rowb][col + 2] ) ); - PPM_ASSIGN( outputrow[col + 1], r, g, b ); - } - ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 ); - } - - /* And write the last row, zeros again. */ - for ( col = 0; col < cols; ++col ) - PPM_ASSIGN( outputrow[col], 0, 0, 0 ); - ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 ); - - pm_close( ifp ); - pm_close( stdout ); - - exit( 0 ); -} diff --git a/editor/ppmshift.c b/editor/ppmshift.c deleted file mode 100644 index a765daa5..00000000 --- a/editor/ppmshift.c +++ /dev/null @@ -1,132 +0,0 @@ - -/*********************************************************************/ -/* ppmshift - shift lines of a picture left or right by x pixels */ -/* Frank Neumann, October 1993 */ -/* V1.1 16.11.1993 */ -/* */ -/* version history: */ -/* V1.0 11.10.1993 first version */ -/* V1.1 16.11.1993 Rewritten to be NetPBM.programming conforming */ -/*********************************************************************/ - -#include "ppm.h" - -/**************************/ -/* start of main function */ -/**************************/ -int -main(int argc, - char * argv[]) { - - FILE * ifP; - unsigned int row; - int argn, rows, cols, format; - pixel * srcrow; - pixel * destrow; - pixval maxval; - int shift, nowshift; - int shiftArg; - - const char * const usage = "shift [ppmfile]\n shift: maximum number of pixels to shift a line by\n"; - - /* parse in 'default' parameters */ - ppm_init(&argc, argv); - - argn = 1; - - /* parse in shift number */ - if (argn == argc) - pm_usage(usage); - if (sscanf(argv[argn], "%d", &shiftArg) != 1) - pm_usage(usage); - if (shiftArg < 0) - pm_error("shift factor must be 0 or more"); - ++argn; - - /* parse in filename (if present, stdin otherwise) */ - if (argn != argc) - { - ifP = pm_openr(argv[argn]); - ++argn; - } - else - ifP = stdin; - - if (argn != argc) - pm_usage(usage); - - /* read first data from file */ - ppm_readppminit(ifP, &cols, &rows, &maxval, &format); - - if (shiftArg > cols) { - shift = cols; - pm_message("shift amount is larger than picture width - reset to %d", - shift); - } else - shift = shiftArg; - - srcrow = ppm_allocrow(cols); - - destrow = ppm_allocrow(cols); - - ppm_writeppminit(stdout, cols, rows, maxval, 0); - - srand(pm_randseed()); - - /** now do the shifting **/ - /* the range by which a line is shifted lays in the range from */ - /* -shift/2 .. +shift/2 pixels; however, within this range it is */ - /* randomly chosen */ - for (row = 0; row < rows; ++row) { - pixel * pP; - pixel * pP2; - - if (shift != 0) - nowshift = (rand() % (shift+1)) - ((shift+1) / 2); - else - nowshift = 0; - - ppm_readppmrow(ifP, srcrow, cols, maxval, format); - - pP = &srcrow[0]; - pP2 = &destrow[0]; - - /* if the shift value is less than zero, we take the original - pixel line and copy it into the destination line translated - to the left by x pixels. The empty pixels on the right end - of the destination line are filled up with the pixel that - is the right-most in the original pixel line. - */ - if (nowshift < 0) { - unsigned int col; - pP += abs(nowshift); - for (col = 0; col < cols; ++col) { - PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); - ++pP2; - if (col < (cols + nowshift) - 1) - ++pP; - } - } else { - unsigned int col; - /* The shift value is 0 or positive, so fill the first - pixels of the destination line with the - first pixel from the source line, and copy the rest of - the source line to the dest line - */ - for (col = 0; col < cols; ++col) { - PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); - ++pP2; - if (col >= nowshift) - ++pP; - } - } - - ppm_writeppmrow(stdout, destrow, cols, maxval, 0); - } - - pm_close(ifP); - ppm_freerow(srcrow); - ppm_freerow(destrow); - - return 0; -} diff --git a/editor/ppmspread.c b/editor/ppmspread.c deleted file mode 100644 index 6753f4fe..00000000 --- a/editor/ppmspread.c +++ /dev/null @@ -1,117 +0,0 @@ -/*********************************************************************/ -/* ppmspread - randomly displace a PPM's pixels by a certain amount */ -/* Frank Neumann, October 1993 */ -/* V1.1 16.11.1993 */ -/* */ -/* version history: */ -/* V1.0 12.10.1993 first version */ -/* V1.1 16.11.1993 Rewritten to be NetPBM.programming conforming */ -/*********************************************************************/ - -#include - -#include "ppm.h" - - - -int -main(int argc, - char * argv[]) { - - FILE * ifP; - int argn, rows, cols; - unsigned int row; - pixel ** destarray, ** srcarray; - pixel * pP; - pixel * pP2; - pixval maxval; - pixval r1, g1, b1; - int amount; - const char * const usage = "amount [ppmfile]\n amount: # of pixels to displace a pixel by at most\n"; - - /* parse in 'default' parameters */ - ppm_init(&argc, argv); - - argn = 1; - - /* parse in amount & seed */ - if (argn == argc) - pm_usage(usage); - if (sscanf(argv[argn], "%d", &amount) != 1) - pm_usage(usage); - if (amount < 0) - pm_error("amount should be a positive number"); - ++argn; - - /* parse in filename (if present, stdin otherwise) */ - if (argn != argc) - { - ifP = pm_openr(argv[argn]); - ++argn; - } - else - ifP = stdin; - - if (argn != argc) - pm_usage(usage); - - srcarray = ppm_readppm(ifP, &cols, &rows, &maxval); - - destarray = ppm_allocarray(cols, rows); - - /* clear out the buffer */ - for (row = 0; row < rows; ++row) - memset(destarray[row], 0, cols * sizeof(pixel)); - - srand(pm_randseed()); - - /* start displacing pixels */ - for (row = 0; row < rows; ++row) { - unsigned int col; - pP = &srcarray[row][0]; - - for (col = 0; col < cols; ++col) { - int const xdis = (rand() % (amount+1)) - ((amount+1) / 2); - int const ydis = (rand() % (amount+1)) - ((amount+1) / 2); - - int const xnew = col + xdis; - int const ynew = row + ydis; - - /* only set the displaced pixel if it's within the bounds - of the image - */ - if (xnew >= 0 && xnew < cols && ynew >= 0 && ynew < rows) { - /* displacing a pixel is accomplished by swapping it - with another pixel in its vicinity - so, first - store other pixel's RGB - */ - pP2 = &srcarray[ynew][xnew]; - r1 = PPM_GETR(*pP2); - g1 = PPM_GETG(*pP2); - b1 = PPM_GETB(*pP2); - /* set second pixel to new value */ - pP2 = &destarray[ynew][xnew]; - PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); - - /* now, set first pixel to (old) value of second */ - pP2 = &destarray[row][col]; - PPM_ASSIGN(*pP2, r1, g1, b1); - } else { - /* displaced pixel is out of bounds; leave the old - pixel there - */ - pP2 = &destarray[row][col]; - PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); - } - ++pP; - } - } - - ppm_writeppm(stdout, destarray, cols, rows, maxval, 0); - - pm_close(ifP); - ppm_freearray(srcarray, rows); - ppm_freearray(destarray, rows); - - return 0; -} diff --git a/editor/ppmtv.c b/editor/ppmtv.c deleted file mode 100644 index da25102a..00000000 --- a/editor/ppmtv.c +++ /dev/null @@ -1,105 +0,0 @@ - -/*********************************************************************/ -/* ppmtv - make a 'look-alike ntsc' picture from a PPM file */ -/* Frank Neumann, October 1993 */ -/* V1.1 16.11.1993 */ -/* */ -/* version history: */ -/* V1.0 12.10.1993 first version */ -/* V1.1 16.11.1993 Rewritten to be NetPBM.programming conforming */ -/*********************************************************************/ - -#include "ppm.h" - -/**************************/ -/* start of main function */ -/**************************/ -int main(argc, argv) -int argc; -char *argv[]; -{ - FILE* ifp; - int argn, rows, cols, format, i = 0, j = 0; - pixel *srcrow, *destrow; - pixel *pP = NULL, *pP2 = NULL; - pixval maxval; - double dimfactor; - long longfactor; - const char * const usage = "dimfactor [ppmfile]\n dimfactor: 0.0 = total blackness, 1.0 = original picture\n"; - - /* parse in 'default' parameters */ - ppm_init(&argc, argv); - - argn = 1; - - /* parse in dim factor */ - if (argn == argc) - pm_usage(usage); - if (sscanf(argv[argn], "%lf", &dimfactor) != 1) - pm_usage(usage); - if (dimfactor < 0.0 || dimfactor > 1.0) - pm_error("dim factor must be in the range from 0.0 to 1.0 "); - ++argn; - - /* parse in filename (if present, stdin otherwise) */ - if (argn != argc) - { - ifp = pm_openr(argv[argn]); - ++argn; - } - else - ifp = stdin; - - if (argn != argc) - pm_usage(usage); - - /* read first data from file */ - ppm_readppminit(ifp, &cols, &rows, &maxval, &format); - - /* no error checking required here, ppmlib does it all for us */ - srcrow = ppm_allocrow(cols); - - longfactor = (long)(dimfactor * 65536); - - /* allocate a row of pixel data for the new pixels */ - destrow = ppm_allocrow(cols); - - ppm_writeppminit(stdout, cols, rows, maxval, 0); - - /** now do the ntsc'ing (actually very similar to ppmdim) **/ - for (i = 0; i < rows; i++) - { - ppm_readppmrow(ifp, srcrow, cols, maxval, format); - - pP = srcrow; - pP2 = destrow; - - for (j = 0; j < cols; j++) - { - /* every alternating row is left in unchanged condition */ - if (i & 1) - { - PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); - } - /* and the other lines are dimmed to the specified factor */ - else - { - PPM_ASSIGN(*pP2, (PPM_GETR(*pP) * longfactor) >> 16, - (PPM_GETG(*pP) * longfactor) >> 16, - (PPM_GETB(*pP) * longfactor) >> 16); - } - pP++; - pP2++; - } - - /* write out one line of graphic data */ - ppm_writeppmrow(stdout, destrow, cols, maxval, 0); - } - - pm_close(ifp); - ppm_freerow(srcrow); - ppm_freerow(destrow); - - exit(0); -} - diff --git a/editor/specialty/Makefile b/editor/specialty/Makefile new file mode 100644 index 00000000..eda54882 --- /dev/null +++ b/editor/specialty/Makefile @@ -0,0 +1,55 @@ +ifeq ($(SRCDIR)x,x) + SRCDIR = $(CURDIR)/../.. + BUILDDIR = $(SRCDIR) +endif +SUBDIR = editor/specialty +VPATH=.:$(SRCDIR)/$(SUBDIR) + +include $(BUILDDIR)/config.mk + +PORTBINARIES = pamdeinterlace \ + pammixinterlace \ + pamoil \ + pampop9 \ + pbmlife \ + pgmabel \ + pgmbentley \ + pgmmorphconv \ + pnmindex \ + ppm3d \ + ppmglobe \ + ppmntsc \ + ppmrelief \ + ppmshift \ + ppmspread \ + ppmtv \ + +# We don't include programs that have special library dependencies in the +# merge scheme, because we don't want those dependencies to prevent us +# from building all the other programs. + +NOMERGEBINARIES = +MERGEBINARIES = $(PORTBINARIES) + + +BINARIES = $(MERGEBINARIES) $(NOMERGEBINARIES) +SCRIPTS = + +OBJECTS = $(BINARIES:%=%.o) + +MERGE_OBJECTS = $(MERGEBINARIES:%=%.o2) + +.PHONY: all +all: $(BINARIES) + +include $(SRCDIR)/common.mk + +install.bin: install.bin.local + +.PHONY: install.bin.local +install.bin.local: $(PKGDIR)/bin +# Remember that $(SYMLINK) might just be a copy command. +# pamoil replaced pgmoil in June 2001. + cd $(PKGDIR)/bin ; \ + rm -f pgmoil ; \ + $(SYMLINK) pamoil$(EXE) pgmoil diff --git a/editor/specialty/pamdeinterlace.c b/editor/specialty/pamdeinterlace.c new file mode 100644 index 00000000..9ed1d8eb --- /dev/null +++ b/editor/specialty/pamdeinterlace.c @@ -0,0 +1,132 @@ +/****************************************************************************** + pamdeinterlace +******************************************************************************* + De-interlace an image, i.e. select every 2nd row. + + By Bryan Henderson, San Jose, CA 2001.11.11. + + Contributed to the public domain. +******************************************************************************/ + +#include "pam.h" +#include "shhopt.h" +#include "mallocvar.h" + +enum evenodd {EVEN, ODD}; + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char *inputFilespec; /* Filespecs of input files */ + enum evenodd rowsToTake; +}; + + +static void +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo *cmdlineP) { +/*---------------------------------------------------------------------------- + Note that the file spec array we return is stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optStruct3 opt; /* set by OPTENT3 */ + optEntry *option_def; + unsigned int option_def_index; + + unsigned int takeeven, takeodd; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "takeeven", OPT_FLAG, NULL, &takeeven, 0); + OPTENT3(0, "takeodd", OPT_FLAG, NULL, &takeodd, 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); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (takeeven && takeodd) + pm_error("You cannot specify both -takeeven and -takeodd options."); + + if (takeodd) + cmdlineP->rowsToTake = ODD; + else + cmdlineP->rowsToTake = EVEN; + + if (argc-1 < 1) + cmdlineP->inputFilespec = "-"; + else if (argc-1 == 1) + cmdlineP->inputFilespec = argv[1]; + else + pm_error("You specified too many arguments (%d). The only " + "argument is the optional input file specification.", + argc-1); +} + + + + + +int +main(int argc, char *argv[]) { + + FILE * ifP; + tuple * tuplerow; /* Row from input image */ + unsigned int row; + struct cmdlineInfo cmdline; + struct pam inpam; + struct pam outpam; + + pnm_init( &argc, argv ); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFilespec); + + pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); + + tuplerow = pnm_allocpamrow(&inpam); + + outpam = inpam; /* Initial value -- most fields should be same */ + outpam.file = stdout; + if (inpam.height % 2 == 0) + outpam.height = inpam.height / 2; + else { + if (cmdline.rowsToTake == ODD) + outpam.height = inpam.height / 2; + else + outpam.height = inpam.height / 2 + 1; + } + + pnm_writepaminit(&outpam); + + { + unsigned int modulusToTake; + /* The row number mod 2 of the rows that are supposed to go into + the output. + */ + + switch (cmdline.rowsToTake) { + case EVEN: modulusToTake = 0; break; + case ODD: modulusToTake = 1; break; + default: pm_error("INTERNAL ERROR: invalid rowsToTake"); + } + + /* Read input and write out rows extracted from it */ + for (row = 0; row < inpam.height; row++) { + pnm_readpamrow(&inpam, tuplerow); + if (row % 2 == modulusToTake) + pnm_writepamrow(&outpam, tuplerow); + } + } + pnm_freepamrow(tuplerow); + pm_close(inpam.file); + pm_close(outpam.file); + + return 0; +} + diff --git a/editor/specialty/pammixinterlace.c b/editor/specialty/pammixinterlace.c new file mode 100644 index 00000000..f22563f6 --- /dev/null +++ b/editor/specialty/pammixinterlace.c @@ -0,0 +1,344 @@ +/****************************************************************************** + pammixinterlace +******************************************************************************* + De-interlace an image by merging adjacent rows. + + Copyright (C) 2007 Bruce Guenter, FutureQuest, Inc. + + 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. + +******************************************************************************/ + +#define _BSD_SOURCE /* Make sure strcaseeq() is in nstring.h */ + +#include + +#include "mallocvar.h" +#include "nstring.h" +#include "shhopt.h" +#include "pam.h" + + + +static sample +clamp(sample const val, + sample const maxval) { + + return val < 0 ? 0 : val > maxval ? maxval : val; +} + + + +static bool +distant(long const above, + long const mid, + long const below) { + + return abs(mid - (above + below) / 2) > abs(above - below); +} + + + +static void +filterLinearBlend(tuple * const outputrow, + tuple ** const tuplerowWindow, + unsigned int const width, + unsigned int const depth, + bool const adaptive, + sample const maxval) { + + unsigned int col; + + for (col = 0; col < width; ++col) { + unsigned int plane; + + for (plane = 0; plane < depth; ++plane) { + long const above = tuplerowWindow[0][col][plane]; + long const mid = tuplerowWindow[1][col][plane]; + long const below = tuplerowWindow[2][col][plane]; + + sample out; + + if (!adaptive || distant(above, mid, below)) + out = (above + mid * 2 + below) / 4; + else + out = mid; + + outputrow[col][plane] = out; + } + } +} + + + +static void +filterFfmpeg(tuple * const outputrow, + tuple ** const tuplerowWindow, + unsigned int const width, + unsigned int const depth, + bool const adaptive, + sample const maxval) { + + unsigned int col; + + for (col = 0; col < width; ++col) { + unsigned int plane; + + for (plane = 0; plane < depth; ++plane) { + long const above = tuplerowWindow[1][col][plane]; + long const mid = tuplerowWindow[2][col][plane]; + long const below = tuplerowWindow[3][col][plane]; + + sample out; + + if (!adaptive || distant(above, mid, below)) { + long const a = (- (long)tuplerowWindow[0][col][plane] + + above * 4 + + mid * 2 + + below * 4 + - (long)tuplerowWindow[4][col][plane]) / 8; + out = clamp(a, maxval); + } else + out = mid; + + outputrow[col][plane] = out; + } + } +} + + + +static void +filterFIR(tuple * const outputrow, + tuple ** const tuplerowWindow, + unsigned int const width, + unsigned int const depth, + bool const adaptive, + sample const maxval) { + + unsigned int col; + + for (col = 0; col < width; ++col) { + unsigned int plane; + + for (plane = 0; plane < depth; ++plane) { + + long const above = tuplerowWindow[1][col][plane]; + long const mid = tuplerowWindow[2][col][plane]; + long const below = tuplerowWindow[3][col][plane]; + + sample out; + + if (!adaptive || distant(above, mid, below)) { + long const a = (- (long)tuplerowWindow[0][col][plane] + + above * 2 + + mid * 6 + + below * 2 + - (long)tuplerowWindow[4][col][plane]) / 8; + out = clamp(a, maxval); + } else + out = mid; + + outputrow[col][plane] = out; + } + } +} + + + +struct filter { + const char * name; /* The command-line name of the filter */ + unsigned int rows; /* The number of rows the filter operates on */ + void (*filter)(tuple *, tuple **, + unsigned int width, unsigned int depth, + bool adaptive, sample maxval); +}; + +static struct filter filters[] = { + { "fir", 5, filterFIR }, /* FIR is cleanest and default filter */ + { "ffmpeg", 5, filterFfmpeg }, + { "linear", 3, filterLinearBlend }, +}; + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileName; /* Names of input files */ + struct filter * filterP; + unsigned int adaptive; +}; + + + +static void +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that the file spec array we return is stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optStruct3 opt; /* set by OPTENT3 */ + optEntry * option_def; + unsigned int option_def_index; + const char * filterName; + unsigned int filterSpec; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "filter", OPT_STRING, &filterName, &filterSpec, 0); + OPTENT3(0, "adaptive", OPT_FLAG, NULL, &cmdlineP->adaptive, 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); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (!filterSpec) + cmdlineP->filterP = &filters[0]; + else { + unsigned int i; + cmdlineP->filterP = NULL; + for (i = 0; i < sizeof filters / sizeof(struct filter); ++i) { + if (strcaseeq(filterName, filters[i].name)) { + cmdlineP->filterP = &filters[i]; + break; + } + } + if (!cmdlineP->filterP) + pm_error("The filter name '%s' is not known.", filterName); + } + + if (argc-1 < 1) + cmdlineP->inputFileName = "-"; + else if (argc-1 == 1) + cmdlineP->inputFileName = argv[1]; + else + pm_error("You specified too many arguments (%d). The only " + "argument is the optional input file specification.", + argc-1); +} + + + +static void +allocateRowWindowBuffer(struct pam * const pamP, + tuple ** const tuplerowWindow, + unsigned int const rows) { + + unsigned int row; + + for (row = 0; row < rows; ++row) + tuplerowWindow[row] = pnm_allocpamrow(pamP); +} + + + +static void +freeRowWindowBuffer(tuple ** const tuplerowWindow, + unsigned int const rows) { + + unsigned int row; + + for (row = 0; row < rows; ++row) + pnm_freepamrow(tuplerowWindow[row]); +} + + + +static void +slideWindowDown(tuple ** const tuplerowWindow, + unsigned int const rows) { +/*---------------------------------------------------------------------------- + Slide the rows-line tuple row window tuplerowWindow[] down one by moving + pointers. +-----------------------------------------------------------------------------*/ + tuple * const oldrow0 = tuplerowWindow[0]; + + unsigned int i; + + for (i = 0; i < rows-1; ++i) + tuplerowWindow[i] = tuplerowWindow[i+1]; + + tuplerowWindow[i] = oldrow0; +} + + + +int +main(int argc, char *argv[]) { + + FILE * ifP; + struct cmdlineInfo cmdline; + struct pam inpam; + struct pam outpam; + tuple * tuplerowWindow[5]; + tuple * outputrow; + unsigned int rows; + + pnm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + rows = cmdline.filterP->rows; + + ifP = pm_openr(cmdline.inputFileName); + + pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); + + outpam = inpam; /* Initial value -- most fields should be same */ + outpam.file = stdout; + + pnm_writepaminit(&outpam); + + allocateRowWindowBuffer(&inpam, tuplerowWindow, rows); + outputrow = pnm_allocpamrow(&outpam); + + if (inpam.height < rows) { + unsigned int row; + pm_message("WARNING: Image height less than %d. No mixing done.", + rows); + for (row = 0; row < inpam.height; ++row) { + pnm_readpamrow(&inpam, tuplerowWindow[0]); + pnm_writepamrow(&outpam, tuplerowWindow[0]); + } + } else { + unsigned int row; + + for (row = 0; row < rows-1; ++row) + pnm_readpamrow(&inpam, tuplerowWindow[row]); + + /* Pass through first unfilterable rows */ + for (row = 0; row < rows/2; ++row) + pnm_writepamrow(&outpam, tuplerowWindow[row]); + + for (row = rows / 2 + 1; row < inpam.height - rows / 2 + 1; ++row) { + pnm_readpamrow(&inpam, tuplerowWindow[rows-1]); + cmdline.filterP->filter(outputrow, tuplerowWindow, + inpam.width, inpam.depth, + cmdline.adaptive, inpam.maxval); + pnm_writepamrow(&outpam, outputrow); + + slideWindowDown(tuplerowWindow, rows); + } + + /* Pass through last rows */ + for (row = rows/2; row < rows-1; ++row) + pnm_writepamrow(&outpam, tuplerowWindow[row]); + } + + freeRowWindowBuffer(tuplerowWindow, rows); + pnm_freepamrow(outputrow); + pm_close(inpam.file); + pm_close(outpam.file); + + return 0; +} diff --git a/editor/specialty/pamoil.c b/editor/specialty/pamoil.c new file mode 100644 index 00000000..6cb8d3ac --- /dev/null +++ b/editor/specialty/pamoil.c @@ -0,0 +1,137 @@ +/* pgmoil.c - read a portable pixmap and turn into an oil painting +** +** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com) +** Shamelessly butchered into a color version by Chris Sheppard +** 2001 +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + +#include +#include +#include +#include "pam.h" +#include "mallocvar.h" + +static void +convertRow(struct pam const inpam, tuple ** const tuples, + tuple * const tuplerow, int const row, int const smearFactor, + int * const hist) { + + int sample; + for (sample = 0; sample < inpam.depth; sample++) { + int col; + for (col = 0; col < inpam.width; ++col) { + int i; + int drow; + int modalval; + /* The sample value that occurs most often in the neighborhood + of the pixel being examined + */ + + /* Compute hist[] - frequencies, in the neighborhood, of each + sample value + */ + for (i = 0; i <= inpam.maxval; ++i) hist[i] = 0; + + for (drow = row - smearFactor; drow <= row + smearFactor; ++drow) { + if (drow >= 0 && drow < inpam.height) { + int dcol; + for (dcol = col - smearFactor; + dcol <= col + smearFactor; + ++dcol) { + if ( dcol >= 0 && dcol < inpam.width ) + ++hist[tuples[drow][dcol][sample]]; + } + } + } + { + /* Compute modalval */ + int sampleval; + int maxfreq; + + maxfreq = 0; + modalval = 0; + + for (sampleval = 0; sampleval <= inpam.maxval; ++sampleval) { + if (hist[sampleval] > maxfreq) { + maxfreq = hist[sampleval]; + modalval = sampleval; + } + } + } + tuplerow[col][sample] = modalval; + } + } +} + + + +int +main(int argc, char *argv[] ) { + struct pam inpam, outpam; + FILE* ifp; + tuple ** tuples; + tuple * tuplerow; + int * hist; + /* A buffer for the convertRow subroutine to use */ + int argn; + int row; + int smearFactor; + const char* const usage = "[-n ] [ppmfile]"; + + ppm_init( &argc, argv ); + + argn = 1; + smearFactor = 3; /* DEFAULT VALUE */ + + /* Check for options. */ + if ( argn < argc && argv[argn][0] == '-' ) { + if ( argv[argn][1] == 'n' ) { + ++argn; + if ( argn == argc || sscanf(argv[argn], "%d", &smearFactor) != 1 ) + pm_usage( usage ); + } else + pm_usage( usage ); + ++argn; + } + if ( argn < argc ) { + ifp = pm_openr( argv[argn] ); + ++argn; + } else + ifp = stdin; + + if ( argn != argc ) + pm_usage( usage ); + + tuples = pnm_readpam(ifp, &inpam, PAM_STRUCT_SIZE(tuple_type)); + pm_close(ifp); + + MALLOCARRAY(hist, inpam.maxval + 1); + if (hist == NULL) + pm_error("Unable to allocate memory for histogram."); + + outpam = inpam; outpam.file = stdout; + + pnm_writepaminit(&outpam); + + tuplerow = pnm_allocpamrow(&inpam); + + for (row = 0; row < inpam.height; ++row) { + convertRow(inpam, tuples, tuplerow, row, smearFactor, hist); + pnm_writepamrow(&outpam, tuplerow); + } + + pnm_freepamrow(tuplerow); + free(hist); + pnm_freepamarray(tuples, &inpam); + + pm_close(stdout); + exit(0); +} + diff --git a/editor/specialty/pampop9.c b/editor/specialty/pampop9.c new file mode 100644 index 00000000..d6c61e4f --- /dev/null +++ b/editor/specialty/pampop9.c @@ -0,0 +1,108 @@ +/* + * + * (c) Robert Tinsley, 2003 (http://www.thepoacher.net/contact) + * + * Released under the GPL (http://www.fsf.org/licenses/gpl.txt) + * + * + * CHANGES + * + * v1.00 2003-02-28 Original version + * + * v1.10 2003-03-02 + * + changed to use pam_* routines rather than ppm_* + * + changed to use pm_* rather than fopen()/fclose() + * + renamed from ppmgrid to pampup9 + * + wrote a man-page (actually, html) + * + * Changes by Bryan Henderson for inclusion in the Netpbm package (fully + * exploiting Netpbm library). Renamed to Pampop9. March 2003. + * + */ + +#include +#include /* atoi() */ + +#include "pam.h" + +static const char * const copyright = + "(c) Robert Tinsley 2003 (http://www.thepoacher.net/contact)"; + +static const char *usagestr = "pnmfile|- xtiles ytiles xdelta ydelta"; + +int main(int argc, char *argv[]) +{ + const char *filename = "-"; + int xtiles, ytiles, xdelta, ydelta; + FILE *fp; + + struct pam spam, dpam; + tuple **spix, *dpix; + int xtilesize, ytilesize, sx, sy, dx, dy, p; + + + + pnm_init(&argc, argv); + + if (argc-1 != 5) { + pm_error("Wrong number of arguments. Program requires 5 arguments; " + "you supplied %d. Usage: %s", argc-1, usagestr); + } + + filename = argv[1]; + xtiles = atoi(argv[2]); + ytiles = atoi(argv[3]); + xdelta = atoi(argv[4]); + ydelta = atoi(argv[5]); + + if (filename == NULL || *filename == '\0' + || xtiles <= 0 || ytiles <= 0 || xdelta < 0 || ydelta < 0) + pm_error("invalid argument"); + + /* read src pam */ + + fp = pm_openr(filename); + + spix = pnm_readpam(fp, &spam, PAM_STRUCT_SIZE(tuple_type)); + + pm_close(fp); + + /* init dst pam */ + + xtilesize = spam.width - (xtiles - 1) * xdelta; + ytilesize = spam.height - (ytiles - 1) * ydelta; + + if (xtilesize <= 0) + pm_error("xtilesize must be positive. You specified %d", xtilesize); + if (ytilesize <= 0) + pm_error("ytilesize must be positive. You specified %d", ytilesize); + + dpam = spam; + dpam.file = stdout; + dpam.width = xtiles * xtilesize; + dpam.height = ytiles * ytilesize; + + dpix = pnm_allocpamrow(&dpam); + + pnm_writepaminit(&dpam); + + /* generate dst pam */ + + for (dy = 0; dy < dpam.height; dy++) { + sy = ((int) (dy / ytilesize)) * ydelta + (dy % ytilesize); + for (dx = 0; dx < dpam.width; dx++) { + sx = ((int) (dx / xtilesize)) * xdelta + (dx % xtilesize); + for (p = 0; p < spam.depth; ++p) { + dpix[dx][p] = spix[sy][sx][p]; + } + } + pnm_writepamrow(&dpam, dpix); + } + + /* all done */ + + pnm_freepamarray(spix, &spam); + pnm_freepamrow(dpix); + + exit(EXIT_SUCCESS); +} diff --git a/editor/specialty/pbmlife.c b/editor/specialty/pbmlife.c new file mode 100644 index 00000000..be34cc69 --- /dev/null +++ b/editor/specialty/pbmlife.c @@ -0,0 +1,114 @@ +/* pbmlife.c - read a portable bitmap and apply Conway's rules of Life to it +** +** Copyright (C) 1988,1 1991 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + +#include "pbm.h" + +int +main( argc, argv ) +int argc; +char* argv[]; + { + FILE* ifp; + bit* prevrow; + bit* thisrow; + bit* nextrow; + bit* temprow; + register bit* newrow; + int rows, cols, row; + register int col, count; + int format; + + + pbm_init( &argc, argv ); + + if ( argc > 2 ) + pm_usage( "[pbmfile]" ); + + if ( argc == 2 ) + ifp = pm_openr( argv[1] ); + else + ifp = stdin; + + pbm_readpbminit( ifp, &cols, &rows, &format ); + prevrow = pbm_allocrow( cols ); + thisrow = pbm_allocrow( cols ); + nextrow = pbm_allocrow( cols ); + + pbm_writepbminit( stdout, cols, rows, 0 ); + newrow = pbm_allocrow( cols ); + + pbm_readpbmrow( ifp, nextrow, cols, format ); + + for ( row = 0; row < rows; ++row ) + { + temprow = prevrow; + prevrow = thisrow; + thisrow = nextrow; + nextrow = temprow; + if ( row < rows - 1 ) + pbm_readpbmrow( ifp, nextrow, cols, format ); + + for ( col = 0; col < cols; ++col ) + { + /* Check the neighborhood, with an unrolled double loop. */ + count = 0; + if ( row > 0 ) + { + /* upper left */ + if ( col > 0 && prevrow[col - 1] == PBM_WHITE ) + ++count; + /* upper center */ + if ( prevrow[col] == PBM_WHITE ) + ++count; + /* upper right */ + if ( col < cols - 1 && prevrow[col + 1] == PBM_WHITE ) + ++count; + } + /* left */ + if ( col > 0 && thisrow[col - 1] == PBM_WHITE ) + ++count; + /* right */ + if ( col < cols - 1 && thisrow[col + 1] == PBM_WHITE ) + ++count; + if ( row < rows - 1 ) + { + /* lower left */ + if ( col > 0 && nextrow[col - 1] == PBM_WHITE ) + ++count; + /* lower center */ + if ( nextrow[col] == PBM_WHITE ) + ++count; + /* lower right */ + if ( col < cols - 1 && nextrow[col + 1] == PBM_WHITE ) + ++count; + } + + /* And compute the new value. */ + if ( thisrow[col] == PBM_WHITE ) + if ( count == 2 || count == 3 ) + newrow[col] = PBM_WHITE; + else + newrow[col] = PBM_BLACK; + else + if ( count == 3 ) + newrow[col] = PBM_WHITE; + else + newrow[col] = PBM_BLACK; + } + pbm_writepbmrow( stdout, newrow, cols, 0 ); + } + + pm_close( ifp ); + pm_close( stdout ); + + exit( 0 ); + } diff --git a/editor/specialty/pgmabel.c b/editor/specialty/pgmabel.c new file mode 100644 index 00000000..4914c4be --- /dev/null +++ b/editor/specialty/pgmabel.c @@ -0,0 +1,316 @@ +/* pgmabel.c - read a portable graymap and making the deconvolution +** +** Deconvolution of an axial-symmetric image of an rotation symmetrical +** process by solving the linear equation system with y-Axis as +** symmetry-line +** +** Copyright (C) 1997-2006 by German Aerospace Research establishment +** +** Author: Volker Schmidt +** lefti@voyager.boerde.de +** +** 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. +** +** $HISTORY: +** +** 24 Jan 2002 : 001.009 : some optimzization +** 22 Jan 2002 : 001.008 : some stupid calculations changed +** 08 Aug 2001 : 001.007 : new usage (netpbm-conform) +** 27 Jul 1998 : 001.006 : First try of error correction +** 26 Mar 1998 : 001.005 : Calculating the dl's before transformation +** 06 Feb 1998 : 001.004 : Include of a logo in the upper left edge +** 26 Nov 1997 : 001.003 : Some bug fixes and reading only lines +** 25 Nov 1997 : 001.002 : include of pixsize for getting scale invariant +** 03 Sep 1997 : 001.001 : only define for PID2 +** 03 Sep 1997 : 001.000 : First public release +** 21 Aug 1997 : 000.909 : Recalculate the streching-factor +** 20 Aug 1997 : 000.908 : -left and -right for calculating only one side +** 20 Aug 1997 : 000.906 : correction of divisor, include of -factor +** 15 Aug 1997 : 000.905 : Include of -help and -axis +*/ + +static const char* const version="$VER: pgmabel 1.009 (24 Jan 2002)"; + +#include +#include /* for calloc */ +#include "pgm.h" +#include "mallocvar.h" + +#ifndef PID2 /* PI/2 (on AMIGA always defined) */ +#define PID2 1.57079632679489661923 +#endif + +#define TRUE 1 +#define FALSE 0 + +/* some global variables */ +static double *aldl, *ardl; /* pointer for weighting factors */ + +/* ---------------------------------------------------------------------------- +** procedure for calculating the sum of the calculated surfaces with the +** weight of the surface +** n <- index of end point of the summation +** N <- width of the calculated row +** xr <- array of the calculated elements of the row +** adl <- pre-calculated surface coefficient for each segment +*/ +static double +Sum ( int n, double *xr, int N, double *adl) +{ + int k; + double result=0.0; + + if (n==0) return(0.0); /* outer ring is 0 per definition */ + for (k=0 ; k<=(n-1) ; k++) + { + result += xr[k] * ( adl[k*N+n] - adl[(k+1)*N+n]); +/* result += xr[k] * ( dr(k,n+0.5,N) - dr(k+1,n+0.5,N)); */ + } + return(result); +} + +/* ---------------------------------------------------------------------------- +** procedure for calculating the surface coefficient for the Integration +** R, N <- indizes of the coefficient +** r <- radial position of the center of the surface +*/ +static double +dr ( int R, double r, int N) +{ + double a; + double b; + a=(double) N-R ; + b=(double) N-r ; + return(sqrt(a*a-b*b)); +} + +/* ---------------------------------------------------------------------------- +** procedure for making the Abel integration for deconvolution of the image +** y <-> array with values for deconvolution and results +** N <- width of the array +** adl <- array with pre-calculated weighting factors +*/ +static void +abel ( float *y, int N, double *adl) +{ + register int n; + double *rho, *rhop; /* results and new index */ + float *yp; /* new indizes for the y-array */ + + MALLOCARRAY(rho, N); + if( !rho ) + pm_error( "out of memory" ); + rhop = rho; + yp = y; + + for (n=0 ; n 2) rhop[n-1] = (rho[n-2]+rho[n-1]+rho[n])/3.0; stabilization*/ + } + for (n=0 ; n=1 )&&( n0?temp:0); + } + for ( col = midcol; col < cols; ++col ) /* right side */ + { + trow[cols-col-1] = (float) (grayorig[col]); + } + if ( right ) abel(trow,(cols-midcol),ardl); /* deconvolution */ + for ( col = midcol; col < cols; ++col) /* writing right side */ + { + temp = (int)(trow[cols-col-1]/r_div); + temp = (temp>0?temp:0); + grayrow[col] = temp; + } + pgm_writepgmrow( stdout, grayrow, cols, maxval, 0 ); /* saving row */ + } + pm_close( ifp ); + pm_close( stdout ); /* closing output */ + free( trow ); /* deconvolution is done, clear memory */ + pgm_freerow( grayorig ); + pgm_freerow( grayrow ); + free(aldl); + free(ardl); /* all used memory freed (i hope) */ + exit( 0 ); /* end of procedure */ +} + diff --git a/editor/specialty/pgmbentley.c b/editor/specialty/pgmbentley.c new file mode 100644 index 00000000..aed92074 --- /dev/null +++ b/editor/specialty/pgmbentley.c @@ -0,0 +1,74 @@ +/* pgmbentley.c - read a portable graymap and smear it according to brightness +** +** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com) +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + +#include + +#include "pm_c_util.h" +#include "pgm.h" + + +static unsigned int const N = 4; + + +int +main(int argc, const char * argv[]) { + + FILE * ifP; + int rows, cols; + gray maxval; + gray ** gin; + gray ** gout; + unsigned int row; + const char * inputFileName; + + pm_proginit(&argc, argv); + + if (argc-1 < 1) + inputFileName = "-"; + else { + inputFileName = argv[1]; + + if (argc-1 > 1) + pm_error("There are no options and only one argument. " + "You specified %u", argc-1); + } + ifP = pm_openr(inputFileName); + + gin = pgm_readpgm(ifP, &cols, &rows, &maxval); + + pm_close(ifP); + + gout = pgm_allocarray(cols, rows); + + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) + gout[row][col] = 0; + } + + for (row = 0; row < rows; ++row) { + unsigned int col; + + for (col = 0; col < cols; ++col) { + unsigned int const brow = MIN(rows-1, row + gin[row][col] / N); + + gout[brow][col] = gin[row][col]; + } + } + + pgm_writepgm(stdout, gout, cols, rows, maxval, 0); + + pm_close(stdout); + pgm_freearray(gout, rows); + + return 0; +} diff --git a/editor/specialty/pgmmorphconv.c b/editor/specialty/pgmmorphconv.c new file mode 100644 index 00000000..abc4e718 --- /dev/null +++ b/editor/specialty/pgmmorphconv.c @@ -0,0 +1,253 @@ +/* pgmmorphconv.c - morphological convolutions on a graymap: dilation and +** erosion +** +** Copyright (C) 2000 by Luuk van Dijk/Mind over Matter +** +** Based on +** pnmconvol.c - general MxN convolution on a portable anymap +** +** Copyright (C) 1989, 1991 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + +#include "pm_c_util.h" +#include "pgm.h" + + +/************************************************************ + * Dilate + ************************************************************/ + +static int +dilate( bit** template, int trowso2, int tcolso2, + gray** in_image, gray** out_image, + int rows, int cols ){ + + int c, r, tc, tr; + int templatecount; + gray source; + + for( c=0; c0)?0:-tr) ; r< ((tr>0)?(rows-tr):rows) ; ++r ){ + for( c= ((tc>0)?0:-tc) ; c< ((tc>0)?(cols-tc):cols) ; ++c ){ + source = in_image[r+tr][c+tc]; + out_image[r][c] = MAX(source, out_image[r][c]); + } /* for c */ + } /* for r */ + } /* for tr */ + } /* for tc */ + + return templatecount; + +} /* dilate */ + + + +/************************************************************ + * Erode: same as dilate except !!!! + ************************************************************/ + +static int +erode( bit** template, int trowso2, int tcolso2, + gray** in_image, gray** out_image, + int rows, int cols ){ + + int c, r, tc, tr; + int templatecount; + gray source; + + for( c=0; c0)?0:-tr) ; r< ((tr>0)?(rows-tr):rows) ; ++r ){ + for( c= ((tc>0)?0:-tc) ; c< ((tc>0)?(cols-tc):cols) ; ++c ){ + + source = in_image[r+tr][c+tc]; + out_image[r][c] = MIN(source, out_image[r][c]); + + } /* for c */ + } /* for r */ + + + + } /* for tr */ + } /* for tc */ + + return templatecount; + +} /* erode */ + + + +/************************************************************ + * Main + ************************************************************/ + + +int main( int argc, char* argv[] ){ + + int argn; + char operation; + const char* usage = "-dilate|-erode|-open|-close [pgmfile]"; + + FILE* tifp; /* template */ + int tcols, trows; + int tcolso2, trowso2; + bit** template; + + + FILE* ifp; /* input image */ + int cols, rows; + gray maxval; + + gray** in_image; + gray** out_image; + + int templatecount=0; + + pgm_init( &argc, argv ); + + /* + * parse arguments + */ + + ifp = stdin; + operation = 'd'; + + argn=1; + + if( argn == argc ) pm_usage( usage ); + + if( pm_keymatch( argv[argn], "-erode", 2 )) { operation='e'; argn++; } + else + if( pm_keymatch( argv[argn], "-dilate", 2 )) { operation='d'; argn++; } + else + if( pm_keymatch( argv[argn], "-open", 2 )) { operation='o'; argn++; } + else + if( pm_keymatch( argv[argn], "-close", 2 )) { operation='c'; argn++; } + + if( argn == argc ) pm_usage( usage ); + + tifp = pm_openr( argv[argn++] ); + + if( argn != argc ) ifp = pm_openr( argv[argn++] ); + + if( argn != argc ) pm_usage( usage ); + + + /* + * Read in the template matrix. + */ + + template = pbm_readpbm( tifp, &tcols, &trows ); + pm_close( tifp ); + + if( tcols % 2 != 1 || trows % 2 != 1 ) + pm_error("the template matrix must have an odd number of " + "rows and columns" ); + + /* the reason is that we want the middle pixel to be the origin */ + tcolso2 = tcols / 2; /* template coords run from -tcols/2 .. 0 .. +tcols/2 */ + trowso2 = trows / 2; + +#if 0 + fprintf(stderr, "template: %d x %d\n", trows, tcols); + fprintf(stderr, "half: %d x %d\n", trowso2, tcolso2); +#endif + + /* + * Read in the image + */ + + in_image = pgm_readpgm( ifp, &cols, &rows, &maxval); + + if( cols < tcols || rows < trows ) + pm_error("the image is smaller than the convolution matrix" ); + +#if 0 + fprintf(stderr, "image: %d x %d (%d)\n", rows, cols, maxval); +#endif + + /* + * Allocate output buffer and initialize with min or max value + */ + + out_image = pgm_allocarray( cols, rows ); + + if( operation == 'd' ){ + templatecount = dilate(template, trowso2, tcolso2, + in_image, out_image, rows, cols); + } + else if( operation == 'e' ){ + templatecount = erode(template, trowso2, tcolso2, + in_image, out_image, rows, cols); + } + else if( operation == 'o' ){ + gray ** eroded_image; + eroded_image = pgm_allocarray( cols, rows ); + templatecount = erode(template, trowso2, tcolso2, + in_image, eroded_image, rows, cols); + templatecount = dilate(template, trowso2, tcolso2, + eroded_image, out_image, rows, cols); + pgm_freearray( eroded_image, rows ); + } + else if( operation == 'c' ){ + gray ** dilated_image; + dilated_image = pgm_allocarray( cols, rows ); + templatecount = dilate(template, trowso2, tcolso2, + in_image, dilated_image, rows, cols); + templatecount = erode(template, trowso2, tcolso2, + dilated_image, out_image, rows, cols); + pgm_freearray( dilated_image, rows ); + } + + if(templatecount == 0 ) pm_error( "The template was empty!" ); + + pgm_writepgm( stdout, out_image, cols, rows, maxval, 1 ); + + pgm_freearray( out_image, rows ); + pgm_freearray( in_image, rows ); + pm_close( ifp ); + + exit( 0 ); + +} /* main */ + diff --git a/editor/specialty/pnmindex.c b/editor/specialty/pnmindex.c new file mode 100644 index 00000000..7b405ef3 --- /dev/null +++ b/editor/specialty/pnmindex.c @@ -0,0 +1,639 @@ +/*============================================================================ + pnmindex +============================================================================== + + build a visual index of a bunch of PNM images + + This used to be a C shell program, and then a BASH program. Neither + were portable enough, and the program is too complex for either of + those languages anyway, so now it's in C. + + By Bryan Henderson 2005.04.24. + + Contributed to the public domain by its author. + +============================================================================*/ + +#define _BSD_SOURCE /* Make sure strdup is in string.h */ + +#include +#include +#include +#include +#include + + +#include "pm_config.h" +#include "shhopt.h" +#include "mallocvar.h" +#include "nstring.h" +#include "pnm.h" + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + unsigned int inputFileCount; + const char ** inputFileName; + unsigned int size; + unsigned int across; + unsigned int colors; + unsigned int black; + unsigned int noquant; + const char * title; + unsigned int verbose; +}; + +static bool verbose; + + + +static void PM_GNU_PRINTF_ATTR(1,2) +systemf(const char * const fmt, + ...) { + + va_list varargs; + + size_t dryRunLen; + + va_start(varargs, fmt); + + vsnprintfN(NULL, 0, fmt, varargs, &dryRunLen); + + va_end(varargs); + + if (dryRunLen + 1 < dryRunLen) + /* arithmetic overflow */ + pm_error("Command way too long"); + else { + size_t const allocSize = dryRunLen + 1; + char * shellCommand; + shellCommand = malloc(allocSize); + if (shellCommand == NULL) + pm_error("Can't get storage for %u-character command", + allocSize); + else { + va_list varargs; + size_t realLen; + int rc; + + va_start(varargs, fmt); + + vsnprintfN(shellCommand, allocSize, fmt, varargs, &realLen); + + assert(realLen == dryRunLen); + va_end(varargs); + + if (verbose) + pm_message("shell cmd: %s", shellCommand); + + rc = system(shellCommand); + if (rc != 0) + pm_error("shell command '%s' failed. rc %d", + shellCommand, rc); + + strfree(shellCommand); + } + } +} + + + +static void +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo * const cmdlineP) { + + unsigned int option_def_index; + optEntry *option_def; + /* Instructions to optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int quant; + unsigned int sizeSpec, colorsSpec, acrossSpec, titleSpec; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "black", OPT_FLAG, NULL, + &cmdlineP->black, 0); + OPTENT3(0, "noquant", OPT_FLAG, NULL, + &cmdlineP->noquant, 0); + OPTENT3(0, "quant", OPT_FLAG, NULL, + &quant, 0); + OPTENT3(0, "verbose", OPT_FLAG, NULL, + &cmdlineP->verbose, 0); + OPTENT3(0, "size", OPT_UINT, &cmdlineP->size, + &sizeSpec, 0); + OPTENT3(0, "colors", OPT_UINT, &cmdlineP->colors, + &colorsSpec, 0); + OPTENT3(0, "across", OPT_UINT, &cmdlineP->across, + &acrossSpec, 0); + OPTENT3(0, "title", OPT_STRING, &cmdlineP->title, + &titleSpec, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; + + optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdline_p and others. */ + + if (quant && cmdlineP->noquant) + pm_error("You can't specify both -quant and -noquat"); + + if (!colorsSpec) + cmdlineP->colors = 256; + + if (!sizeSpec) + cmdlineP->size = 100; + + if (!acrossSpec) + cmdlineP->across = 6; + + if (!titleSpec) + cmdlineP->title = NULL; + + if (colorsSpec && cmdlineP->noquant) + pm_error("-colors doesn't make any sense with -noquant"); + + if (argc-1 < 1) + pm_error("You must name at least one file that contains an image " + "to go into the index"); + + cmdlineP->inputFileCount = argc-1; + + MALLOCARRAY_NOFAIL(cmdlineP->inputFileName, cmdlineP->inputFileCount); + + { + unsigned int i; + for (i = 0; i < cmdlineP->inputFileCount; ++i) { + cmdlineP->inputFileName[i] = strdup(argv[i+1]); + if (cmdlineP->inputFileName[i] == NULL) + pm_error("Unable to allocate memory for a file name"); + } + } +} + + + +static void +freeCmdline(struct cmdlineInfo const cmdline) { + + unsigned int i; + + for (i = 0; i < cmdline.inputFileCount; ++i) + strfree(cmdline.inputFileName[i]); + + free(cmdline.inputFileName); + +} + + + +static void +makeTempDir(const char ** const tempDirP) { + + const char * const tmpdir = getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp"; + + const char * mytmpdir; + int rc; + + asprintfN(&mytmpdir, "%s/pnmindex_%d", tmpdir, getpid()); + + rc = pm_mkdir(mytmpdir, 0700); + if (rc != 0) + pm_error("Unable to create temporary file directory '%s'. mkdir() " + "fails with errno %d (%s)", + mytmpdir, errno, strerror(errno)); + + *tempDirP = mytmpdir; +} + + + +static void +removeTempDir(const char * const tempDir) { + + int rc; + + rc = rmdir(tempDir); + if (rc != 0) + pm_error("Failed to remove temporary file directory '%s'. " + "rmdir() fails with errno %d (%s)", + tempDir, errno, strerror(errno)); +} + + +static const char * +rowFileName(const char * const dirName, + unsigned int const row) { + + const char * fileName; + + asprintfN(&fileName, "%s/pi.%u", dirName, row); + + return fileName; +} + + + +static void +makeTitle(const char * const title, + unsigned int const rowNumber, + bool const blackBackground, + const char * const tempDir) { + + const char * const invertStage = blackBackground ? "| pnminvert " : ""; + + const char * fileName; + + fileName = rowFileName(tempDir, rowNumber); + + /* This quoting is not adequate. We really should do this without + a shell at all. + */ + systemf("pbmtext \"%s\" " + "%s" + "> %s", + title, invertStage, fileName); + + strfree(fileName); +} + + + +static void +copyImage(const char * const inputFileName, + const char * const outputFileName) { + + systemf("cat %s > %s", inputFileName, outputFileName); +} + + + +static void +copyScaleQuantImage(const char * const inputFileName, + const char * const outputFileName, + int const format, + unsigned int const size, + unsigned int const quant, + unsigned int const colors) { + + const char * scaleCommand; + + switch (PNM_FORMAT_TYPE(format)) { + case PBM_TYPE: + asprintfN(&scaleCommand, + "pamscale -quiet -xysize %u %u %s " + "| pgmtopbm > %s", + size, size, inputFileName, outputFileName); + break; + + case PGM_TYPE: + asprintfN(&scaleCommand, + "pamscale -quiet -xysize %u %u %s >%s", + size, size, inputFileName, outputFileName); + break; + + case PPM_TYPE: + if (quant) + asprintfN(&scaleCommand, + "pamscale -quiet -xysize %u %u %s " + "| pnmquant -quiet %u > %s", + size, size, inputFileName, colors, outputFileName); + else + asprintfN(&scaleCommand, + "pamscale -quiet -xysize %u %u %s >%s", + size, size, inputFileName, outputFileName); + break; + default: + pm_error("Unrecognized Netpbm format: %d", format); + } + + systemf("%s", scaleCommand); + + strfree(scaleCommand); +} + + + +static int +formatTypeMax(int const typeA, + int const typeB) { + + if (typeA == PPM_TYPE || typeB == PPM_TYPE) + return PPM_TYPE; + else if (typeA == PGM_TYPE || typeB == PGM_TYPE) + return PGM_TYPE; + else + return PBM_TYPE; +} + + + +static const char * +thumbnailFileName(const char * const dirName, + unsigned int const row, + unsigned int const col) { + + const char * fileName; + + asprintfN(&fileName, "%s/pi.%u.%u", dirName, row, col); + + return fileName; +} + + + +static const char * +thumbnailFileList(const char * const dirName, + unsigned int const row, + unsigned int const cols) { + + unsigned int const maxListSize = 4096; + + char * list; + unsigned int col; + + list = malloc(maxListSize); + if (list == NULL) + pm_error("Unable to allocate %u bytes for file list", maxListSize); + + list[0] = '\0'; + + for (col = 0; col < cols; ++col) { + const char * const fileName = thumbnailFileName(dirName, row, col); + + if (strlen(list) + strlen(fileName) + 1 > maxListSize - 1) + pm_error("File name list too long for this program to handle."); + else { + strcat(list, " "); + strcat(list, fileName); + } + strfree(fileName); + } + + return list; +} + + + +static void +makeImageFile(const char * const thumbnailFileName, + const char * const inputFileName, + bool const blackBackground, + const char * const outputFileName) { + + const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; + const char * const invertStage = blackBackground ? "| pnminvert " : ""; + + systemf("pbmtext \"%s\" " + "%s" + "| pnmcat %s -topbottom %s - " + "> %s", + inputFileName, invertStage, blackWhiteOpt, + thumbnailFileName, outputFileName); +} + + + +static void +makeThumbnail(const char * const inputFileName, + unsigned int const size, + bool const black, + bool const quant, + unsigned int const colors, + const char * const tempDir, + unsigned int const row, + unsigned int const col, + int * const formatP) { + + FILE * ifP; + int imageCols, imageRows, format; + xelval maxval; + const char * tmpfile; + const char * fileName; + + ifP = pm_openr(inputFileName); + pnm_readpnminit(ifP, &imageCols, &imageRows, &maxval, &format); + pm_close(ifP); + + asprintfN(&tmpfile, "%s/pi.tmp", tempDir); + + if (imageCols < size && imageRows < size) + copyImage(inputFileName, tmpfile); + else + copyScaleQuantImage(inputFileName, tmpfile, format, + size, quant, colors); + + fileName = thumbnailFileName(tempDir, row, col); + + makeImageFile(tmpfile, inputFileName, black, fileName); + + unlink(tmpfile); + + strfree(fileName); + strfree(tmpfile); + + *formatP = format; +} + + + +static void +unlinkThumbnailFiles(const char * const dirName, + unsigned int const row, + unsigned int const cols) { + + unsigned int col; + + for (col = 0; col < cols; ++col) { + const char * const fileName = thumbnailFileName(dirName, row, col); + + unlink(fileName); + + strfree(fileName); + } +} + + + +static void +unlinkRowFiles(const char * const dirName, + unsigned int const rows) { + + unsigned int row; + + for (row = 0; row < rows; ++row) { + const char * const fileName = rowFileName(dirName, row); + + unlink(fileName); + + strfree(fileName); + } +} + + + +static void +combineIntoRowAndDelete(unsigned int const row, + unsigned int const cols, + int const maxFormatType, + bool const blackBackground, + bool const quant, + unsigned int const colors, + const char * const tempDir) { + + const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; + + const char * fileName; + const char * quantStage; + const char * fileList; + + fileName = rowFileName(tempDir, row); + + unlink(fileName); + + if (maxFormatType == PPM_TYPE && quant) + asprintfN(&quantStage, "| pnmquant -quiet %u ", colors); + else + quantStage = strdup(""); + + fileList = thumbnailFileList(tempDir, row, cols); + + systemf("pnmcat %s -leftright -jbottom %s " + "%s" + ">%s", + blackWhiteOpt, fileList, quantStage, fileName); + + strfree(fileList); + strfree(quantStage); + strfree(fileName); + + unlinkThumbnailFiles(tempDir, row, cols); +} + + + +static const char * +rowFileList(const char * const dirName, + unsigned int const rows) { + + unsigned int const maxListSize = 4096; + + unsigned int row; + char * list; + + list = malloc(maxListSize); + if (list == NULL) + pm_error("Unable to allocate %u bytes for file list", maxListSize); + + list[0] = '\0'; + + for (row = 0; row < rows; ++row) { + const char * const fileName = rowFileName(dirName, row); + + if (strlen(list) + strlen(fileName) + 1 > maxListSize - 1) + pm_error("File name list too long for this program to handle."); + + else { + strcat(list, " "); + strcat(list, fileName); + } + strfree(fileName); + } + + return list; +} + + + +static void +writeRowsAndDelete(unsigned int const rows, + int const maxFormatType, + bool const blackBackground, + bool const quant, + unsigned int const colors, + const char * const tempDir) { + + const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; + + const char * quantStage; + const char * fileList; + + if (maxFormatType == PPM_TYPE && quant) + asprintfN(&quantStage, "| pnmquant -quiet %u ", colors); + else + quantStage = strdup(""); + + fileList = rowFileList(tempDir, rows); + + systemf("pnmcat %s -topbottom %s %s", + blackWhiteOpt, fileList, quantStage); + + strfree(fileList); + strfree(quantStage); + + unlinkRowFiles(tempDir, rows); +} + + + +int +main(int argc, char *argv[]) { + struct cmdlineInfo cmdline; + const char * tempDir; + int maxFormatType; + unsigned int colsInRow; + unsigned int rowsDone; + unsigned int i; + + pnm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + verbose = cmdline.verbose; + + makeTempDir(&tempDir); + + maxFormatType = PBM_TYPE; + colsInRow = 0; + rowsDone = 0; + + if (cmdline.title) + makeTitle(cmdline.title, rowsDone++, cmdline.black, tempDir); + + for (i = 0; i < cmdline.inputFileCount; ++i) { + const char * const inputFileName = cmdline.inputFileName[i]; + + int format; + + makeThumbnail(inputFileName, cmdline.size, cmdline.black, + !cmdline.noquant, cmdline.colors, tempDir, + rowsDone, colsInRow, &format); + + maxFormatType = formatTypeMax(maxFormatType, PNM_FORMAT_TYPE(format)); + + ++colsInRow; + if (colsInRow >= cmdline.across || i == cmdline.inputFileCount-1) { + combineIntoRowAndDelete( + rowsDone, colsInRow, maxFormatType, + cmdline.black, !cmdline.noquant, cmdline.colors, + tempDir); + ++rowsDone; + colsInRow = 0; + } + } + + writeRowsAndDelete(rowsDone, maxFormatType, cmdline.black, + !cmdline.noquant, cmdline.colors, tempDir); + + removeTempDir(tempDir); + + freeCmdline(cmdline); + + pm_close(stdout); + + return 0; +} diff --git a/editor/specialty/ppm3d.c b/editor/specialty/ppm3d.c new file mode 100644 index 00000000..6f317a0b --- /dev/null +++ b/editor/specialty/ppm3d.c @@ -0,0 +1,307 @@ +/*============================================================================= + ppmto3d +=============================================================================== + This program converts two PPM images into an anaglyph stereogram image PPM. + (for viewing with red/blue 3D glasses). + +=============================================================================*/ + +#include + +#include "shhopt.h" +#include "mallocvar.h" +#include "ppm.h" +#include "lum.h" + + + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * leftInputFileName; /* '-' if stdin */ + const char * rghtInputFileName; /* '-' if stdin */ + int offset; + unsigned int color; +}; + + + +static void +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + parse program command line described in Unix standard form by argc + and argv. Return the information in the options as *cmdlineP. + + If command line is internally inconsistent (invalid options, etc.), + issue error message to stderr and abort program. + + Note that the strings we return are stored in the storage that + was passed to us as the argv array. We also trash *argv. +-----------------------------------------------------------------------------*/ + optEntry * option_def; + /* Instructions to optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + unsigned int offsetSpec; + const char * offsetArg; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "color", OPT_FLAG, NULL, + &cmdlineP->color, 0); + OPTENT3(0, "offset", OPT_INT, &cmdlineP->offset, + &offsetSpec, 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); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (argc-1 < 2) + pm_error("You must specify at least two arguments: left and right " + "input file names. You specified %u", argc-1); + else { + cmdlineP->leftInputFileName = argv[1]; + cmdlineP->rghtInputFileName = argv[2]; + + if (argc-1 > 2) { + offsetArg = argv[3]; + + if (argc-1 > 3) + pm_error("Program takes at most 3 arguments: left and " + "right input file names and offset. " + "You specified %u", argc-1); + } else + offsetArg = NULL; + } + + if (offsetArg && offsetSpec) + pm_error("You cannot specify both -offset and the offset " + "argument (i.e. with -offset, there is at most " + "two arguments: left and right input file names"); + else if (!offsetArg && !offsetSpec) + cmdlineP->offset = 0; + else if (offsetArg) + cmdlineP->offset = atoi(offsetArg); +} + + + +static void +computeGrayscaleRow(const pixel * const inputRow, + gray * const outputRow, + pixval const maxval, + unsigned int const cols) { + + if (maxval <= 255) { + unsigned int col; + /* Use fast approximation to 0.299 r + 0.587 g + 0.114 b. */ + for (col = 0; col < cols; ++col) + outputRow[col] = ppm_fastlumin(inputRow[col]); + } else { + unsigned int col; + /* Can't use fast approximation, so fall back on floats. */ + for (col = 0; col < cols; ++col) + outputRow[col] = PPM_LUMIN(inputRow[col]) + 0.5; + } +} + + + +static void +compute3dRowMono(gray * const lGrayrow, + gray * const rGrayrow, + pixel * const pixelrow, + unsigned int const cols, + int const offset) { + + unsigned int col; + gray * lgP; + gray * rgP; + pixel * pP; + + assert(abs(offset) <= cols); + + for (col = 0, pP = pixelrow, lgP = lGrayrow, rgP = rGrayrow; + col < cols + offset; + ++col) { + + if ((int)col < offset/2) + ++lgP; + else if ((int)col < offset) { + PPM_ASSIGN(*pP, 0, *lgP, *lgP); + ++lgP; + ++pP; + } else if (col < cols) { + PPM_ASSIGN(*pP, *rgP, *lgP, *lgP); + ++lgP; + ++rgP; + ++pP; + } else if (col < cols + offset/2) { + PPM_ASSIGN(*pP, *rgP, 0, 0); + ++rgP; + ++pP; + } else { + assert(col < cols + offset); + ++rgP; + } + } +} + + + +static void +compute3dRowColor(pixel * const lPixelrow, + pixel * const rPixelrow, + pixel * const pixelrow, + unsigned int const cols, + unsigned int const offset) { + + unsigned int col; + pixel * lP; + pixel * rP; + pixel * pP; + + assert(abs(offset) <= cols); + + for (col = 0, pP = pixelrow, lP = lPixelrow, rP = rPixelrow; + col < cols + offset; + ++col) { + + if ((int)col < offset/2) + ++lP; + else if ((int)col < offset) { + PPM_ASSIGN(*pP, 0, PPM_GETG(*lP), PPM_GETB(*lP)); + ++lP; + ++pP; + } else if (col < cols) { + PPM_ASSIGN(*pP, PPM_GETR(*rP), PPM_GETG(*lP), PPM_GETB(*lP)); + ++lP; + ++rP; + ++pP; + } else if (col < cols + offset/2) { + PPM_ASSIGN(*pP, PPM_GETR(*rP), 0, 0); + ++rP; + ++pP; + } else { + assert(col < cols + offset); + ++rP; + } + } +} + + + +static void +write3dRaster(FILE * const ofP, + FILE * const lIfP, + FILE * const rIfP, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + int const lFormat, + int const rFormat, + int const offset, + bool const color) { + + pixel * lPixelrow; + gray * lGrayrow; + pixel * rPixelrow; + gray * rGrayrow; + pixel * pixelrow; + + unsigned int row; + + assert(abs(offset) < cols); + + lPixelrow = ppm_allocrow (cols); + lGrayrow = pgm_allocrow (cols); + rPixelrow = ppm_allocrow (cols); + rGrayrow = pgm_allocrow (cols); + pixelrow = ppm_allocrow (cols); + + for (row = 0; row < rows; ++row) { + ppm_readppmrow(lIfP, lPixelrow, cols, maxval, lFormat); + ppm_readppmrow(rIfP, rPixelrow, cols, maxval, rFormat); + + computeGrayscaleRow(lPixelrow, lGrayrow, maxval, cols); + computeGrayscaleRow(rPixelrow, rGrayrow, maxval, cols); + + if (color) + compute3dRowColor(lPixelrow, rPixelrow, pixelrow, cols, offset); + else + compute3dRowMono(lGrayrow, rGrayrow, pixelrow, cols, offset); + + ppm_writeppmrow(ofP, pixelrow, cols, maxval, 0); + } + + ppm_freerow(pixelrow); + pgm_freerow(rGrayrow); + ppm_freerow(rPixelrow); + pgm_freerow(lGrayrow); + ppm_freerow(lPixelrow); +} + + + +int +main(int argc, char *argv[]) { + + struct cmdlineInfo cmdline; + FILE * lIfP; + FILE * rIfP; + + int cols, rows; + pixval maxval; + + int lRows, lCols; + int lFormat; + pixval lMaxval; + + int rRows, rCols; + int rFormat; + pixval rMaxval; + + ppm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + lIfP = pm_openr(cmdline.leftInputFileName); + rIfP = pm_openr(cmdline.rghtInputFileName); + + ppm_readppminit(lIfP, &lCols, &lRows, &lMaxval, &lFormat); + ppm_readppminit(rIfP, &rCols, &rRows, &rMaxval, &rFormat); + + if ((lCols != rCols) || (lRows != rRows) || + (lMaxval != rMaxval) || + (PPM_FORMAT_TYPE(lFormat) != PPM_FORMAT_TYPE(rFormat))) + pm_error ("Pictures are not of same size and format"); + + cols = lCols; + rows = lRows; + maxval = lMaxval; + + if (abs(cmdline.offset) >= cols) + pm_error("Magnitude of -offset (%u columns) is not less than " + "width of images " + "(%u columns)", abs(cmdline.offset), cols); + + ppm_writeppminit(stdout, cols, rows, maxval, 0); + + write3dRaster(stdout, lIfP, rIfP, cols, rows, maxval, + lFormat, rFormat, cmdline.offset, cmdline.color); + + pm_close(lIfP); + pm_close(rIfP); + pm_close(stdout); + + return 0; +} + diff --git a/editor/specialty/ppmglobe.c b/editor/specialty/ppmglobe.c new file mode 100644 index 00000000..ee1a57c3 --- /dev/null +++ b/editor/specialty/ppmglobe.c @@ -0,0 +1,172 @@ +/* + * This code written 2003 + * by Max Gensthaler + * Distributed under the Gnu Public License (GPL) + * + * Gensthaler called it 'ppmglobemap'. + * + * Translations of comments and C dialect by Bryan Henderson May 2003. + */ + + +#define _XOPEN_SOURCE /* get M_PI in math.h */ +#include +#include +#include +#include + +#include "ppm.h" +#include "colorname.h" +#include "shhopt.h" +#include "mallocvar.h" + + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileName; /* Filename of input files */ + unsigned int stripcount; + const char * background; + unsigned int closeok; +}; + + + +static void +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that the file spec array we return is stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optEntry *option_def; + /* Instructions to optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + + unsigned int backgroundSpec; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "background", OPT_STRING, &cmdlineP->background, + &backgroundSpec, 0); + OPTENT3(0, "closeok", OPT_FLAG, NULL, + &cmdlineP->closeok, 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); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (!backgroundSpec) + cmdlineP->background = NULL; + + if (argc - 1 < 1) + pm_error("You must specify at least one argument: the strip count"); + else { + int const stripcount = atoi(argv[1]); + if (stripcount <= 0) + pm_error("The strip count must be positive. You specified %d", + stripcount); + + cmdlineP->stripcount = stripcount; + + if (argc-1 < 2) + cmdlineP->inputFileName = "-"; + else + cmdlineP->inputFileName = argv[2]; + + if (argc - 1 > 2) + pm_error("There are at most two arguments: strip count " + "and input file name. " + "You specified %u", argc-1); + } +} + + + +int +main(int argc, char *argv[]) { + + struct cmdlineInfo cmdline; + FILE * ifP; + pixel ** srcPixels; + pixel ** dstPixels; + int srcCols, srcRows; + unsigned int dstCols, dstRows; + pixval srcMaxval, dstMaxval; + unsigned int stripWidth; + /* Width in pixels of each strip. In the output image, this means + the rectangular strip in which the lens-shaped foreground strip + is placed.. + */ + unsigned int row; + pixel backgroundColor; + + ppm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFileName); + + srcPixels = ppm_readppm(ifP, &srcCols, &srcRows, &srcMaxval); + + pm_close(ifP); + + stripWidth = srcCols / cmdline.stripcount; + + if (stripWidth < 1) + pm_error("You asked for %u strips, but the image is only " + "%u pixels wide, so that is impossible.", + cmdline.stripcount, srcCols); + + dstCols = stripWidth * cmdline.stripcount; + dstRows = srcRows; + dstMaxval = srcMaxval; + + if (cmdline.background == NULL) + PPM_ASSIGN(backgroundColor, 0, 0, 0); + else + pm_parse_dictionary_name(cmdline.background, + dstMaxval, cmdline.closeok, + &backgroundColor); + + dstPixels = ppm_allocarray(dstCols, dstRows); + + for (row = 0; row < dstRows; ++row) { + double const factor = sin(M_PI * row / dstRows); + /* Amount by which we squeeze the foreground image of each + strip in this row. + */ + int const stripBorder = (int)((stripWidth*(1.0-factor)/2.0) + 0.5); + /* Distance from the edge (either one) of a strip to the + foreground image within that strip -- i.e. number of pixels + of background color, which User will cut out with scissors + after he prints the image. + */ + unsigned int dstCol; + + for (dstCol = 0; dstCol < dstCols; ++dstCol) { + if (dstCol % stripWidth < stripBorder + || dstCol % stripWidth >= stripWidth - stripBorder) + dstPixels[row][dstCol] = backgroundColor; + else { + unsigned int const leftEdge = + (dstCol / stripWidth) * stripWidth; + unsigned int const srcCol = leftEdge + + (int)((dstCol % stripWidth - stripBorder) / factor + 0.5); + dstPixels[row][dstCol] = srcPixels[row][srcCol]; + } + } + } + + ppm_writeppm(stdout, dstPixels, dstCols, dstRows, dstMaxval, 0); + + return 0; +} diff --git a/editor/specialty/ppmntsc.c b/editor/specialty/ppmntsc.c new file mode 100644 index 00000000..b9f2ac2f --- /dev/null +++ b/editor/specialty/ppmntsc.c @@ -0,0 +1,499 @@ +/* This is ppmntsc.c, a program to adjust saturation values in an image + so they are legal for NTSC or PAL. + + It is derived from the program rlelegal.c, dated June 5, 1995, + which is described below and propagates that program's copyright. + The derivation was done by Bryan Henderson on 2000.04.21 to convert + it from operating on the RLE format to operating on the PPM format + and to rewrite it in a cleaner style, taking advantage of modern C + compiler technology. +*/ + + +/* + * This software is copyrighted as noted below. It may be freely copied, + * modified, and redistributed, provided that the copyright notice is + * preserved on all copies. + * + * There is no warranty or other guarantee of fitness for this software, + * it is provided solely "as is". Bug reports or fixes may be sent + * to the author, who may or may not act on them as he desires. + * + * You may not include this software in a program or other software product + * without supplying the source, or without informing the end-user that the + * source is available for no extra charge. + * + * If you modify this software, you should include a notice giving the + * name of the person performing the modification, the date of modification, + * and the reason for such modification. + */ + +/* + * rlelegal.c - Make RGB colors legal in the YIQ or YUV color systems. + * + * Author: Wes Barris + * Minnesota Supercomputer Center, Inc. + * Date: Fri Oct 15, 1993 + * @Copyright, Research Equipment Inc., d/b/a Minnesota Supercomputer + * Center, Inc., 1993 + + */ + +#define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ +#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ + +#include +#include +#include +#include "ppm.h" +#include "mallocvar.h" +#include "shhopt.h" + +#define TRUE 1 +#define FALSE 0 + +enum legalize {RAISE_SAT, LOWER_SAT, ALREADY_LEGAL}; + /* The actions that make a legal pixel */ + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFilename; + unsigned int verbose; + unsigned int debug; + unsigned int pal; + enum {ALL, LEGAL_ONLY, ILLEGAL_ONLY, CORRECTED_ONLY} output; +}; + + + + +static void +rgbtoyiq(const int r, const int g, const int b, + double * const y_p, + double * const i_p, + double * const q_p) { + + *y_p = .299*(r/255.0) + .587*(g/255.0) + .114*(b/255.0); + *i_p = .596*(r/255.0) - .274*(g/255.0) - .322*(b/255.0); + *q_p = .211*(r/255.0) - .523*(g/255.0) + .312*(b/255.0); +} + + + +static void +yiqtorgb(const double y, const double i, const double q, + int * const r_p, int * const g_p, int * const b_p) { + *r_p = 255.0*(1.00*y + .9562*i + .6214*q); + *g_p = 255.0*(1.00*y - .2727*i - .6468*q); + *b_p = 255.0*(1.00*y -1.1037*i +1.7006*q); +} + + + +static void +rgbtoyuv(const int r, const int g, const int b, + double * const y_p, + double * const u_p, + double * const v_p) { + *y_p = .299*(r/255.0) + .587*(g/255.0) + .114*(b/255.0); + *u_p = -.147*(r/255.0) - .289*(g/255.0) + .437*(b/255.0); + *v_p = .615*(r/255.0) - .515*(g/255.0) - .100*(b/255.0); +} + + + +static void +yuvtorgb(const double y, const double u, const double v, + int * const r_p, int * const g_p, int * const b_p) { + + *r_p = 255.0*(1.00*y + .0000*u +1.1398*v); + *g_p = 255.0*(1.00*y - .3938*u - .5805*v); + *b_p = 255.0*(1.00*y +2.0279*u + .0000*v); +} + + + +static void +make_legal_yiq(const double y, const double i, const double q, + double * const y_new_p, + double * const i_new_p, + double * const q_new_p, + enum legalize * const action_p + ) { + + double sat_old, sat_new; + /* + * I and Q are legs of a right triangle. Saturation is the hypotenuse. + */ + sat_old = sqrt(i*i + q*q); + if (y+sat_old > 1.0) { + const double diff = 0.5*((y+sat_old) - 1.0); + *y_new_p = y - diff; + sat_new = 1.0 - *y_new_p; + *i_new_p = i*(sat_new/sat_old); + *q_new_p = q*(sat_new/sat_old); + *action_p = LOWER_SAT; + } else if (y-sat_old <= -0.251) { + const double diff = 0.5*((sat_old-y) - 0.251); + *y_new_p = y + diff; + sat_new = 0.250 + *y_new_p; + *i_new_p = i*(sat_new/sat_old); + *q_new_p = q*(sat_new/sat_old); + *action_p = RAISE_SAT; + } else { + *y_new_p = y; + *i_new_p = i; + *q_new_p = q; + *action_p = ALREADY_LEGAL; + } + return; +} + + + +static void +make_legal_yuv(const double y, const double u, const double v, + double * const y_new_p, + double * const u_new_p, + double * const v_new_p, + enum legalize * const action_p + ) { + + double sat_old, sat_new; + /* + * U and V are legs of a right triangle. Saturation is the hypotenuse. + */ + sat_old = sqrt(u*u + v*v); + if (y+sat_old >= 1.334) { + const double diff = 0.5*((y+sat_old) - 1.334); + *y_new_p = y - diff; + sat_new = 1.333 - *y_new_p; + *u_new_p = u*(sat_new/sat_old); + *v_new_p = v*(sat_new/sat_old); + *action_p = LOWER_SAT; + } else if (y-sat_old <= -0.339) { + const double diff = 0.5*((sat_old-y) - 0.339); + *y_new_p = y + diff; + sat_new = 0.338 + *y_new_p; + *u_new_p = u*(sat_new/sat_old); + *v_new_p = v*(sat_new/sat_old); + *action_p = RAISE_SAT; + } else { + *u_new_p = u; + *v_new_p = v; + *action_p = ALREADY_LEGAL; + } + return; +} + + + +static void +make_legal_yiq_i(const int r_in, const int g_in, const int b_in, + int * const r_out_p, + int * const g_out_p, + int * const b_out_p, + enum legalize * const action_p + ) { + + double y, i, q; + double y_new, i_new, q_new; + /* + * Convert to YIQ and compute the new saturation. + */ + rgbtoyiq(r_in, g_in, b_in, &y, &i, &q); + make_legal_yiq(y, i, q, &y_new, &i_new, &q_new, action_p); + if (*action_p != ALREADY_LEGAL) + /* + * Given the new I and Q, compute new RGB values. + */ + yiqtorgb(y_new, i_new, q_new, r_out_p, g_out_p, b_out_p); + else { + *r_out_p = r_in; + *g_out_p = g_in; + *b_out_p = b_in; + } + return; +} + + + +static void +make_legal_yuv_i(const int r_in, const int g_in, const int b_in, + int * const r_out_p, + int * const g_out_p, + int * const b_out_p, + enum legalize * const action_p + ){ + + double y, u, v; + double y_new, u_new, v_new; + /* + * Convert to YUV and compute the new saturation. + */ + rgbtoyuv(r_in, g_in, b_in, &y, &u, &v); + make_legal_yuv(y, u, v, &y_new, &u_new, &v_new, action_p); + if (*action_p != ALREADY_LEGAL) + /* + * Given the new U and V, compute new RGB values. + */ + yuvtorgb(y_new, u_new, v_new, r_out_p, g_out_p, b_out_p); + else { + *r_out_p = r_in; + *g_out_p = g_in; + *b_out_p = b_in; + } + return; +} + + + +static void +make_legal_yiq_b(const pixel input, + pixel * const output_p, + enum legalize * const action_p) { + + + int ir_in, ig_in, ib_in; + int ir_out, ig_out, ib_out; + + ir_in = (int)PPM_GETR(input); + ig_in = (int)PPM_GETG(input); + ib_in = (int)PPM_GETB(input); + + make_legal_yiq_i(ir_in, ig_in, ib_in, &ir_out, &ig_out, &ib_out, action_p); + + PPM_ASSIGN(*output_p, ir_out, ig_out, ib_out); + + return; +} + + + +static void +make_legal_yuv_b(const pixel input, + pixel * const output_p, + enum legalize * const action_p) { + + int ir_in, ig_in, ib_in; + int ir_out, ig_out, ib_out; + + ir_in = (int)PPM_GETR(input); + ig_in = (int)PPM_GETG(input); + ib_in = (int)PPM_GETB(input); + make_legal_yuv_i(ir_in, ig_in, ib_in, &ir_out, &ig_out, &ib_out, action_p); + + PPM_ASSIGN(*output_p, ir_out, ig_out, ib_out); + + return; +} + + + +static void +report_mapping(const pixel old_pixel, const pixel new_pixel) { +/*---------------------------------------------------------------------------- + Assuming old_pixel and new_pixel are input and output pixels, + tell the user that we changed a pixel to make it legal, if in fact we + did and it isn't the same change that we just reported. +-----------------------------------------------------------------------------*/ + static pixel last_changed_pixel; + static int first_time = TRUE; + + if (!PPM_EQUAL(old_pixel, new_pixel) && + (first_time || PPM_EQUAL(old_pixel, last_changed_pixel))) { + pm_message("Mapping %d %d %d -> %d %d %d\n", + PPM_GETR(old_pixel), + PPM_GETG(old_pixel), + PPM_GETB(old_pixel), + PPM_GETR(new_pixel), + PPM_GETG(new_pixel), + PPM_GETB(new_pixel) + ); + + last_changed_pixel = old_pixel; + first_time = FALSE; + } +} + + + +static void +convert_one_image(FILE * const ifp, struct cmdlineInfo const cmdline, + bool * const eofP, + int * const hicountP, int * const locountP) { + + /* Parameters of input image: */ + int rows, cols; + pixval maxval; + int format; + + ppm_readppminit(ifp, &cols, &rows, &maxval, &format); + ppm_writeppminit(stdout, cols, rows, maxval, FALSE); + { + pixel* const input_row = ppm_allocrow(cols); + pixel* const output_row = ppm_allocrow(cols); + pixel last_illegal_pixel; + /* Value of the illegal pixel we most recently processed */ + pixel black; + /* A constant - black pixel */ + + PPM_ASSIGN(black, 0, 0, 0); + + PPM_ASSIGN(last_illegal_pixel, 0, 0, 0); /* initial value */ + { + int row; + + *hicountP = 0; *locountP = 0; /* initial values */ + + for (row = 0; row < rows; ++row) { + int col; + ppm_readppmrow(ifp, input_row, cols, maxval, format); + for (col = 0; col < cols; ++col) { + pixel corrected; + /* Corrected or would-be corrected value for pixel */ + enum legalize action; + /* What action was used to make pixel legal */ + if (cmdline.pal) + make_legal_yuv_b(input_row[col], + &corrected, + &action); + else + make_legal_yiq_b(input_row[col], + &corrected, + &action); + + if (action == LOWER_SAT) + (*hicountP)++; + if (action == RAISE_SAT) + (*locountP)++; + if (cmdline.debug) report_mapping(input_row[col], + corrected); + switch (cmdline.output) { + case ALL: + output_row[col] = corrected; + break; + case LEGAL_ONLY: + output_row[col] = (action == ALREADY_LEGAL) ? + input_row[col] : black; + break; + case ILLEGAL_ONLY: + output_row[col] = (action != ALREADY_LEGAL) ? + input_row[col] : black; + break; + case CORRECTED_ONLY: + output_row[col] = (action != ALREADY_LEGAL) ? + corrected : black; + break; + } + } + ppm_writeppmrow(stdout, output_row, cols, maxval, FALSE); + } + } + ppm_freerow(output_row); + ppm_freerow(input_row); + } +} + + +static void +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that many of the strings that this function returns in the + *cmdlineP structure are actually in the supplied argv array. And + sometimes, one of these strings is actually just a suffix of an entry + in argv! +-----------------------------------------------------------------------------*/ + optStruct3 opt; + optEntry *option_def; + /* Instructions to OptParseOptions on how to parse our options. + */ + unsigned int option_def_index; + unsigned int legalonly, illegalonly, correctedonly; + + MALLOCARRAY(option_def, 100); + + option_def_index = 0; /* incremented by OPTENTRY */ + OPTENT3('v', "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); + OPTENT3('V', "debug", OPT_FLAG, NULL, &cmdlineP->debug, 0); + OPTENT3('p', "pal", OPT_FLAG, NULL, &cmdlineP->pal, 0); + OPTENT3('l', "legalonly", OPT_FLAG, NULL, &legalonly, 0); + OPTENT3('i', "illegalonly", OPT_FLAG, NULL, &illegalonly, 0); + OPTENT3('c', "correctedonly", OPT_FLAG, NULL, &correctedonly, 0); + + opt.opt_table = option_def; + opt.short_allowed = TRUE; + opt.allowNegNum = FALSE; + + optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + + if (argc - 1 == 0) + cmdlineP->inputFilename = "-"; /* he wants stdin */ + else if (argc - 1 == 1) + cmdlineP->inputFilename = argv[1]; + else + pm_error("Too many arguments. The only arguments accepted " + "are the mask color and optional input file specification"); + + if (legalonly + illegalonly + correctedonly > 1) + pm_error("--legalonly, --illegalonly, and --correctedonly are " + "conflicting options. Specify at most one of these."); + + if (legalonly) + cmdlineP->output = LEGAL_ONLY; + else if (illegalonly) + cmdlineP->output = ILLEGAL_ONLY; + else if (correctedonly) + cmdlineP->output = CORRECTED_ONLY; + else + cmdlineP->output = ALL; +} + + + +int +main(int argc, char **argv) { + + struct cmdlineInfo cmdline; + FILE * ifP; + int total_hicount, total_locount; + int image_count; + + bool eof; + + ppm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFilename); + + image_count = 0; /* initial value */ + total_hicount = 0; /* initial value */ + total_locount = 0; /* initial value */ + + eof = FALSE; + while (!eof) { + int hicount, locount; + convert_one_image(ifP, cmdline, &eof, &hicount, &locount); + image_count++; + total_hicount += hicount; + total_locount += locount; + ppm_nextimage(ifP, &eof); + } + + + if (cmdline.verbose) { + pm_message("%d images processed.", image_count); + pm_message("%d pixels were above the saturation limit.", + total_hicount); + pm_message("%d pixels were below the saturation limit.", + total_locount); + } + + pm_close(ifP); + + return 0; +} diff --git a/editor/specialty/ppmrelief.c b/editor/specialty/ppmrelief.c new file mode 100644 index 00000000..5e0669c3 --- /dev/null +++ b/editor/specialty/ppmrelief.c @@ -0,0 +1,90 @@ +/* ppmrelief.c - generate a relief map of a portable pixmap +** +** Copyright (C) 1990 by Wilson H. Bent, Jr. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + +#include +#include "ppm.h" + +int +main(int argc, char * argv[]) { + + FILE* ifp; + pixel** inputbuf; + pixel* outputrow; + int argn, rows, cols, format, row; + register int col; + pixval maxval, mv2; + const char* const usage = "[ppmfile]"; + + ppm_init( &argc, argv ); + + argn = 1; + + if ( argn != argc ) { + ifp = pm_openr( argv[argn] ); + ++argn; + } else + ifp = stdin; + + if ( argn != argc ) + pm_usage( usage ); + + ppm_readppminit( ifp, &cols, &rows, &maxval, &format ); + mv2 = maxval / 2; + + /* Allocate space for 3 input rows, plus an output row. */ + inputbuf = ppm_allocarray( cols, 3 ); + outputrow = ppm_allocrow( cols ); + + ppm_writeppminit( stdout, cols, rows, maxval, 0 ); + + /* Read in the first two rows. */ + ppm_readppmrow( ifp, inputbuf[0], cols, maxval, format ); + ppm_readppmrow( ifp, inputbuf[1], cols, maxval, format ); + + /* Write out the first row, all zeros. */ + for ( col = 0; col < cols; ++col ) + PPM_ASSIGN( outputrow[col], 0, 0, 0 ); + ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 ); + + /* Now the rest of the image - read in the 3rd row of inputbuf, + ** and convolve with the first row into the output buffer. + */ + for ( row = 2 ; row < rows; ++row ) { + pixval r, g, b; + int rowa, rowb; + + rowa = row % 3; + rowb = (row + 2) % 3; + ppm_readppmrow( ifp, inputbuf[rowa], cols, maxval, format ); + + for ( col = 0; col < cols - 2; ++col ) { + r = PPM_GETR( inputbuf[rowa][col] ) + + ( mv2 - PPM_GETR( inputbuf[rowb][col + 2] ) ); + g = PPM_GETG( inputbuf[rowa][col] ) + + ( mv2 - PPM_GETG( inputbuf[rowb][col + 2] ) ); + b = PPM_GETB( inputbuf[rowa][col] ) + + ( mv2 - PPM_GETB( inputbuf[rowb][col + 2] ) ); + PPM_ASSIGN( outputrow[col + 1], r, g, b ); + } + ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 ); + } + + /* And write the last row, zeros again. */ + for ( col = 0; col < cols; ++col ) + PPM_ASSIGN( outputrow[col], 0, 0, 0 ); + ppm_writeppmrow( stdout, outputrow, cols, maxval, 0 ); + + pm_close( ifp ); + pm_close( stdout ); + + exit( 0 ); +} diff --git a/editor/specialty/ppmshift.c b/editor/specialty/ppmshift.c new file mode 100644 index 00000000..a765daa5 --- /dev/null +++ b/editor/specialty/ppmshift.c @@ -0,0 +1,132 @@ + +/*********************************************************************/ +/* ppmshift - shift lines of a picture left or right by x pixels */ +/* Frank Neumann, October 1993 */ +/* V1.1 16.11.1993 */ +/* */ +/* version history: */ +/* V1.0 11.10.1993 first version */ +/* V1.1 16.11.1993 Rewritten to be NetPBM.programming conforming */ +/*********************************************************************/ + +#include "ppm.h" + +/**************************/ +/* start of main function */ +/**************************/ +int +main(int argc, + char * argv[]) { + + FILE * ifP; + unsigned int row; + int argn, rows, cols, format; + pixel * srcrow; + pixel * destrow; + pixval maxval; + int shift, nowshift; + int shiftArg; + + const char * const usage = "shift [ppmfile]\n shift: maximum number of pixels to shift a line by\n"; + + /* parse in 'default' parameters */ + ppm_init(&argc, argv); + + argn = 1; + + /* parse in shift number */ + if (argn == argc) + pm_usage(usage); + if (sscanf(argv[argn], "%d", &shiftArg) != 1) + pm_usage(usage); + if (shiftArg < 0) + pm_error("shift factor must be 0 or more"); + ++argn; + + /* parse in filename (if present, stdin otherwise) */ + if (argn != argc) + { + ifP = pm_openr(argv[argn]); + ++argn; + } + else + ifP = stdin; + + if (argn != argc) + pm_usage(usage); + + /* read first data from file */ + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); + + if (shiftArg > cols) { + shift = cols; + pm_message("shift amount is larger than picture width - reset to %d", + shift); + } else + shift = shiftArg; + + srcrow = ppm_allocrow(cols); + + destrow = ppm_allocrow(cols); + + ppm_writeppminit(stdout, cols, rows, maxval, 0); + + srand(pm_randseed()); + + /** now do the shifting **/ + /* the range by which a line is shifted lays in the range from */ + /* -shift/2 .. +shift/2 pixels; however, within this range it is */ + /* randomly chosen */ + for (row = 0; row < rows; ++row) { + pixel * pP; + pixel * pP2; + + if (shift != 0) + nowshift = (rand() % (shift+1)) - ((shift+1) / 2); + else + nowshift = 0; + + ppm_readppmrow(ifP, srcrow, cols, maxval, format); + + pP = &srcrow[0]; + pP2 = &destrow[0]; + + /* if the shift value is less than zero, we take the original + pixel line and copy it into the destination line translated + to the left by x pixels. The empty pixels on the right end + of the destination line are filled up with the pixel that + is the right-most in the original pixel line. + */ + if (nowshift < 0) { + unsigned int col; + pP += abs(nowshift); + for (col = 0; col < cols; ++col) { + PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); + ++pP2; + if (col < (cols + nowshift) - 1) + ++pP; + } + } else { + unsigned int col; + /* The shift value is 0 or positive, so fill the first + pixels of the destination line with the + first pixel from the source line, and copy the rest of + the source line to the dest line + */ + for (col = 0; col < cols; ++col) { + PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); + ++pP2; + if (col >= nowshift) + ++pP; + } + } + + ppm_writeppmrow(stdout, destrow, cols, maxval, 0); + } + + pm_close(ifP); + ppm_freerow(srcrow); + ppm_freerow(destrow); + + return 0; +} diff --git a/editor/specialty/ppmspread.c b/editor/specialty/ppmspread.c new file mode 100644 index 00000000..6753f4fe --- /dev/null +++ b/editor/specialty/ppmspread.c @@ -0,0 +1,117 @@ +/*********************************************************************/ +/* ppmspread - randomly displace a PPM's pixels by a certain amount */ +/* Frank Neumann, October 1993 */ +/* V1.1 16.11.1993 */ +/* */ +/* version history: */ +/* V1.0 12.10.1993 first version */ +/* V1.1 16.11.1993 Rewritten to be NetPBM.programming conforming */ +/*********************************************************************/ + +#include + +#include "ppm.h" + + + +int +main(int argc, + char * argv[]) { + + FILE * ifP; + int argn, rows, cols; + unsigned int row; + pixel ** destarray, ** srcarray; + pixel * pP; + pixel * pP2; + pixval maxval; + pixval r1, g1, b1; + int amount; + const char * const usage = "amount [ppmfile]\n amount: # of pixels to displace a pixel by at most\n"; + + /* parse in 'default' parameters */ + ppm_init(&argc, argv); + + argn = 1; + + /* parse in amount & seed */ + if (argn == argc) + pm_usage(usage); + if (sscanf(argv[argn], "%d", &amount) != 1) + pm_usage(usage); + if (amount < 0) + pm_error("amount should be a positive number"); + ++argn; + + /* parse in filename (if present, stdin otherwise) */ + if (argn != argc) + { + ifP = pm_openr(argv[argn]); + ++argn; + } + else + ifP = stdin; + + if (argn != argc) + pm_usage(usage); + + srcarray = ppm_readppm(ifP, &cols, &rows, &maxval); + + destarray = ppm_allocarray(cols, rows); + + /* clear out the buffer */ + for (row = 0; row < rows; ++row) + memset(destarray[row], 0, cols * sizeof(pixel)); + + srand(pm_randseed()); + + /* start displacing pixels */ + for (row = 0; row < rows; ++row) { + unsigned int col; + pP = &srcarray[row][0]; + + for (col = 0; col < cols; ++col) { + int const xdis = (rand() % (amount+1)) - ((amount+1) / 2); + int const ydis = (rand() % (amount+1)) - ((amount+1) / 2); + + int const xnew = col + xdis; + int const ynew = row + ydis; + + /* only set the displaced pixel if it's within the bounds + of the image + */ + if (xnew >= 0 && xnew < cols && ynew >= 0 && ynew < rows) { + /* displacing a pixel is accomplished by swapping it + with another pixel in its vicinity - so, first + store other pixel's RGB + */ + pP2 = &srcarray[ynew][xnew]; + r1 = PPM_GETR(*pP2); + g1 = PPM_GETG(*pP2); + b1 = PPM_GETB(*pP2); + /* set second pixel to new value */ + pP2 = &destarray[ynew][xnew]; + PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); + + /* now, set first pixel to (old) value of second */ + pP2 = &destarray[row][col]; + PPM_ASSIGN(*pP2, r1, g1, b1); + } else { + /* displaced pixel is out of bounds; leave the old + pixel there + */ + pP2 = &destarray[row][col]; + PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); + } + ++pP; + } + } + + ppm_writeppm(stdout, destarray, cols, rows, maxval, 0); + + pm_close(ifP); + ppm_freearray(srcarray, rows); + ppm_freearray(destarray, rows); + + return 0; +} diff --git a/editor/specialty/ppmtv.c b/editor/specialty/ppmtv.c new file mode 100644 index 00000000..da25102a --- /dev/null +++ b/editor/specialty/ppmtv.c @@ -0,0 +1,105 @@ + +/*********************************************************************/ +/* ppmtv - make a 'look-alike ntsc' picture from a PPM file */ +/* Frank Neumann, October 1993 */ +/* V1.1 16.11.1993 */ +/* */ +/* version history: */ +/* V1.0 12.10.1993 first version */ +/* V1.1 16.11.1993 Rewritten to be NetPBM.programming conforming */ +/*********************************************************************/ + +#include "ppm.h" + +/**************************/ +/* start of main function */ +/**************************/ +int main(argc, argv) +int argc; +char *argv[]; +{ + FILE* ifp; + int argn, rows, cols, format, i = 0, j = 0; + pixel *srcrow, *destrow; + pixel *pP = NULL, *pP2 = NULL; + pixval maxval; + double dimfactor; + long longfactor; + const char * const usage = "dimfactor [ppmfile]\n dimfactor: 0.0 = total blackness, 1.0 = original picture\n"; + + /* parse in 'default' parameters */ + ppm_init(&argc, argv); + + argn = 1; + + /* parse in dim factor */ + if (argn == argc) + pm_usage(usage); + if (sscanf(argv[argn], "%lf", &dimfactor) != 1) + pm_usage(usage); + if (dimfactor < 0.0 || dimfactor > 1.0) + pm_error("dim factor must be in the range from 0.0 to 1.0 "); + ++argn; + + /* parse in filename (if present, stdin otherwise) */ + if (argn != argc) + { + ifp = pm_openr(argv[argn]); + ++argn; + } + else + ifp = stdin; + + if (argn != argc) + pm_usage(usage); + + /* read first data from file */ + ppm_readppminit(ifp, &cols, &rows, &maxval, &format); + + /* no error checking required here, ppmlib does it all for us */ + srcrow = ppm_allocrow(cols); + + longfactor = (long)(dimfactor * 65536); + + /* allocate a row of pixel data for the new pixels */ + destrow = ppm_allocrow(cols); + + ppm_writeppminit(stdout, cols, rows, maxval, 0); + + /** now do the ntsc'ing (actually very similar to ppmdim) **/ + for (i = 0; i < rows; i++) + { + ppm_readppmrow(ifp, srcrow, cols, maxval, format); + + pP = srcrow; + pP2 = destrow; + + for (j = 0; j < cols; j++) + { + /* every alternating row is left in unchanged condition */ + if (i & 1) + { + PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP)); + } + /* and the other lines are dimmed to the specified factor */ + else + { + PPM_ASSIGN(*pP2, (PPM_GETR(*pP) * longfactor) >> 16, + (PPM_GETG(*pP) * longfactor) >> 16, + (PPM_GETB(*pP) * longfactor) >> 16); + } + pP++; + pP2++; + } + + /* write out one line of graphic data */ + ppm_writeppmrow(stdout, destrow, cols, maxval, 0); + } + + pm_close(ifp); + ppm_freerow(srcrow); + ppm_freerow(destrow); + + exit(0); +} + -- cgit 1.4.1