/*
 * 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.
 */
/*
 * zoom.c - Adjust a component to a given size.
 *
 * Author:      Raul Rivero
 *              Mathematics Dept.
 *              University of Oviedo
 * Date:        Mon Jan 6 1992
 * Copyright (c) 1992, Raul Rivero
 *
 */

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

extern int LUGverbose;


adjust_bitmap(inbitmap, outbitmap, newx, newy, noblur)
bitmap_hdr *inbitmap;
bitmap_hdr *outbitmap;
int newx, newy;
int noblur;
{
  if ( inbitmap->magic != LUGUSED )
    error( 19 );

  /*
   * We only can manage true color or gray scaled 
   * images. But, the mapped images are permited if 
   * no blur is required.
   */
  if ( inbitmap->depth < 24) 
    if ( ! isagrayscaled( inbitmap ) )
      noblur = 1;

  /* If the same image, copy it (!!!???) */
  if ( inbitmap->xsize == newx && inbitmap->ysize == newy ) {
    copy_bitmap( inbitmap, outbitmap );
  }else {
    /*
     * Fill new header ...
     */
    outbitmap->magic = LUGUSED;
    outbitmap->xsize = newx;
    outbitmap->ysize = newy;
    outbitmap->depth = inbitmap->depth;
    outbitmap->colors = inbitmap->colors;

    /*
     * ... and zoom each component.
     */
    VPRINTF(stderr, "Zooming R\n");
    outbitmap->r= zoom( inbitmap->xsize, inbitmap->ysize,
                        newx, newy, inbitmap->r, noblur );
    if ( inbitmap->depth > 8 ) {
      /* Yeah!, a true color image */
      VPRINTF(stderr, "Zooming G\n");
      outbitmap->g= zoom( inbitmap->xsize, inbitmap->ysize,
                          newx, newy, inbitmap->g, noblur );
      VPRINTF(stderr, "Zooming B\n");
      outbitmap->b= zoom( inbitmap->xsize, inbitmap->ysize,
                          newx, newy, inbitmap->b, noblur );
    }else {
      /* A mapped image, so copy the color map */
      outbitmap->cmap = (byte *) Malloc( 3*outbitmap->colors );
      bcopy( inbitmap->cmap, outbitmap->cmap, 3*outbitmap->colors );
    }
  }
}

byte *zoom(oldx, oldy, newx, newy, buffer, noblur)
int oldx, oldy;
int newx, newy;
register byte *buffer;
int noblur;
{
  register int i, j;
  register byte *o_base, *i_base;
  double relx, rely;
  double nrelx, nrely;
  byte *ptr;
  byte *nbuffer;
  double foldx, foldy;
  double fnewx, fnewy;

  /* Allocate memory for new zoomed image */
  o_base = nbuffer = (byte *) Malloc(newx * newy);

  /* Better perform *'s than /'s */
  fnewx = 1. / (double) newx, fnewy= 1. / (double) newy;
  /* We use double variables ( only once transformation ) */
  foldx = (double) oldx, foldy= (double) oldy;

  for ( i = 0; i < newy; i++ ) {
    /*
     * Scale row from 0 to 1 with the new image.
     */
    nrely = ((double) i) * fnewy;
    /*
     * Get equal value in old image.
     */
    rely = nrely * foldy;
    /*
     * Pointer to first pixel in that row.
     */
    i_base = buffer + ((int) rely) * oldx;
    for ( j = 0; j < newx; j++ ) {
      /* scale column from 0 to 1 ... */
      nrelx = ((double) j) * fnewx;
      /* then we get position of old image */
      relx = nrelx * foldx;
      ptr = i_base + (int) relx;
      *o_base++ = *ptr;
    }
  }

  /*
   * If image is greater then blur ( if no_blur switch
   * is actived ).
   */
  if ( (newx > oldx || newy > oldy) && !noblur ) {
    /* Blur zoomed image */
    ptr = blur( nbuffer, newx, newy );
    /* We have a new [blur] image, free first */
    free( nbuffer );
    return( ptr );
  }else {
    return( nbuffer );
  }
}
