home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2171 / ppmbrighten.c < prev   
Encoding:
C/C++ Source or Header  |  1990-12-28  |  5.0 KB  |  275 lines

  1. /* ppmbrighten.c - allow user control over Value and Saturation of PPM file
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. ** Copyright (C) 1990 by Brian Moffet.
  5. **
  6. ** Permission to use, copy, modify, and distribute this software and its
  7. ** documentation for any purpose and without fee is hereby granted, provided
  8. ** that the above copyright notice appear in all copies and that both that
  9. ** copyright notice and this permission notice appear in supporting
  10. ** documentation.  This software is provided "as is" without express or
  11. ** implied warranty.
  12. */
  13.  
  14. #include <stdio.h>
  15. #include "ppm.h"
  16.  
  17. #define    MULTI    1000
  18. #define    FIND_MINMAX    1
  19. #define    SET_VALUE    2
  20. #define    SET_SATUR    4
  21.  
  22. main( argc, argv )
  23. int argc;
  24. char *argv[];
  25. {
  26.     FILE *fp = stdin;
  27.     extern char *optarg;
  28.     extern int optind;
  29.     int value = 100, saturation = 100, c, error = 0;
  30.     int min_value, max_value;
  31.     int flags = 0;
  32.  
  33.     pixel *pixelP;
  34.     pixval maxval;
  35.     int rows, cols, format, index;
  36.  
  37.  
  38.     while ((c = getopt( argc, argv, "s:v:n" )) != -1)
  39.         switch (c) 
  40.         {
  41.             case 's':
  42.                 flags |= SET_SATUR;
  43.                 saturation = 100 + atoi( optarg );
  44.                 break;
  45.             case 'v':
  46.                 flags |= SET_SATUR;
  47.                 value = 100 + atoi( optarg );
  48.                 break;
  49.             case 'n':
  50.                 flags |= FIND_MINMAX;
  51.                 break;
  52.             default:
  53.                 error = 1;
  54.                 break;
  55.         }
  56.  
  57.     if (error)
  58.     {
  59.         fprintf( stderr,
  60.         "Usage: %s [-s <+- saturation>] [-v <+- value>] <ppmfile>\n",
  61.              argv[0] );
  62.         exit( 1 );
  63.     }
  64.  
  65.     if (value < 0) value = 0;
  66.  
  67.     if (saturation < 0) saturation = 0;
  68.  
  69.     if (optind != argc)
  70.         if ((fp = fopen( argv[optind], "r" )) == NULL )
  71.         {
  72.             fprintf( stderr, "Coundn't open %s for reading\n",
  73.                 argv[optind] );
  74.             exit( 1 );
  75.         }
  76.  
  77.     if (flags & FIND_MINMAX)
  78.     {
  79.         ppm_readppminit( fp, &cols, &rows, &maxval, &format );
  80.         pixelP = ppm_allocrow( cols );
  81.         max_value = 0;
  82.         min_value = MULTI;
  83.         for (index = 0; index < rows; index++)
  84.         {
  85.             int i;
  86.             ppm_readppmrow( fp, pixelP, cols, maxval, format );
  87.             for (i = 0; i < cols; i++)
  88.             {
  89.                 int r, g, b;
  90.                 long R, G, B, H, S, V;
  91.  
  92.                 r = PPM_GETR( pixelP[i] );
  93.                 g = PPM_GETG( pixelP[i] );
  94.                 b = PPM_GETB( pixelP[i] );
  95.  
  96.                 R = (MULTI * r + maxval - 1) / maxval;
  97.                 G = (MULTI * g + maxval - 1) / maxval;
  98.                 B = (MULTI * b + maxval - 1) / maxval;
  99.  
  100.                 GetHSV( R, G, B, &H, &S, &V );
  101.                 if ( V > max_value)    max_value = V;
  102.                 if ( V < min_value)    min_value = V;
  103.             }
  104.         }
  105.         ppm_freerow( pixelP );
  106.         fprintf( stderr, "Min is %4d\tMax = %4d\n",
  107.                         min_value, max_value );
  108.         rewind( fp );
  109.     }
  110.  
  111.     ppm_readppminit( fp, &cols, &rows, &maxval, &format );
  112.  
  113.     ppm_writeppminit( stdout, cols, rows, maxval );
  114.  
  115.     pixelP = ppm_allocrow( cols );
  116.  
  117.     if (pixelP == NULL)
  118.     {
  119.         fprintf( stderr, "Error allocating Pixel row\n" );
  120.         exit( 3 );
  121.     }
  122.  
  123.     for (index = 0; index < rows; index++)
  124.     {
  125.         int i;
  126.         ppm_readppmrow( fp, pixelP, cols, maxval, format );
  127.         for (i = 0; i < cols; i++)
  128.         {
  129.             int r, g, b;
  130.             long R, G, B, H, S, V;
  131.  
  132.             r = PPM_GETR( pixelP[i] );
  133.             g = PPM_GETG( pixelP[i] );
  134.             b = PPM_GETB( pixelP[i] );
  135.  
  136.             R = (MULTI * r + maxval - 1) / maxval;
  137.             G = (MULTI * g + maxval - 1) / maxval;
  138.             B = (MULTI * b + maxval - 1) / maxval;
  139.  
  140.             GetHSV( R, G, B, &H, &S, &V );
  141.  
  142.             if (flags & FIND_MINMAX)
  143.             {
  144.                 V -= min_value;
  145.                 V = (V * MULTI) /
  146.                     (MULTI - (min_value+MULTI-max_value));
  147.             }
  148.  
  149.             S = ( S * saturation ) / 100;
  150.             V = ( V * value ) / 100;
  151.  
  152.             if (V > MULTI)
  153.                 V = MULTI;
  154.             if (S > MULTI)
  155.                 S = MULTI;
  156.  
  157.             GetRGB( H, S, V, &R, &G, &B );
  158.  
  159.             r = (R * maxval) / MULTI;
  160.             g = (G * maxval) / MULTI;
  161.             b = (B * maxval) / MULTI;
  162.  
  163.             PPM_ASSIGN( pixelP[i], r, g, b );
  164.         }
  165.  
  166.         ppm_writeppmrow( stdout, pixelP, cols, maxval );
  167.     }
  168.     ppm_freerow( pixelP );
  169.  
  170.     if (fp != stdin)
  171.         fclose( fp );
  172. }
  173.  
  174. #define    min(x,y)    ((x < y) ? x : y)
  175. #define    max(x,y)    ((x > y) ? x : y)
  176.  
  177. static int
  178. GetHSV( r, g, b, h, s, v )
  179. long r, g, b;
  180. long *h, *s, *v;
  181. {
  182.     long t;
  183.  
  184.     *v = max( r, max( g, b ) );
  185.  
  186.     t = min( r, min( g, b ) );
  187.  
  188.     if ( *v == 0 )
  189.         *s = 0;
  190.     else
  191.         *s = ( (*v - t)*MULTI ) / *v;
  192.  
  193.     if ( *s == 0 )
  194.         *h = 0;
  195.     else
  196.     {
  197.         long cr, cg, cb;
  198.         cr = (MULTI * ( *v - r ))/( *v - t );
  199.         cg = (MULTI * ( *v - g ))/( *v - t );
  200.         cb = (MULTI * ( *v - b ))/( *v - t );
  201.  
  202.         if ( r == *v )
  203.             *h = cb - cg;
  204.  
  205.         if ( g == *v )
  206.             *h = (2*MULTI) + cr - cb;
  207.  
  208.         if ( b == *v )
  209.             *h = (4*MULTI) + cg - cr;
  210.  
  211.         *h = *h * 60;
  212.         if ( *h < 0 )
  213.             *h += (360 * MULTI);
  214.     }
  215. }
  216.  
  217. static int
  218. GetRGB( h, s, v, r, g, b )
  219. long h, s, v;
  220. long *r, *g, *b;
  221. {
  222.     if ( s == 0 )
  223.     {
  224.         *r = v;
  225.         *g = v;
  226.         *b = v;
  227.     } else {
  228.         long f, m, n, k;
  229.         long i;
  230.  
  231.         if (h == (360 * MULTI))
  232.             h = 0;
  233.         h = h / 60;
  234.         i = (h - (h % MULTI));
  235.         f = h - i;
  236.         m = (v * (MULTI - s)) / MULTI;
  237.         n = (v * (MULTI - (s * f)/MULTI)) / MULTI;
  238.         k = (v * (MULTI - (s * (MULTI - f))/MULTI)) / MULTI;
  239.  
  240.         switch (i)
  241.         {
  242.             case 0:
  243.                 *r = v;
  244.                 *g = k;
  245.                 *b = m;
  246.                 break;
  247.             case MULTI:
  248.                 *r = n;
  249.                 *g = v;
  250.                 *b = m;
  251.                 break;
  252.             case (2*MULTI):
  253.                 *r = m;
  254.                 *g = v;
  255.                 *b = k;
  256.                 break;
  257.             case (3*MULTI):
  258.                 *r = m;
  259.                 *g = n;
  260.                 *b = v;
  261.                 break;
  262.             case (4*MULTI):
  263.                 *r = k;
  264.                 *g = m;
  265.                 *b = v;
  266.                 break;
  267.             case (5*MULTI):
  268.                 *r = v;
  269.                 *g = m;
  270.                 *b = n;
  271.                 break;
  272.         }
  273.     }
  274. }
  275.