I43 Answer ― Edge Handling


#include <stdlib.h>
#include <stdio.h>
#include "basicImage.c"

/* Puzzle43.c -- Smooth 3x3 with Edge Handling
|
| This is the easy solution that uses lots of statements
| for all the special cases of edges and corners.
|
*/

#include 
#include 
#include "../basicImage.c"

void smoothImage( image img, image smooth )
{
  int r, c, sum;
  unsigned char value ;

  /* Upper Left corner */
  r=0; c=0;
  sum  = getPixel( img, r  , c   );
  sum += getPixel( img, r  , c+1 );
  sum += getPixel( img, r+1, c   );
  sum += getPixel( img, r+1, c+1 );
  setPixel( smooth, r, c, sum/4 );

  /* Upper Right corner */
  r=0; c=img.ncols-1;
  sum  = getPixel( img, r  , c-1 );
  sum += getPixel( img, r  , c   );
  sum += getPixel( img, r+1, c-1 );
  sum += getPixel( img, r+1, c   );
  setPixel( smooth, r, c, sum/4 );

  /* Lower Left corner */
  r=img.nrows-1; c=0;
  sum  = getPixel( img, r-1, c   );
  sum += getPixel( img, r-1, c+1 );
  sum += getPixel( img, r  , c   );
  sum += getPixel( img, r  , c+1 );
  setPixel( smooth, r, c, sum/4 );

  /* Lower Right corner */
  r=img.nrows-1; c=img.ncols-1;
  sum  = getPixel( img, r-1, c-1 );
  sum += getPixel( img, r-1, c   );
  sum += getPixel( img, r  , c-1 );
  sum += getPixel( img, r  , c   );
  setPixel( smooth, r, c, sum/4 );

  /* Deal with top and bottom edges */
  for ( c=1; c<img.ncols-1; c++ )
  {
    r=0;
    sum  = getPixel( img, r  , c-1 );
    sum += getPixel( img, r  , c   );
    sum += getPixel( img, r  , c+1 );
    sum += getPixel( img, r+1, c-1 );
    sum += getPixel( img, r+1, c   );
    sum += getPixel( img, r+1, c+1 );
    setPixel( smooth, r, c, sum/6 );

    r=img.nrows-1;
    sum  = getPixel( img, r-1, c-1 );
    sum += getPixel( img, r-1, c   );
    sum += getPixel( img, r-1, c+1 );
    sum += getPixel( img, r  , c-1 );
    sum += getPixel( img, r  , c   );
    sum += getPixel( img, r  , c+1 );
    setPixel( smooth, r, c, sum/6 );
  }

  /* Deal with left and right edges */
  for ( r=1; r<img.nrows-1; r++ )
  {
    c=0;
    sum  = getPixel( img, r-1, c   );
    sum += getPixel( img, r-1, c+1 );
    sum += getPixel( img, r  , c   );
    sum += getPixel( img, r  , c+1 );
    sum += getPixel( img, r+1, c   );
    sum += getPixel( img, r+1, c+1 );
    setPixel( smooth, r, c, sum/6 );

    c=img.ncols-1;
    sum  = getPixel( img, r-1, c-1 );
    sum += getPixel( img, r-1, c   );
    sum += getPixel( img, r  , c-1 );
    sum += getPixel( img, r  , c   );
    sum += getPixel( img, r+1, c-1 );
    sum += getPixel( img, r+1, c   );
    setPixel( smooth, r, c, sum/6 );
  }

  /* Fill in the center with neighborhood averages */
  for ( r=1; r<img.nrows-1; r++ )
    for ( c=1; c<img.ncols-1; c++ )
    {
      sum  = getPixel( img, r-1, c-1 );
      sum += getPixel( img, r-1, c   );
      sum += getPixel( img, r-1, c+1 );
      sum += getPixel( img, r  , c-1 );
      sum += getPixel( img, r  , c   );
      sum += getPixel( img, r  , c+1 );
      sum += getPixel( img, r+1, c-1 );
      sum += getPixel( img, r+1, c   );
      sum += getPixel( img, r+1, c+1 );

      setPixel( smooth, r, c, sum/9 );
    }
}

int main ( int argc, char* argv[] )
{
  image img, smimg;
  
  if ( argc != 3 )
  {
    printf( "smoothE oldImage smoothImage\n" );
    system( "pause" );
    exit( EXIT_FAILURE );
  }
  
  /* read in the image */
  readPGMimage( &img, argv[1] );

  /* create a blank image */
  newImage( &smimg, img.nrows, img.ncols );

  /* fill in values for the new image */
  smoothImage( img, smimg );
  
  /* write the image to disk and free memory */
  writePGMimage( smimg, argv[2] );
  freeImage( &img );
  freeImage( &smimg );
}


Comments: The hard solution might actually be easier. It certainly is shorter:

void smoothImage( image img, image smooth )
{
  int r, ri, c, ci, sum, count;
  unsigned char value ;

  /* Find all neighborhood averages */
  for ( r=0; r<img.nrows; r++ )
    for ( c=0; c<img.ncols; c++ )
    {
      sum = 0; count = 0;
      for ( ri= -1; ri<=1; ri++ )
        if ( r+ri >=0 && r+ri < img.nrows )
          for ( ci= -1; ci<=1; ci++ )
            if ( c+ci >=0 && c+ci < img.ncols )
            {
              sum += getPixel( img, r+ri, c+ci );
              count++ ;
            }

      setPixel( smooth, r, c, sum/count );
    }
}