/*
 * This software is copyrighted as noted below.  It may be freely copied,
 * modified, and redistributed, provided that the copyright notice is
 * preserved on all copies.
 *
 * There is no warranty or other guarantee of fitness for this software,
 * it is provided solely "as is".  Bug reports or fixes may be sent
 * to the author, who may or may not act on them as he desires.
 *
 * You may not include this software in a program or other software product
 * without supplying the source, or without informing the end-user that the
 * source is available for no extra charge.
 *
 * If you modify this software, you should include a notice giving the
 * name of the person performing the modification, the date of modification,
 * and the reason for such modification.
 */
/*
 * convolve.c - perform a convolutiion process.
 *
 * Author:      Raul Rivero
 *              Mathematics Dept.
 *              University of Oviedo
 * Date:        Sun Jan 5 1992 
 * Copyright (c) 1992, Raul Rivero
 *
 */

#include <lug.h>
#include <lugfnts.h>

extern LUGverbose;
byte *convolve();

convolve_bitmap(inbitmap, outbitmap, matrix)
bitmap_hdr *inbitmap;
bitmap_hdr *outbitmap;
double matrix[9];
{

  if ( inbitmap->magic != LUGUSED )
    error( 19 );

  /*
   * We only can manage true color or gray scaled
   * images.
   */
  if ( inbitmap->depth < 24)
    if ( ! isagrayscaled( inbitmap ) )
      error( 7 );

  /* Fill our header */
  outbitmap->magic  = LUGUSED;
  outbitmap->xsize  = inbitmap->xsize;
  outbitmap->ysize  = inbitmap->ysize;
  outbitmap->depth  = inbitmap->depth;
  outbitmap->colors = inbitmap->colors;

  VPRINTF( stderr, " Convolving R channel\n" );
  outbitmap->r = convolve( inbitmap->r,
                           outbitmap->xsize, outbitmap->ysize, matrix );
  if ( outbitmap->depth > 8 ) {
    VPRINTF( stderr, " Convolving G channel\n" );
    outbitmap->g = convolve( inbitmap->g,
                             outbitmap->xsize, outbitmap->ysize, matrix );
    VPRINTF( stderr, " Convolving B channel\n" );
    outbitmap->b = convolve( inbitmap->b,
                             outbitmap->xsize, outbitmap->ysize, matrix );
  }else {
    outbitmap->cmap = (byte *) Malloc( 3 * outbitmap->colors );
    bcopy( inbitmap->cmap, outbitmap->cmap, 3 * outbitmap->colors );
  }

  /* No errors */
  return 0;
}

byte *
convolve(buffer, xsize, ysize, matrix)
byte *buffer;
int xsize, ysize;
double matrix[9];
{
  register int i;
  int totalsize = xsize * ysize;
  byte *nbuffer;
  register byte *fin;
  register byte *base, *line_before;    /* pointers to new [blured] image */
  register byte *last, *next_line;      /* pointers to old [zoomed] image */
  double tmp;

  /* Allocate memory for new blured image */
  nbuffer= (byte *) Malloc( totalsize );

  /*
   * First and last rows, and first and last pixels in
   * each row are not modified, so we copy image into new
   * buffer and keep all information.
   */
  bcopy( buffer, nbuffer, totalsize );

  /* Skip first and last row */
  ysize--;
  for ( i = 1; i < ysize; i++ ) {
    /* Skip first pixel of current line */
    base = nbuffer + i*xsize + 1;
    /* Point to current line */
    last = buffer + i*xsize + 1;
    /* Point to line before */
    line_before = last - xsize;
    /* Point to next line */
    next_line = last + xsize;
    /*
     * Pointer to last pixel for being modified of the current
     * line ( skip last pixel ).
     */
    fin = base + xsize - 1;
    while ( base < fin ) {
      /* Blur the current pixel */
      tmp = matrix[4] * *last +
            matrix[3] * *(last-1)        + matrix[5] * *(last+1)        +
            matrix[1] * *line_before     + matrix[7] * *next_line       +
            matrix[0] * *(line_before-1) + matrix[2] * *(line_before+1) +
            matrix[6] * *(next_line-1)   + matrix[8] * *(next_line+1);
      *base++ = CORRECT( tmp );
      /* Update pointers */
      next_line++;
      line_before++;
      last++;
    }
  }

  return nbuffer;
}
