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

  1. /* ppmnorm.c - read a portable pixmap and normalize the contrast
  2. **
  3. ** by Wilson H. Bent, Jr. (whb@usc.edu)
  4. ** Extensively hacked from pgmnorm.c, which carries the following note:
  5. **
  6. ** Copyright (C) 1989, 1991 by Jef Poskanzer.
  7. **
  8. ** Permission to use, copy, modify, and distribute this software and its
  9. ** documentation for any purpose and without fee is hereby granted, provided
  10. ** that the above copyright notice appear in all copies and that both that
  11. ** copyright notice and this permission notice appear in supporting
  12. ** documentation.  This software is provided "as is" without express or
  13. ** implied warranty.
  14. **
  15. ** (End of note from pgmnorm.c)
  16. */
  17.  
  18. #include "ppm.h"
  19.  
  20. #include "lum.h"
  21.  
  22. #define MAXMAXVAL 1023
  23.  
  24. int
  25. main( argc, argv )
  26. int argc;
  27. char *argv[];
  28.     {
  29.     FILE *ifp;
  30.     pixel **pixels, *pixelrow;
  31.     register pixel *pP;
  32.     pixval maxval;
  33.     int argn, rows, cols, format, row;
  34.     int i, size, cutoff, count, val;
  35.     int hist[MAXMAXVAL+1];
  36.  
  37.     float bpercent, wpercent;
  38.     int range, bvalue, wvalue;
  39.     int specbpercent, specbvalue, specwpercent, specwvalue;
  40.     register int col;
  41.     char *usage = "[-bpercent N | -bvalue N] [-wpercent N | -wvalue N] [ppmfile]";
  42.  
  43.     ppm_init( &argc, argv );
  44.  
  45.     argn = 1;
  46.     bpercent = 2.0;
  47.     wpercent = 1.0;
  48.     specbpercent = specbvalue = specwpercent = specwvalue = 0;
  49.  
  50.     while ( argn + 1 < argc && argv[argn][0] == '-' )
  51.     {
  52.     if ( pm_keymatch( argv[argn], "-bpercent", 3 ) )
  53.         {
  54.         if ( specbvalue )
  55.         pm_error( "only one of -bpercent and -bvalue may be specified",
  56.             0,0,0,0,0 );
  57.         ++argn;
  58.         if ( argn == argc || sscanf( argv[argn], "%f", &bpercent ) != 1 )
  59.         pm_usage( usage );
  60.         if ( bpercent < 0.0  || bpercent > 100.0 )
  61.         pm_error( "black percentage must between 0 and 100",
  62.             0,0,0,0,0 );
  63.         specbpercent = 1;
  64.         }
  65.     else if ( pm_keymatch( argv[argn], "-bvalue", 3 ) )
  66.         {
  67.         if ( specbpercent )
  68.         pm_error( "only one of -bpercent and -bvalue may be specified",
  69.             0,0,0,0,0 );
  70.         ++argn;
  71.         if ( argn == argc || sscanf( argv[argn], "%d", &bvalue ) != 1 )
  72.         pm_usage( usage );
  73.         if ( bvalue < 0 )
  74.         pm_error( "black value must be >= 0", 0,0,0,0,0 );
  75.         specbvalue = 1;
  76.         }
  77.     else if ( pm_keymatch( argv[argn], "-wpercent", 3 ) )
  78.         {
  79.         if ( specbvalue )
  80.         pm_error( "only one of -wpercent and -wvalue may be specified",
  81.             0,0,0,0,0 );
  82.         ++argn;
  83.         if ( argn == argc || sscanf( argv[argn], "%f", &wpercent ) != 1 )
  84.         pm_usage( usage );
  85.         if ( wpercent < 0.0  || wpercent > 100.0 )
  86.         pm_error( "white percentage must between 0 and 100",
  87.             0,0,0,0,0 );
  88.         specwpercent = 1;
  89.         }
  90.     else if ( pm_keymatch( argv[argn], "-wvalue", 3 ) )
  91.         {
  92.         if ( specwpercent )
  93.         pm_error( "only one of -wpercent and -wvalue may be specified",
  94.             0,0,0,0,0 );
  95.         ++argn;
  96.         if ( argn == argc || sscanf( argv[argn], "%d", &wvalue ) != 1 )
  97.         pm_usage( usage );
  98.         if ( wvalue < 0 )
  99.         pm_error( "white value must be >= 0", 0,0,0,0,0 );
  100.         specwvalue = 1;
  101.         }
  102.     else
  103.         pm_usage( usage );
  104.     ++argn;
  105.     }
  106.  
  107.     if ( argn < argc )
  108.     {
  109.     ifp = pm_openr( argv[argn] );
  110.     ++argn;
  111.     }
  112.     else
  113.     ifp = stdin;
  114.  
  115.     if ( argn != argc )
  116.     pm_usage( usage );
  117.  
  118.     if ( specbvalue && specwvalue )
  119.     {
  120.     /* Rescale so that bvalue maps to 0, wvalue maps to maxval. */
  121.     ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
  122.     pixelrow = ppm_allocrow( cols );
  123.     ppm_writeppminit( stdout, cols, rows, maxval, 0 );
  124.     for ( i = 0; i <= bvalue; ++i )
  125.        hist[i] = 0;
  126.     for ( i = wvalue; i <= maxval; ++i )
  127.         hist[i] = maxval;
  128.     range = wvalue - bvalue;
  129.     for ( i = bvalue+1, val = maxval; i < wvalue; ++i, val += maxval )
  130.         hist[i] = val / range;
  131.     for ( row = 0; row < rows; row++ )
  132.         {
  133.         ppm_readppmrow( ifp, pixelrow, cols, maxval, format );
  134.         for ( col = 0, pP = pixelrow; col < cols; col++, pP++ )
  135.         {
  136.         PPM_ASSIGN(*pP, hist[PPM_GETR(*pP)], hist[PPM_GETG(*pP)], hist[PPM_GETB(*pP)]);
  137.         }
  138.         ppm_writeppmrow( stdout, pixelrow, cols, maxval, 0 );
  139.         }
  140.     pm_close( ifp );
  141.     }
  142.     else
  143.     {
  144.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  145.     pm_close( ifp );
  146.  
  147.     /* Build histogram. */
  148.     for ( i = 0; i <= maxval; i++ )
  149.         hist[i] = 0;
  150.     for ( row = 0; row < rows; row++ )
  151.         for ( col = 0, pP = pixels[row]; col < cols; col++, pP++ )
  152.         {
  153. #ifdef MAX_METHOD
  154. #define max(a,b) ((a) > (b) ? (a) : (b))
  155.         i = max (pP->r, max (pP->g, pP->b));
  156. #else
  157.         i = ( ( times77 [PPM_GETR ( *pP )] +
  158.             times150[PPM_GETG ( *pP )] +
  159.             times29 [PPM_GETB ( *pP )]) >> 8);
  160. #endif
  161.         ++hist[i];
  162.         }
  163.     size = rows * cols;
  164.     if ( ! specbvalue )
  165.         { /* Compute bvalue from bpercent. */
  166.         cutoff = size * bpercent / 100.0;
  167.         count = 0;
  168.         for ( bvalue = 0; bvalue <= maxval; bvalue++ )
  169.         {
  170.         count += hist[bvalue];
  171.         if ( count > cutoff )
  172.         break;
  173.         }
  174.         }
  175.     if ( ! specwvalue )
  176.         { /* Compute wvalue from wpercent. */
  177.         cutoff = size * wpercent / 100.0;
  178.         count = 0;
  179.         for ( wvalue = maxval; wvalue >= 0; wvalue-- )
  180.         {
  181.         count += hist[wvalue];
  182.         if ( count > cutoff )
  183.             break;
  184.         }
  185.         }
  186.  
  187.     /* Now rescale so that bvalue maps to 0, wvalue maps to maxval. */
  188.     pm_message(
  189.         "remapping %d..%d to %d..%d", bvalue, wvalue, 0, maxval, 0 );
  190.     ppm_writeppminit( stdout, cols, rows, maxval, 0 );
  191.     for ( i = 0; i <= bvalue; i++ )
  192.         hist[i] = 0;
  193.     for ( i = wvalue; i <= maxval; ++i )
  194.         hist[i] = maxval;
  195.     range = wvalue - bvalue;
  196.     for ( i = bvalue+1, val = maxval; i < wvalue; ++i, val += maxval )
  197.         hist[i] = val / range;
  198.     for ( row = 0; row < rows; row++ )
  199.         {
  200.         for ( col = 0, pP = pixels[row]; col < cols; col++, pP++ )
  201.         {
  202.         PPM_ASSIGN(*pP, hist[PPM_GETR(*pP)], hist[PPM_GETG(*pP)], hist[PPM_GETB(*pP)]);
  203.         }
  204.         ppm_writeppmrow( stdout, pixels[row], cols, maxval, 0 );
  205.         }
  206.     }
  207.  
  208.     exit( 0 );
  209.     }
  210.