/* smooth.c:
 *
 * this performs a smoothing convolution using a 3x3 area.
 *
 * jim frost 09.20.90
 *
 * Copyright 1990, 1991 Jim Frost.
 * See included file "copyright.h" for complete copyright information.
 */

#include "copyright.h"
#include "image.h"

static Image *doSmooth(image)
     Image *image;
{ Image *old, *new;
  int    x, y, x1, y1, linelen;
  int    xindex[3];
  byte  *yindex[3];
  byte  *destptr;
  Pixel  pixval;
  unsigned long avgred, avggreen, avgblue;

  /* build true color image from old image and allocate new image
   */

  old= expand(image);
  new= newTrueImage(image->width, image->height);
  if (image->title) {
      new->title= (char *)lmalloc(strlen(image->title) + 12);
      sprintf(new->title, "%s (smoothed)", image->title);
  }

  /* run through image and take a guess as to what the color should
   * actually be.
   */

  destptr= new->data;
  linelen= old->pixlen * old->width;
  for (y= 0; y < old->height; y++) {
    yindex[1]= old->data + (y * linelen);
    yindex[0]= yindex[1] - (y > 0 ? linelen : 0);
    yindex[2]= yindex[1] + (y < old->height - 1 ? linelen : 0);
    for (x= 0; x < old->width; x++) {
      avgred= avggreen= avgblue= 0;
      xindex[1]= x * old->pixlen;
      xindex[0]= xindex[1] - (x > 0 ? old->pixlen : 0);
      xindex[2]= xindex[1] + (x < old->width - 1 ? old->pixlen : 0);
      for (y1= 0; y1 < 3; y1++) {
	for (x1= 0; x1 < 3; x1++) {
	  pixval= memToVal(yindex[y1] + xindex[x1], old->pixlen);
	  avgred += TRUE_RED(pixval);
	  avggreen += TRUE_GREEN(pixval);
	  avgblue += TRUE_BLUE(pixval);
	}
      }

      /* average the pixel values
       */

      avgred= ((avgred + 8) / 9);
      avggreen= ((avggreen + 8) / 9);
      avgblue= ((avgblue + 8) / 9);
      pixval= (avgred << 16) | (avggreen << 8) | avgblue;
      valToMem(pixval, destptr, new->pixlen);
      destptr += new->pixlen;
    }
  }

  if (old != image)
    freeImage(old);
  return(new);
}

Image *smooth(image, iterations, verbose)
     Image *image;
     int    verbose;
{ int a;
  Image *old, *new;

  if (verbose) {
    fprintf(stderr, "  Smoothing...");
    fflush(stderr);
  }

  old= image;
  for (a= 0; a < iterations; a++) {
    new= doSmooth(old);
    if (image != old)
      freeImage(old);
    old= new;
  }

  if (verbose)
    fprintf(stderr, "done\n");

  return(old);
}
