home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pnm / pnmhistmap.c < prev    next >
C/C++ Source or Header  |  1994-02-01  |  6KB  |  214 lines

  1. /* pnmhistmap.c -
  2.  *    Draw a histogram for a PGM or PPM file
  3.  *
  4.  * Options:    -verbose: the usual
  5.  *        -max N: force scaling value to N
  6.  *        -black: ignore all-black count
  7.  *        -white: ignore all-white count
  8.  *
  9.  * - PGM histogram is a PBM file, PPM histogram is a PPM file
  10.  * - No conditional code - assumes all three: PBM, PGM, PPM
  11.  *
  12.  * Copyright (C) 1993 by Wilson H. Bent, Jr (whb@usc.edu)
  13.  *
  14.  */
  15.  
  16. #include "pnm.h"
  17.  
  18. /* prototypes */
  19. static void ppm_hist ARGS((FILE *fp));
  20. static void pgm_hist ARGS((FILE *fp));
  21.  
  22. #define HIST_WIDTH    256
  23. #define HIST_HEIGHT    200
  24.  
  25. int rows, hist_cols;
  26. xelval maxval;
  27. int format;
  28.  
  29. int verbose = 0;
  30. int no_black = 0;
  31. int no_white = 0;
  32.  
  33. int rhist[HIST_WIDTH];
  34. int ghist[HIST_WIDTH];
  35. int bhist[HIST_WIDTH];
  36. int hmax = -1;
  37. double scale;
  38.  
  39. int
  40. main (argc, argv)
  41. int argc;
  42. char *argv[];
  43. {
  44.     FILE *ifp;
  45.     int argn = 1;
  46.     char *usage = "[-white] [-black] [-max maxvalue] [-verbose] [pnmfile]";
  47.  
  48.     pnm_init (&argc, argv);
  49.  
  50.     /* Check for flags. */
  51.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) {
  52.     if ( pm_keymatch( argv[argn], "-white", 2 ) )
  53.         no_white = 1;
  54.     else if ( pm_keymatch( argv[argn], "-black", 2 ) )
  55.         no_black = 1;
  56.     else if ( pm_keymatch( argv[argn], "-max", 2 ) ) {
  57.         if ((hmax = atoi (argv[++argn])) <= 0)
  58.         pm_error ("Max. value (%d) must be positive", hmax, 0, 0, 0, 0);
  59.     }
  60.     else if ( pm_keymatch( argv[argn], "-verbose", 2 ) )
  61.         verbose = 1;
  62.     else
  63.         pm_usage( usage );
  64.     ++argn;
  65.     }
  66.  
  67.     if (--argc > argn)
  68.     pm_usage (usage);
  69.     else if (argc == argn)
  70.     ifp = pm_openr (argv[argn]);
  71.     else
  72.     ifp = stdin;
  73.  
  74.     pnm_readpnminit (ifp, &hist_cols, &rows, &maxval, &format);
  75.     switch (PNM_FORMAT_TYPE (format)) {
  76.       case PPM_TYPE:
  77.     ppm_hist (ifp);
  78.     break;
  79.       case PGM_TYPE:
  80.     pgm_hist (ifp);
  81.     break;
  82.       case PBM_TYPE:
  83.     pm_error ("no histograms for PBM files", 0, 0, 0, 0, 0);
  84.     break;
  85.     }
  86.     exit (0);
  87. }
  88.  
  89. static void
  90. ppm_hist (fp)
  91. FILE *fp;
  92. {
  93.     pixel *pixrow;
  94.     pixel **pixels;
  95.     int i, j;
  96.     int start, finish;
  97.  
  98.     if ((pixels = ppm_allocarray (HIST_WIDTH, HIST_HEIGHT)) == NULL)
  99.     pm_error ("no space for output array (%d pixels)",
  100.         HIST_WIDTH * HIST_HEIGHT, 0,0,0,0);
  101.     for (i = 0; i < HIST_HEIGHT; ++i)
  102.     bzero (pixels[i], HIST_WIDTH * sizeof (pixel));
  103.     bzero (rhist, sizeof (rhist));
  104.     bzero (ghist, sizeof (ghist));
  105.     bzero (bhist, sizeof (bhist));
  106.  
  107.     /* read the pixel values into the histogram arrays */
  108.     pixrow = ppm_allocrow (hist_cols);
  109.     /*XX error-check! */
  110.     if (verbose) pm_message ("making histogram...", 0,0,0,0,0);
  111.     for (i = rows; i > 0; --i) {
  112.     ppm_readppmrow (fp, pixrow, hist_cols, maxval, format);
  113.     for (j = hist_cols-1; j >= 0; --j) {
  114.         rhist[PPM_GETR(pixrow[j])]++;
  115.         ghist[PPM_GETG(pixrow[j])]++;
  116.         bhist[PPM_GETB(pixrow[j])]++;
  117.     }
  118.     }
  119.     ppm_freerow (pixrow);
  120.     fclose (fp);
  121.  
  122.     /* find the highest-valued slot and set the scale value */
  123.     if (verbose)
  124.     pm_message ("finding max. slot height...", 0, 0, 0, 0, 0);
  125.     if (hmax == -1) {
  126.     start = (no_black ? 1 : 0);
  127.     finish = (no_white ? HIST_WIDTH - 1 : HIST_WIDTH);
  128.     for (hmax = 0, i = start; i < finish; ++i) {
  129.         if (hmax < rhist[i])
  130.         hmax = rhist[i];
  131.         if (hmax < ghist[i])
  132.         hmax = ghist[i];
  133.         if (hmax < bhist[i])
  134.         hmax = bhist[i];
  135.     }
  136.     }
  137.     for (i = 0; i < HIST_WIDTH; ++i) {
  138.     if (rhist[i] > hmax)
  139.         rhist[i] = hmax;
  140.     if (ghist[i] > hmax)
  141.         ghist[i] = hmax;
  142.     if (bhist[i] > hmax)
  143.         bhist[i] = hmax;
  144.     }
  145.     if (verbose)
  146.     pm_message ("Done: height = %d", hmax, 0, 0, 0, 0);
  147.     scale = (double) HIST_HEIGHT / hmax;
  148.  
  149.     for (i = 0; i < HIST_WIDTH; ++i) {
  150.     for (j = HIST_HEIGHT - (int)(scale * rhist[i]); j < HIST_HEIGHT; ++j)
  151.         PPM_PUTR(pixels[j][i], maxval);
  152.     for (j = HIST_HEIGHT - (int)(scale * ghist[i]); j < HIST_HEIGHT; ++j)
  153.         PPM_PUTG(pixels[j][i], maxval);
  154.     for (j = HIST_HEIGHT - (int)(scale * bhist[i]); j < HIST_HEIGHT; ++j)
  155.         PPM_PUTB(pixels[j][i], maxval);
  156.     }
  157.  
  158.     ppm_writeppm (stdout, pixels, HIST_WIDTH, HIST_HEIGHT, maxval, 0);
  159. }
  160.  
  161. static void
  162. pgm_hist (fp)
  163. FILE *fp;
  164. {
  165.     gray *grayrow;
  166.     bit **bits;
  167.     int i, j;
  168.     int start, finish;
  169.  
  170.     if ((bits = pbm_allocarray (HIST_WIDTH, HIST_HEIGHT)) == NULL)
  171.     pm_error ("no space for output array (%d bits)",
  172.         HIST_WIDTH * HIST_HEIGHT, 0,0,0,0);
  173.     bzero (ghist, sizeof (ghist));
  174.  
  175.     /* read the pixel values into the histogram arrays */
  176.     grayrow = pgm_allocrow (hist_cols);
  177.     /*XX error-check! */
  178.     if (verbose) pm_message ("making histogram...", 0,0,0,0,0);
  179.     for (i = rows; i > 0; --i) {
  180.     pgm_readpgmrow (fp, grayrow, hist_cols, maxval, format);
  181.     for (j = hist_cols-1; j >= 0; --j)
  182.         ghist[grayrow[j]]++;
  183.     }
  184.     pgm_freerow (grayrow);
  185.     fclose (fp);
  186.  
  187.     /* find the highest-valued slot and set the scale value */
  188.     if (verbose)
  189.     pm_message ("finding max. slot height...", 0, 0, 0, 0, 0);
  190.     if (hmax == -1) {
  191.     start = (no_black ? 1 : 0);
  192.     finish = (no_white ? HIST_WIDTH - 1 : HIST_WIDTH);
  193.     for (hmax = 0, i = start; i < finish; ++i)
  194.         if (hmax < ghist[i])
  195.         hmax = ghist[i];
  196.     }
  197.     for (i = 0; i < HIST_WIDTH; ++i)
  198.     if (ghist[0] > hmax)
  199.         ghist[0] = hmax;
  200.     if (verbose)
  201.     pm_message ("Done: height = %d", hmax, 0, 0, 0, 0);
  202.     scale = (double) HIST_HEIGHT / hmax;
  203.  
  204.     for (i = 0; i < HIST_WIDTH; ++i) {
  205.     int mark = HIST_HEIGHT - (int)(scale * ghist[i]);
  206.     for (j = 0; j < mark; ++j)
  207.         bits[j][i] = PBM_BLACK;
  208.     for ( ; j < HIST_HEIGHT; ++j)
  209.         bits[j][i] = PBM_WHITE;
  210.     }
  211.  
  212.     pbm_writepbm (stdout, bits, HIST_WIDTH, HIST_HEIGHT, 0);
  213. }
  214.