diff options
Diffstat (limited to 'converter/ppm/ppmtoterm.c')
-rw-r--r-- | converter/ppm/ppmtoterm.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/converter/ppm/ppmtoterm.c b/converter/ppm/ppmtoterm.c new file mode 100644 index 00000000..72105705 --- /dev/null +++ b/converter/ppm/ppmtoterm.c @@ -0,0 +1,173 @@ +/* ppmtoterm.c - convert a portable pixmap into an ISO 6429 (ANSI) color ascii +** text. +** +** Copyright (C) 2002 by Ero Carrera (ecarrera@lightforge.com) +** Partially based on, +** ppmtoyuv.c by Marc Boucher, +** ppmtolj.c by Jonathan Melvin and +** ppmtogif.c 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. +** +** 14/Aug/2002: First version. +** +*/ + +#include <string.h> + +#include "ppm.h" +#include "shhopt.h" + + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char *inputFilespec; /* Filespec of input file */ + unsigned int verbose; +}; + + + +static void +parseCommandLine(int argc, char **argv, + struct cmdlineInfo *cmdlineP) { + optEntry *option_def = malloc(100*sizeof(optEntry)); + /* Instructions to OptParseOptions3 on how to parse our options */ + optStruct3 opt; + + unsigned int option_def_index; + + option_def_index = 0; /* incremented by OPTENTRY */ + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + + optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + switch (argc-1) { + case 0: + cmdlineP->inputFilespec = "-"; + break; + case 1: + cmdlineP->inputFilespec = argv[1]; + break; + case 2: + break; + } +} + + +#define ESC "\x1B\x5B" +#define NUM_COLORS 128 +#define MAX_ANSI_STR_LEN 16 + + +static int __inline__ sqr(const int x) { + return x*x; +} + +/* + Generates some sort of color palette mixing the available + colors as different values of background, foreground & brightness. +*/ +static int +generate_palette(unsigned char rgb[NUM_COLORS][3], + char ansi_code[NUM_COLORS][MAX_ANSI_STR_LEN]) { + int code, col=0, cd2=0; + + memset((void *)rgb, 0, NUM_COLORS*3); + memset((void *)ansi_code, 0, NUM_COLORS*MAX_ANSI_STR_LEN); + + for(col=cd2=0; cd2<8; cd2++) { + unsigned int b; + for(b=0;b<2;b++) { + for(code=0; code<8; code++) { + unsigned int c; + for(c=0;c<3;c++) { + if(code&(1<<c)) { + rgb[col][c]=(192|(b?63:0)); + } + if(cd2&(1<<c)) { + rgb[col][c]|=(128); + } + } + sprintf(ansi_code[col], + ESC"%dm"ESC"3%dm"ESC"4%dm", + b, code, cd2); + col++; + } + } + } + return col; +} + + + +int main(int argc, char **argv) +{ + FILE *ifp; + pixel **pixels; + int rows, row, cols, col, + pal_len, i; + pixval maxval; + struct cmdlineInfo + cmdline; + unsigned char rgb[NUM_COLORS][3]; + char ansi_code[NUM_COLORS][MAX_ANSI_STR_LEN]; + + + ppm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifp = pm_openr(cmdline.inputFilespec); + + pixels = ppm_readppm(ifp, &cols, &rows, &maxval); + + pm_close(ifp); + + pal_len=generate_palette(rgb, ansi_code); + + for (row = 0; row < rows; ++row) { + for (col = 0; col < cols; col++) { + pixval const r=(int)PPM_GETR(pixels[row][col])*255/maxval; + pixval const g=(int)PPM_GETG(pixels[row][col])*255/maxval; + pixval const b=(int)PPM_GETB(pixels[row][col])*255/maxval; + int val, dist; + + /* + The following loop calculates the index that + corresponds to the minimum color distance + between the given RGB values and the values + available in the palette. + */ + for(i=0, dist=sqr(255)*3, val=0; i<pal_len; i++) { + pixval const pr=rgb[i][0]; + pixval const pg=rgb[i][1]; + pixval const pb=rgb[i][2]; + unsigned int j; + if( (j=sqr(r-pr)+sqr(b-pb)+sqr(g-pg))<dist ) { + dist=j; + val=i; + } + } + printf("%s%c", ansi_code[val],0xB1); + } + printf(ESC"\x30m\n"); + } + printf(ESC"\x30m"); + + ppm_freearray(pixels, rows); + + exit(0); +} |