www.pudn.com > ilib > ICopyImg.c


/*
 * ICopyImg.c
 *
 * Image library
 *
 * Description:
 *	Copy an area of an image to another image.
 *
 * History:
 *	23-Jul-99	Craig Knudsen   cknudsen@radix.net
 *			Added ICopyImageScaled
 *	11-Nov-98	Craig Knudsen	cknudsen@radix.net
 *			Allow transparent values to not be copied.
 *	20-May-96	Craig Knudsen	cknudsen@radix.net
 *			Created
 *
 ****************************************************************************/

#include 
#include 
#include 
#include 

#include "Ilib.h"
#include "IlibP.h"


IError ICopyImage ( source, dest, gc, src_x, src_y, width, height,
  dest_x, dest_y )
IImage source, dest;
IGC gc;
int src_x, src_y;
unsigned int width, height;
int dest_x, dest_y;
{
  IImageP *i1 = (IImageP *) source;
  IImageP *i2 = (IImageP *) dest;
  IGCP *gcp = (IGCP *) gc;
  int row, col, x, y;
  IColor color;
  IColorP *colorp;
  IColorP *save;
  unsigned char *ptr;

  if ( i1 ) {
    if ( i1->magic != IMAGIC_IMAGE )
      return ( IInvalidImage );
  }
  else
    return ( IInvalidImage );

  if ( i2 ) {
    if ( i2->magic != IMAGIC_IMAGE )
      return ( IInvalidImage );
  }
  else
    return ( IInvalidImage );

  if ( gcp ) {
    if ( gcp->magic != IMAGIC_GC )
      return ( IInvalidGC );
  }
  else
    return ( IInvalidGC );

  save = gcp->foreground;

  color = IAllocColor ( 0, 0, 0 );
  colorp = _IGetColor ( color );
  ISetForeground ( gc, color );

  for ( row = src_y, y = dest_y; row < src_y + height; row++, y++ ) {
    for ( col = src_x, x = dest_x; col < src_x + width; col++, x++ ) {
      if ( i1->greyscale ) {
        ptr = i1->data + ( row * i1->width ) + col;
        colorp->red = colorp->green = colorp->blue = *(ptr);
        _ISetPoint ( i2, gcp, x, y );
      }
      else {
        ptr = i1->data + ( row * i1->width * 3 ) + ( col * 3 );
        /* check for transparent color */
        if ( i1->transparent == NULL 
          || i1->transparent->red != *(ptr)
          || i1->transparent->green != *(ptr + 1)
          || i1->transparent->blue != (*ptr + 2) ) {
          colorp->red = *(ptr);
          colorp->green = *(ptr + 1);
          colorp->blue = *(ptr + 2);
          _ISetPoint ( i2, gcp, x, y );
        }
      }
    }
  }

  IFreeColor ( color );

  gcp->foreground = save;

  return ( INoError );
}




/*
** This allows the user to scale up or down the source image onto
** the destination image.
*/
IError ICopyImageScaled ( source, dest, gc,
  src_x, src_y, src_width, src_height,
  dest_x, dest_y, dest_width, dest_height )
IImage source, dest;
IGC gc;
int src_x, src_y;
unsigned int src_width, src_height;
int dest_x, dest_y;
unsigned int dest_width, dest_height;
{
  IImageP *i1 = (IImageP *) source;
  IImageP *i2 = (IImageP *) dest;
  IGCP *gcp = (IGCP *) gc;
  int x, y, x2, y2;
  IColor color;
  IColorP *colorp;
  IColorP *save;
  unsigned char *ptr;
  double scalex, scaley;
  double tempx, tempy;

  if ( i1 ) {
    if ( i1->magic != IMAGIC_IMAGE )
      return ( IInvalidImage );
  }
  else
    return ( IInvalidImage );

  if ( i2 ) {
    if ( i2->magic != IMAGIC_IMAGE )
      return ( IInvalidImage );
  }
  else
    return ( IInvalidImage );

  if ( gcp ) {
    if ( gcp->magic != IMAGIC_GC )
      return ( IInvalidGC );
  }
  else
    return ( IInvalidGC );

  save = gcp->foreground;

  color = IAllocColor ( 0, 0, 0 );
  colorp = _IGetColor ( color );
  ISetForeground ( gc, color );

  /*
  ** When scaling down, we might want to add an algorithm for averaging
  ** a series of source pixels into the destination pixel.  For now,
  ** we just grab one color.
  */
  scalex = (double) dest_width / (double) src_width;
  scaley = (double) dest_height / (double) src_height;
  for ( y = dest_y; y < dest_y + dest_height; y++ ) {
    for ( x = dest_x; x < dest_x + dest_width; x++ ) {
      /* get location from source image for this location
      ** x2,y2 is location in source image.
      */
      tempx = (double) src_x + (double) ( x - dest_x ) / scalex;
      x2 = (int) tempx;
      tempy = (double) src_y + (double) ( y - dest_y ) / scaley;
      y2 = (int) tempy;
      if ( i1->greyscale ) {
        ptr = i1->data + ( y2 * i1->width ) + x2;
        colorp->red = colorp->green = colorp->blue = *(ptr);
        _ISetPoint ( i2, gcp, x, y );
      }
      else {
        ptr = i1->data + ( y2 * i1->width * 3 ) + ( x2 * 3 );
        /* check for transparent color */
        if ( i1->transparent == NULL 
          || i1->transparent->red != *(ptr)
          || i1->transparent->green != *(ptr + 1)
          || i1->transparent->blue != (*ptr + 2) ) {
          colorp->red = *(ptr);
          colorp->green = *(ptr + 1);
          colorp->blue = *(ptr + 2);
          _ISetPoint ( i2, gcp, x, y );
        }
      }
    }
  }

  IFreeColor ( color );

  gcp->foreground = save;

  return ( INoError );
}