From d8d1608b90da80ce89870be7371624e14ba31974 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 14 Oct 2006 17:49:21 +0000 Subject: cleanup git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@85 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/ppm/ppmtomitsu.c | 797 ++++++++++++++++++++++++------------------ converter/ppm/ppmtomitsu.test | 12 + 2 files changed, 472 insertions(+), 337 deletions(-) create mode 100644 converter/ppm/ppmtomitsu.test diff --git a/converter/ppm/ppmtomitsu.c b/converter/ppm/ppmtomitsu.c index e8d6540a..837d9e2b 100644 --- a/converter/ppm/ppmtomitsu.c +++ b/converter/ppm/ppmtomitsu.c @@ -20,339 +20,70 @@ x** - mymalloc() and check_and_rotate() functions for often used ** implied warranty. */ +#include #include +#include #include "pm_c_util.h" -#include "ppm.h" #include "nstring.h" #include "mallocvar.h" +#include "ppm.h" #include "mitsu.h" -#include - #define HASHSIZE 2048 #define myhash(x) ((PPM_GETR(x)*3 + PPM_GETG(x)*5 + PPM_GETB(x)*7) % HASHSIZE) typedef struct hashinfo { pixel color; long flag; - struct hashinfo *next; + struct hashinfo * next; } hashinfo; -static void lineputinit(int cols, int rows, int sharpness, int enlarge, int - copy, struct mediasize medias); -static void frametransferinit(int cols, int rows, int sharpness, int enlarge, - int copy, struct mediasize medias); -static void lookuptableinit(int sharpness, int enlarge, int copy, - struct mediasize medias); -static void lookuptabledata(int cols, int rows, int enlarge, - struct mediasize medias); -static void check_and_rotate(int cols, int rows, int enlarge, - struct mediasize medias); - #define cmd(arg) fputc((arg), stdout) #define datum(arg) fputc((char)(arg), stdout) #define data(arg,num) fwrite((arg), sizeof(char), (num), stdout) -int main(int argc, char *argv[] ) - { - FILE *ifp; - /*hashinfo colorhashtable[HASHSIZE];*/ - struct hashinfo *hashrun; - pixel *xP; - int argn; - bool dpi300; - int cols, rows, format, col, row; - int sharpness, enlarge, copy, tiny; - pixval maxval; - struct mediasize medias; - char media[16]; - const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media ] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]"; - - ppm_init(&argc, argv); - dpi300 = FALSE; - argn = 1; - sharpness = 32; - enlarge = 1; - copy = 1; - memset(media, '\0', 16); - tiny = FALSE; - - /* check for flags */ - while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { - if (pm_keymatch(argv[argn], "-sharpness", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1) - pm_usage(usage); - else if (sharpness < 1 || sharpness > 4) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-enlarge", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1) - pm_usage(usage); - else if (enlarge < 1 || enlarge > 3) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-media", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%15s", media) < 1) - pm_usage(usage); - else if (TOUPPER(media[0]) != 'A') - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-copy", 2)) { - ++argn; - if (argn == argc || sscanf(argv[argn], "%d", ©) != 1) - pm_usage(usage); - else if (copy < 1 || copy > 9) - pm_usage(usage); - } - else if (pm_keymatch(argv[argn], "-dpi300", 2)) - dpi300 = TRUE; - else if (pm_keymatch(argv[argn], "-tiny", 2)) - tiny = TRUE; - else - pm_usage(usage); - ++argn; - } - - if (argn < argc) { - ifp = pm_openr(argv[argn]); - ++argn; - } - else - ifp = stdin; - - if (argn != argc) - pm_usage(usage); - - if (TOUPPER(media[0]) == 'A') - switch (TOUPPER(media[1])) { - case 'S': - medias = MSize_AS; - break; - case '4': - if(TOUPPER(media[2]) == 'S') - medias = MSize_A4S; - else { - medias = MSize_A4; - } - break; - default: - medias = MSize_A; - } - else - medias = MSize_User; - - if (dpi300) { - medias.maxcols *= 2; - medias.maxrows *= 2; - } +static void +check_and_rotate(int const cols, + int const rows, + int const enlarge, + struct mediasize const medias) { - if (tiny) { - pixel *pixelrow; - char *redrow, *greenrow, *bluerow; - - ppm_readppminit(ifp, &cols, &rows, &maxval, &format); - pixelrow = (pixel *) ppm_allocrow(cols); - MALLOCARRAY_NOFAIL(redrow, cols); - MALLOCARRAY_NOFAIL(greenrow, cols); - MALLOCARRAY_NOFAIL(bluerow, cols); - lineputinit(cols, rows, sharpness, enlarge, copy, medias); - - for ( row = 0; row < rows; ++row ) { - ppm_readppmrow(ifp, pixelrow, cols, maxval, format); - switch(PPM_FORMAT_TYPE(format)) { - /* color */ - case PPM_TYPE: - for (col = 0, xP = pixelrow; col < cols; col++, xP++) { - /* First red. */ - redrow[col] = PPM_GETR(*xP); - /* Then green. */ - greenrow[col] = PPM_GETG(*xP); - /* And blue. */ - bluerow[col] = PPM_GETB(*xP); - } - data(redrow, cols); - data(greenrow, cols); - data(bluerow, cols); - break; - /* grayscale */ - default: - for (col = 0, xP = pixelrow; col < cols; col++, xP++) - bluerow[col] = PPM_GETB(*xP); - data(bluerow, cols); - data(bluerow, cols); - data(bluerow, cols); - break; - } - } - pm_close(ifp); + if (cols > rows) { + ROTATEIMG(DOROTATE); /* rotate image */ + if (enlarge * rows > medias.maxcols || enlarge * cols > medias.maxrows) + pm_error("Image too large, MaxPixels = %u x %u", + medias.maxrows, medias.maxcols); + HPIXELS(cols); + VPIXELS(rows); + HPIXELSOFF((medias.maxcols/enlarge - rows)/2); + VPIXELSOFF((medias.maxrows/enlarge - cols)/2); + pm_message("rotating image for output"); + } else { + ROTATEIMG(DONTROTATE); + if (enlarge * rows > medias.maxrows || enlarge * cols > medias.maxcols) + pm_error("Image too large, MaxPixels = %u x %u", + medias.maxrows, medias.maxcols); + HPIXELS(cols); + VPIXELS(rows); + HPIXELSOFF((medias.maxcols/enlarge - cols)/2); + VPIXELSOFF((medias.maxrows/enlarge - rows)/2); } - else { - pixel **pixelpic; - int colanz, colval; - int i; - colorhist_vector table; - - ppm_readppminit( ifp, &cols, &rows, &maxval, &format ); - pixelpic = ppm_allocarray( cols, rows ); - for (row = 0; row < rows; row++) - ppm_readppmrow( ifp, pixelpic[row], cols, maxval, format ); - pm_close(ifp); - - /* first check wether we can use the lut transfer */ - - table = ppm_computecolorhist(pixelpic, cols, rows, MAXLUTCOL+1, - &colanz); - if (table != NULL) { - hashinfo *colorhashtable; +} - MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE); - for (i=0; iflag == -1) { - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - } - else { - while (hashrun->next != NULL) - hashrun = hashrun->next; - MALLOCVAR_NOFAIL(hashrun->next); - hashrun = hashrun->next; - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - hashrun->next = NULL; - } - } - break; - /* other */ - default: - for (colval=0; colvalflag == -1) { - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - } - else { - while (hashrun->next != NULL) - hashrun = hashrun->next; - MALLOCVAR_NOFAIL(hashrun->next); - hashrun = hashrun->next; - hashrun->color = (table[colval]).color; - hashrun->flag = colval; - hashrun->next = NULL; - } - } - } - lookuptabledata(cols, rows, enlarge, medias); - for (row=0; rowcolor), *xP)) - if (hashrun->next != NULL) - hashrun = hashrun->next; - else { - pm_error("you just found a lethal bug."); - } - datum(hashrun->flag); - } - } - free(colorhashtable); - } - else { - /* $#%@^!& no lut possible, so send the pic as 24bit */ - pm_message("found too many colors for fast lookuptable mode"); - frametransferinit(cols, rows, sharpness, enlarge, copy, medias); - switch(PPM_FORMAT_TYPE(format)) { - /* color */ - case PPM_TYPE: - COLORDES(RED); - DATASTART; /* red coming */ - for (row=0; row rows) { - ROTATEIMG(DOROTATE); /* rotate image */ - if (enlarge*rows > medias.maxcols || enlarge*cols > medias.maxrows) { - pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols); +colorRow(colorhist_vector const table, + unsigned int const colanz, + hashinfo * const colorhashtable) { + + unsigned int colval; + for (colval = 0; colval < colanz; ++colval) { + struct hashinfo * const hashchain = + &colorhashtable[myhash((table[colval]).color)]; + + struct hashinfo * hashrun; + + cmd('$'); + datum(colval); + datum(PPM_GETR((table[colval]).color)); + datum(PPM_GETG((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + + hashrun = hashchain; /* start at beginning of chain */ + + if (hashrun->flag == -1) { + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + } else { + while (hashrun->next != NULL) + hashrun = hashrun->next; + MALLOCVAR_NOFAIL(hashrun->next); + hashrun = hashrun->next; + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + hashrun->next = NULL; } - HPIXELS(cols); - VPIXELS(rows); - HPIXELSOFF((medias.maxcols/enlarge - rows)/2); - VPIXELSOFF((medias.maxrows/enlarge - cols)/2); - pm_message("rotating image for output"); } - else { - ROTATEIMG(DONTROTATE); - if (enlarge*rows > medias.maxrows || enlarge*cols > medias.maxcols) { - pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols); +} + + + +static void +grayRow(colorhist_vector const table, + unsigned int const colanz, + hashinfo * const colorhashtable) { + + unsigned int colval; + for (colval = 0; colval < colanz; ++colval) { + struct hashinfo * const hashchain = + &colorhashtable[myhash((table[colval]).color)]; + struct hashinfo * hashrun; + + cmd('$'); + datum(colval); + datum(PPM_GETB((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + datum(PPM_GETB((table[colval]).color)); + + hashrun = hashchain; /* start at beginning of chain */ + + if (hashrun->flag == -1) { + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + } + else { + while (hashrun->next != NULL) + hashrun = hashrun->next; + MALLOCVAR_NOFAIL(hashrun->next); + hashrun = hashrun->next; + hashrun->color = (table[colval]).color; + hashrun->flag = colval; + hashrun->next = NULL; } - HPIXELS(cols); - VPIXELS(rows); - HPIXELSOFF((medias.maxcols/enlarge - cols)/2); - VPIXELSOFF((medias.maxrows/enlarge - rows)/2); } } + + +static void +useLookupTable(pixel ** const pixels, + colorhist_vector const table, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias, + unsigned int const cols, + unsigned int const rows, + int const format, + unsigned int const colanz) { + + hashinfo * colorhashtable; + + pm_message("found %u colors - using the lookuptable-method", colanz); + + MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE); + { + unsigned int i; + for (i = 0; i < HASHSIZE; ++i) { + colorhashtable[i].flag = -1; + colorhashtable[i].next = NULL; + } + } + + lookuptableinit(sharpness, enlarge, copy, medias); + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: + colorRow(table, colanz, colorhashtable); + break; + default: + grayRow(table, colanz, colorhashtable); + } + lookuptabledata(cols, rows, enlarge, medias); + { + unsigned int row; + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + pixel * const pixrow = pixels[row]; + struct hashinfo * const hashchain = + &colorhashtable[myhash(pixrow[col])]; + struct hashinfo * p; + + p = hashchain; + while (!PPM_EQUAL((p->color), pixrow[col])) { + assert(p->next); + p = p->next; + } + datum(p->flag); + } + } + } + free(colorhashtable); +} + + + +static void +noLookupColor(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows) { + + unsigned int row; + COLORDES(RED); + DATASTART; /* red coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETR(pixrow[col])); + } + COLORDES(GREEN); + DATASTART; /* green coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETG(pixrow[col])); + } + COLORDES(BLUE); + DATASTART; /* blue coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } +} + + + +static void +noLookupGray(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows) { + + unsigned int row; + COLORDES(RED); + DATASTART; /* red coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } + COLORDES(GREEN); + DATASTART; /* green coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } + COLORDES(BLUE); + DATASTART; /* blue coming */ + for (row = 0; row < rows; ++row) { + pixel * const pixrow = pixels[row]; + unsigned int col; + for (col = 0; col < cols; ++col) + datum(PPM_GETB(pixrow[col])); + } +} + + + +static void +useNoLookupTable(pixel ** const pixels, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias, + unsigned int const cols, + unsigned int const rows, + int const format) { + + /* $#%@^!& no lut possible, so send the pic as 24bit */ + + pm_message("found too many colors for fast lookuptable mode"); + + frametransferinit(cols, rows, sharpness, enlarge, copy, medias); + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: + noLookupColor(pixels, cols, rows); + break; + default: + noLookupGray(pixels, cols, rows); + } +} + + + +static void +doTiny(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + int const format, + int const sharpness, + int const enlarge, + int const copy, + struct mediasize const medias) { + + pixel * pixelrow; + unsigned char * redrow; + unsigned char * grnrow; + unsigned char * blurow; + unsigned int row; + + pixelrow = ppm_allocrow(cols); + MALLOCARRAY_NOFAIL(redrow, cols); + MALLOCARRAY_NOFAIL(grnrow, cols); + MALLOCARRAY_NOFAIL(blurow, cols); + lineputinit(cols, rows, sharpness, enlarge, copy, medias); + + for (row = 0; row < rows; ++row) { + ppm_readppmrow(ifP, pixelrow, cols, maxval, format); + switch(PPM_FORMAT_TYPE(format)) { + case PPM_TYPE: { /* color */ + unsigned int col; + for (col = 0; col < cols; ++col) { + redrow[col] = PPM_GETR(pixelrow[col]); + grnrow[col] = PPM_GETG(pixelrow[col]); + blurow[col] = PPM_GETB(pixelrow[col]); + } + data(redrow, cols); + data(grnrow, cols); + data(blurow, cols); + } break; + default: { /* grayscale */ + unsigned int col; + for (col = 0; col < cols; ++col) + blurow[col] = PPM_GETB(pixelrow[col]); + data(blurow, cols); + data(blurow, cols); + data(blurow, cols); + } + } + } +} + + + +int +main(int argc, char * argv[]) { + FILE * ifP; + int argn; + bool dpi300; + int cols, rows, format; + pixval maxval; + int sharpness, enlarge, copy, tiny; + struct mediasize medias; + char media[16]; + const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media ] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]"; + + ppm_init(&argc, argv); + + dpi300 = FALSE; + argn = 1; + sharpness = 32; + enlarge = 1; + copy = 1; + memset(media, '\0', 16); + tiny = FALSE; + + /* check for flags */ + while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { + if (pm_keymatch(argv[argn], "-sharpness", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1) + pm_usage(usage); + else if (sharpness < 1 || sharpness > 4) + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-enlarge", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1) + pm_usage(usage); + else if (enlarge < 1 || enlarge > 3) + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-media", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%15s", media) < 1) + pm_usage(usage); + else if (TOUPPER(media[0]) != 'A') + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-copy", 2)) { + ++argn; + if (argn == argc || sscanf(argv[argn], "%d", ©) != 1) + pm_usage(usage); + else if (copy < 1 || copy > 9) + pm_usage(usage); + } + else if (pm_keymatch(argv[argn], "-dpi300", 2)) + dpi300 = TRUE; + else if (pm_keymatch(argv[argn], "-tiny", 2)) + tiny = TRUE; + else + pm_usage(usage); + ++argn; + } + + if (argn < argc) { + ifP = pm_openr(argv[argn]); + ++argn; + } + else + ifP = stdin; + + if (argn != argc) + pm_usage(usage); + + if (TOUPPER(media[0]) == 'A') + switch (TOUPPER(media[1])) { + case 'S': + medias = MSize_AS; + break; + case '4': + if(TOUPPER(media[2]) == 'S') + medias = MSize_A4S; + else { + medias = MSize_A4; + } + break; + default: + medias = MSize_A; + } + else + medias = MSize_User; + + if (dpi300) { + medias.maxcols *= 2; + medias.maxrows *= 2; + } + + ppm_readppminit(ifP, &cols, &rows, &maxval, &format); + + if (tiny) { + doTiny(ifP, cols, rows, maxval, format, + sharpness, enlarge, copy, medias); + + } else { + pixel ** pixels; + int colanz; + colorhist_vector table; + unsigned int row; + + pixels = ppm_allocarray(cols, rows); + for (row = 0; row < rows; row++) + ppm_readppmrow(ifP, pixels[row], cols, maxval, format); + + /* first check wether we can use the lut transfer */ + + table = ppm_computecolorhist(pixels, cols, rows, MAXLUTCOL+1, + &colanz); + if (table) + useLookupTable(pixels, table, sharpness, enlarge, copy, medias, + cols, rows, format, colanz); + else + useNoLookupTable(pixels, sharpness, enlarge, copy, medias, + cols, rows, format); + ppm_freearray(pixels, rows); + } + PRINTIT; + pm_close(ifP); + return 0; +} + diff --git a/converter/ppm/ppmtomitsu.test b/converter/ppm/ppmtomitsu.test new file mode 100644 index 00000000..1805838a --- /dev/null +++ b/converter/ppm/ppmtomitsu.test @@ -0,0 +1,12 @@ +echo Test 1. Should print 3110813682 101562 +./ppmtomitsu ../../testimg.ppm | cksum +echo Test 2. Should print 239186803 34399 +pnmquant 100 ../../testimg.ppm | ./ppmtomitsu | cksum +echo Test 3. Should print 816221676 310 +./ppmtomitsu ../../testgrid.pbm | cksum +echo Test 4. Should print 629834989 752 +./ppmtomitsu -tiny ../../testgrid.pbm | cksum +echo Test 5. Should print 3999654426 101549 +./ppmtomitsu -tiny ../../testimg.ppm | cksum +echo Test 2. Should print 3078685526 101549 +pnmquant 100 ../../testimg.ppm | ./ppmtomitsu -tiny | cksum -- cgit 1.4.1