home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 309.lha / PBM_PLUS / ppm / ppmconvol.c < prev    next >
C/C++ Source or Header  |  1980-12-04  |  4KB  |  144 lines

  1. /* ppmconvol.c - general MxN convolution on a portable pixmap
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include "ppm.h"
  15.  
  16. main( argc, argv )
  17. int argc;
  18. char *argv[];
  19.     {
  20.     FILE *cifd, *ifd;
  21.     pixel **cpixels, **pixelbuf, *outputrow, p;
  22.     int argn, crows, ccols, ccolso2, crowso2, rows, cols, format, crow, row;
  23.     register int ccol, col;
  24.     pixval cmaxval, maxval, r, g, b;
  25.     float **rweights, **gweights, **bweights, rsum, gsum, bsum;
  26.     char *usage = "<convolutionfile> [ppmfile]";
  27.  
  28.     pm_progname = argv[0];
  29.  
  30.     argn = 1;
  31.  
  32.     if ( argn == argc )
  33.     pm_usage( usage );
  34.     cifd = pm_openr( argv[argn] );
  35.     argn++;
  36.  
  37.     if ( argn != argc )
  38.     {
  39.     ifd = pm_openr( argv[argn] );
  40.     argn++;
  41.     }
  42.     else
  43.     ifd = stdin;
  44.  
  45.     if ( argn != argc )
  46.     pm_usage( usage );
  47.  
  48.     ppm_pbmmaxval = 255;    /* use larger value for better results */
  49.  
  50.     /* Read in the convolution matrix. */
  51.     cpixels = ppm_readppm( cifd, &ccols, &crows, &cmaxval );
  52.     pm_close( cifd );
  53.     if ( ccols % 2 != 1 || crows % 2 != 1 )
  54.     pm_error(
  55.         "the convolution matrix must have an odd number of rows and columns",
  56.         0,0,0,0,0 );
  57.     ccolso2 = ccols / 2;
  58.     crowso2 = crows / 2;
  59.  
  60.     ppm_readppminit( ifd, &cols, &rows, &maxval, &format );
  61.     if ( cols < ccols || rows < crows )
  62.     pm_error(
  63.         "the image is smaller than the convolution matrix", 0,0,0,0,0 );
  64.  
  65.     /* Set up the normalized weights. */
  66.     rweights = (float **) pm_allocarray( ccols, crows, sizeof(float) );
  67.     gweights = (float **) pm_allocarray( ccols, crows, sizeof(float) );
  68.     bweights = (float **) pm_allocarray( ccols, crows, sizeof(float) );
  69.     rsum = gsum = bsum = 0;
  70.     for ( crow = 0; crow < crows; crow++ )
  71.     for ( ccol = 0; ccol < ccols; ccol++ )
  72.         {
  73.         rsum += rweights[crow][ccol] =
  74.         ( PPM_GETR(cpixels[crow][ccol]) * 2.0 / cmaxval - 1.0 );
  75.         gsum += gweights[crow][ccol] =
  76.         ( PPM_GETG(cpixels[crow][ccol]) * 2.0 / cmaxval - 1.0 );
  77.         bsum += bweights[crow][ccol] =
  78.         ( PPM_GETB(cpixels[crow][ccol]) * 2.0 / cmaxval - 1.0 );
  79.         }
  80.     if ( rsum < 0.9 || rsum > 1.1 || gsum < 0.9 || gsum > 1.1 ||
  81.      bsum < 0.9 || bsum > 1.1 )
  82.     fprintf( stderr, "WARNING: this convolution matrix is biased.\n" );
  83.  
  84.     /* Allocate space for one convolution-matrix's worth of rows, plus
  85.     ** a row output buffer. */
  86.     pixelbuf = ppm_allocarray( cols, crows );
  87.     outputrow = ppm_allocrow( cols );
  88.  
  89.     ppm_writeppminit( stdout, cols, rows, maxval );
  90.  
  91.     /* Read in one convolution-matrix's worth of image, less one row. */
  92.     for ( row = 0; row < crows - 1; row++ )
  93.     {
  94.     ppm_readppmrow( ifd, pixelbuf[row], cols, maxval, format );
  95.     /* Write out just the part we're not going to convolve. */
  96.     if ( row < crowso2 )
  97.         ppm_writeppmrow( stdout, pixelbuf[row], cols, maxval );
  98.     }
  99.  
  100.     /* Now the rest of the image -- read in the row at the end of
  101.     ** pixelbuf, and convolve and write out the row in the middle.
  102.     */
  103.     for ( ; row < rows; row++ )
  104.     {
  105.     ppm_readppmrow( ifd, pixelbuf[row % crows], cols, maxval, format );
  106.  
  107.     for ( col = 0; col < cols; col++ )
  108.         if ( col < ccolso2 || col >= cols - ccolso2 )
  109.         outputrow[col] = pixelbuf[(row - crowso2) % crows][col];
  110.         else
  111.         {
  112.         rsum = gsum = bsum = 0.0;
  113.         for ( crow = 0; crow < crows; crow++ )
  114.             for ( ccol = 0; ccol < ccols; ccol++ )
  115.             {
  116.             p = pixelbuf[(row+1+crow) % crows][col-ccolso2+ccol];
  117.             rsum += PPM_GETR( p ) * rweights[crow][ccol];
  118.             gsum += PPM_GETG( p ) * gweights[crow][ccol];
  119.             bsum += PPM_GETB( p ) * bweights[crow][ccol];
  120.             }
  121.         if ( rsum < 0.0 ) r = 0;
  122.         else if ( rsum > maxval ) r = maxval;
  123.         else r = rsum + 0.5;
  124.         if ( gsum < 0.0 ) g = 0;
  125.         else if ( gsum > maxval ) g = maxval;
  126.         else g = gsum + 0.5;
  127.         if ( bsum < 0.0 ) b = 0;
  128.         else if ( bsum > maxval ) b = maxval;
  129.         else b = bsum + 0.5;
  130.         PPM_ASSIGN( outputrow[col], r, g, b );
  131.         }
  132.  
  133.     ppm_writeppmrow( stdout, outputrow, cols, maxval );
  134.     }
  135.     pm_close( ifd );
  136.  
  137.     /* Now write out the remaining unconvolved rows in pixelbuf. */
  138.     for ( ; row < rows + crowso2; row++ )
  139.     ppm_writeppmrow(
  140.         stdout, pixelbuf[(row - crowso2) % crows], cols, maxval );
  141.  
  142.     exit( 0 );
  143.     }
  144.