/***********************************************************************
 *
 * $Id: labScale.cc,v 1.2 2000/09/20 13:00:23 uli Exp $
 *
 * $Author: uli $
 * $Revision: 1.2 $
 * $State: Exp $
 * $Date: 2000/09/20 13:00:23 $
 *
 ***********************************************************************
 *
 * $Log: labScale.cc,v $
 * Revision 1.2  2000/09/20 13:00:23  uli
 * *** empty log message ***
 *
 * Revision 1.1  2000/07/10 04:02:05  uli
 * Picture library
 *
 * Revision 1.2  1997/07/25  16:43:00  mehren
 * Cast operator added (required by ANSI C++).
 *
 * Revision 1.1  1996/10/30  14:37:49  mehren
 * In 'scaleTIP' interlace mode removed.
 *
 * Revision 1.0  1996/05/27  15:38:48  mehren
 * FrameWork: Basic Datatypes and Functions.
 *
 **********************************************************************/

#include <stdlib.h>
#include <string.h>


#include "labScale.h"

/* cut out & scaling for monochrome format (YYYYY.....). */
unsigned char *scaleMONO( unsigned char    *imageData,
                          int imageW, int imageH, int sourceX, 
                          int sourceY, int sourceW, int sourceH,
                          unsigned char *destData, int destW, int destH)
{
  register int   x, y;           /*Current position in the new Image  */
  register int   i, j;           /*Countervariables                   */
  register float shareX, shareY; /*part of a pixel in the original    */
  register float share;          /*Image supporting the new Image     */
  register float x1, x2, y1, y2; /*Auxiliaries                        */
  int            imageArea;      /*Area of the original Image         */
  int            sourceArea;     /*Area of the Source-Rectangle       */
  int            destArea;       /*Area of the destination Image      */
  unsigned char *image;          /*Imagedata                          */
  unsigned char *imageOffs;      /*Pointer to the current Pixel       */
  unsigned char *dest;           /*Destination-Image Data             */
  int            intens;         /*Intensity Accumulator for one Pixel*/
  int            autoscale=0;    /*Auxiliary                          */

  if ((sourceH<=0) | (sourceW<=0)) return NULL;

  imageArea=imageW*imageH;
  sourceArea=sourceW*sourceH;
  destArea=destW*destH;

  if (destW<=0)
  { if (sourceW<sourceH)
    { destW=destH*sourceW/sourceH;
      destArea=destH*destH;
      autoscale=destH-destW;
    }
    if (sourceW>=sourceH)
    { destW=destH;
      destH=destW*sourceH/sourceW;
      destArea=destW*destW;
    }
  }
  if (destH<=0)
  { if (sourceW<sourceH)
    { destH=destW;
      destW=destH*sourceW/sourceH;
      destArea=destH*destH;
      autoscale=destH-destW;
    }
    if (sourceW>=sourceH)
    { destH=destW*sourceH/sourceW;
      destArea=destW*destW;
    }
  }

  memset((char *)destData, 0, (unsigned int)destArea);

  image=imageData;

  dest=destData;

  destArea=destW*destH;/*!!*/

  y1 = y2 = (float)sourceY;

  for (y=0; y<destH; y++)
  { 
    y2+=(float)sourceH/destH;

    x1 = x2 = (float)sourceX;
    for (x=0; x<destW; x++)
    { 

      x2+=(float)sourceW/destW;
      intens=0;
      for (j=(int)y1; ((float)j)<y2; j++)
      { 
        imageOffs=image+j*imageW+(int)x1;
       
        for (i=(int)x1; ((float)i)<x2; i++)
        { 
          shareX=shareY=1.0;

          if (i+1>x2) shareX=x2-i;
          if (i<x1) shareX+=i-x1;    
          if (j+1>y2) shareY=y2-j;
          if (j<y1) shareY+=j-y1;
          
          share=shareX*shareY*destArea;
          intens+=(int)((*imageOffs++)*share);
        }
      }
      x1=x2;

      *dest++=(unsigned char)(intens/sourceArea);
    }

    if (autoscale)
    {
      dest+=autoscale;
    }
    y1=y2;

  }
  return destData;
}




/* cut out & scaling for RGB format (RGBRGBRGB...) */
unsigned char *scaleRGB( unsigned char    *imageData, int imageW, 
                         int imageH, int sourceX, int sourceY, 
                         int sourceW, int sourceH, 
                         unsigned char *destData, int destW, int destH)
{
  register int   x, y;           /*Current position in the new Image  */
  register int   i, j;           /*Countervariables                   */
  register float shareX, shareY; /*part of a pixel in the original    */
  register float share;          /*Image supporting the new Image     */
  register float x1, x2, y1, y2; /*Auxiliaries                        */
  int            imageArea;      /*Area of the original Image         */
  int            sourceArea;     /*Area of the Source-Rectangle       */
  int            destArea;       /*Area of the destination Image      */
  unsigned char *image;          /*Imagedata                          */
  unsigned char *imageOffs;      /*Pointer to the current Pixel       */
  unsigned char *dest;           /*Destination-Image Data             */
  int            intensRed;      /*Intensity Accumulator for one Pixel*/
  int            intensGreen;    /*Divided into the 3 Colorchannels   */
  int            intensBlue;     /*                                   */
  int            autoscale=0;    /*Auxiliary                          */
 
  if ((sourceH<=0) | (sourceW<=0)) return NULL;

  imageArea=imageW*imageH;
  sourceArea=sourceW*sourceH;
  destArea=destW*destH;

  if (destW<=0)
  { if (sourceW<sourceH)
    { destW=destH*sourceW/sourceH;
      destArea=destH*destH;
      autoscale=destH-destW;
    }
    if (sourceW>=sourceH)
    { destW=destH;
      destH=destW*sourceH/sourceW;
      destArea=destW*destW;
    }
  }
  if (destH<=0)
  { if (sourceW<sourceH)
    { destH=destW;
      destW=destH*sourceW/sourceH;
      destArea=destH*destH;
      autoscale=destH-destW;
    }
    if (sourceW>=sourceH)
    { destH=destW*sourceH/sourceW;
      destArea=destW*destW;
    }
  }

  memset((char *)destData, 0, (unsigned int)(destArea*3));

  image=imageData;

  dest=destData;

  destArea=destW*destH;/*!!*/

  y1 = y2 = (float)sourceY;

  for (y=0; y<destH; y++)
  { 
    y2+=(float)sourceH/destH;

    x1 = x2 = (float)sourceX;
    for (x=0; x<destW; x++)
    { 
      x2+=(float)sourceW/destW;
      intensRed=intensGreen=intensBlue=0;
      for (j=(int)y1; ((float)j)<y2; j++)
      { 
        imageOffs=image+(j*imageW+(int)x1)*3;
       
        for (i=(int)x1; ((float)i)<x2; i++)
        { 
          shareX=shareY=1.0;

          if (i+1>x2) shareX=x2-i;
          if (i<x1) shareX+=i-x1;    
          if (j+1>y2) shareY=y2-j;
          if (j<y1) shareY+=j-y1;
          
          share=shareX*shareY*destArea;
          intensRed  +=(int)((*imageOffs++)*share);
          intensGreen+=(int)((*imageOffs++)*share);
          intensBlue +=(int)((*imageOffs++)*share);
        }
      }
      x1=x2;

      *dest++=(unsigned char)(intensRed/sourceArea);
      *dest++=(unsigned char)(intensGreen/sourceArea);
      *dest++=(unsigned char)(intensBlue/sourceArea);
    }

    if (autoscale)
    {
      dest+=autoscale;
      dest+=autoscale;
      dest+=autoscale;
    }
    y1=y2;

  }
  return destData;
}

int scaleMONO_int( unsigned char *imageData, int imageW, int imageH, 
                   int sourceX, int sourceY, int sourceW, int sourceH,
                          unsigned char *destData, int destW, int destH)
{
  register int   xshare, yshare; /*part of a pixel in the original    */
  register int   x, y;           /*Current position in the new Image  */
  register int   x1, y1;         /*Auxiliaries                        */
  int            destArea;       /*Area of the destination Image      */
  unsigned char *image ;         /*Imagedata                          */
  unsigned char *dest;           /*Destination-Image Data             */
  int            intens;         /*Intensity Accumulator for one Pixel*/
  int            autoscale=0;    /*Auxiliary                          */
  int            yn, xn, xo, yo; /*Auxiliaries                        */
  int            firsty, lasty;  /*Auxiliaries                        */
  int            firstx, lastx;  /*Auxiliaries                        */

  if ((sourceH<=0) | (sourceW<=0)) return(0);
  if(imageW < sourceX + sourceW)   return(0);
  if(imageH < sourceY + sourceH)   return(0);
  destArea = destW * destH;
  if (destW <= 0)
  { 
    if (sourceW < sourceH)
    { 
      destW = destH * sourceW / sourceH;
      destArea = destH * destH;
      autoscale = destH-destW;
    }
    if (sourceW >= sourceH)
    { 
      destW = destH;
      destH = destW * sourceH / sourceW;
      destArea = destW * destW;
    }
  }
  if (destH <= 0)
  {
    if (sourceW < sourceH)
    { 
      destH = destW;
      destW = destH * sourceW / sourceH;
      destArea = destH * destH;
      autoscale = destH - destW;
    }
    if (sourceW >= sourceH)
    {
      destH = destW * sourceH / sourceW;
      destArea = destW * destW;
    }
  }
  /*ClearImage*/
  memset((char *)destData, 0, (unsigned int)destArea);
  image = imageData;
  dest = destData;


  yn = 0;
  for (y = 0; y < destH; yn += sourceH, y++)
  {
    xn = 0;
    for(x = 0; x < destW; xn += sourceW, x++)
    {
      intens = 0;
      firsty = yn/destH;
      lasty  = (yn+sourceH)/destH;
      if(lasty == sourceH) lasty--;
      yo = firsty*destH;
      for(y1 = firsty; y1 <= lasty; yo += destH, y1++)
      {
        firstx = xn/destW;
        lastx  = (xn+sourceW)/destW;
        if(lastx == sourceW) lastx--;
        xo = firstx*destW;
        for(x1 = firstx; x1 <= lastx; xo += destW, x1++)
        {
          yshare = destH;
          if(yo           < yn        ) yshare -= yn - yo;
          if((yo+destH) > (yn+sourceH)) yshare-=(yo+destH)-(yn+sourceH);
          xshare = destW;
          if(xo           <       xn) xshare -= xn - xo; 
          if((xo+destW) > xn+sourceW) xshare -= (xo+destW)-(xn+sourceW);
          intens += xshare*yshare*image[(y1+sourceY)*imageW+x1+sourceX];
        }
      }
      *dest++ = (unsigned char)(intens/(sourceH*sourceW)); 
    }
    if(autoscale) dest += autoscale;
  }
  return(1);
}


int scaleRGB_int( unsigned char *imageData, int imageW, int imageH, 
                   int sourceX, int sourceY, int sourceW, int sourceH,
                          unsigned char *destData, int destW, int destH)
{
  register int   xshare, yshare; /*part of a pixel in the original    */
  register int   x, y;           /*Current position in the new Image  */
  register int   x1, y1;         /*Auxiliaries                        */
  int            destArea;       /*Area of the destination Image      */
  unsigned char *image ;         /*Imagedata                          */
  unsigned char *dest;           /*Destination-Image Data             */
  int            intensR;        /*Intensity Accumulator for one Pixel*/
  int            intensG;        /*for the different Colors           */
  int            intensB;        /*                                   */
  int            autoscale=0;    /*Auxiliary                          */
  int            yn, xn, xo, yo; /*Auxiliaries                        */
  int            firsty, lasty;  /*Auxiliaries                        */
  int            firstx, lastx;  /*Auxiliaries                        */
  int            val;            /*Auxiliary                          */
  
  if ((sourceH<=0) | (sourceW<=0)) return(0);
  if(imageW < sourceX + sourceW)   return(0);
  if(imageH < sourceY + sourceH)   return(0);
  destArea = destW * destH;
  if (destW <= 0)
  { 
    if (sourceW < sourceH)
    { 
      destW = destH * sourceW / sourceH;
      destArea = destH * destH;
      autoscale = destH-destW;
    }
    if (sourceW >= sourceH)
    { 
      destW = destH;
      destH = destW * sourceH / sourceW;
      destArea = destW * destW;
    }
  }
  if (destH <= 0)
  {
    if (sourceW < sourceH)
    { 
      destH = destW;
      destW = destH * sourceW / sourceH;
      destArea = destH * destH;
      autoscale = destH - destW;
    }
    if (sourceW >= sourceH)
    {
      destH = destW * sourceH / sourceW;
      destArea = destW * destW;
    }
  }
  /*ClearImage*/
  memset((char *)destData, 0, (unsigned int)destArea);
  image = imageData;
  dest = destData;


  yn = 0;
  for (y = 0; y < destH; yn += sourceH, y++)
  {
    xn = 0;
    for(x = 0; x < destW; xn += sourceW, x++)
    {
      intensR = 0;
      intensG = 0;
      intensB = 0;
      firsty = yn/destH;
      lasty  = (yn+sourceH)/destH;
      if(lasty == sourceH) lasty--;
      yo = firsty*destH;
      for(y1 = firsty; y1 <= lasty; yo += destH, y1++)
      {
        firstx = xn/destW;
        lastx  = (xn+sourceW)/destW;
        if(lastx == sourceW) lastx--;
        xo = firstx*destW;
        for(x1 = firstx; x1 <= lastx; xo += destW, x1++)
        {
          yshare = destH;
          if(yo           < yn        ) yshare -= yn - yo;
          if((yo+destH) > (yn+sourceH)) yshare-=(yo+destH)-(yn+sourceH);
          xshare = destW;
          if(xo           <       xn) xshare -= xn - xo; 
          if((xo+destW) > xn+sourceW) xshare -= (xo+destW)-(xn+sourceW);
          val = 3*((y1+sourceY)*imageW+x1+sourceX);
          intensR+=xshare*yshare*image[val];
          intensG+=xshare*yshare*image[val+1];
          intensB+=xshare*yshare*image[val+2];
        }
      }
      *dest++ = (unsigned char)(intensR/(sourceH*sourceW)); 
      *dest++ = (unsigned char)(intensG/(sourceH*sourceW)); 
      *dest++ = (unsigned char)(intensB/(sourceH*sourceW));
    }
    if(autoscale) dest += 3*autoscale;
  }
  return(1);
}

/*Positive samplefactor -> subsampling, negative -> enlarging         */
int subsample_mono(unsigned char *p_image, int imageW, int imageH, 
              int sourceX, int sourceY, int sourceW, int sourceH,
              unsigned char *p_destData, int samplefactorx, 
          int samplefactory)
{
  int            ii, jj, kk, ll;  /*Countervariables                  */
  int            xno, yno;        /*full pixels x-Dir, y-Dir          */
  int            ovx, ovy;        /*Additional Pixel only partly cover*/
  int            lineoffset;      /*Jumpoffset to new line in origimg */
  int            newx;            /*New Width of the subsampled Image */
  int            yoff;            /*Jumpvalue in y-Direction          */
  int            wert;            /*Accumulated New Pixelvalue        */
  unsigned char *p_data, *p_data2;/*Image-Data-Pointers               */
  
  if(!p_image || !p_destData )         return(0);
  if(!samplefactorx || !samplefactory) return(0);
  if((sourceX < 0) || (sourceY < 0))   return(0);
  if((sourceX + sourceW) > imageW)     return(0);
  if((sourceY + sourceH) > imageH)     return(0);
  
  
  lineoffset = imageW - sourceW;
  p_data     = p_image + sourceY * imageW + sourceX;
  p_data2    = p_destData;
  
  /*Both directions subsampling*/
  if((samplefactorx > 0) && (samplefactory > 0))
  {
    xno = sourceW/samplefactorx;
    yno = sourceH/samplefactory;
    ovx = sourceW%samplefactorx;
    ovy = sourceH%samplefactory;
    
    for(ii = 0; ii < yno; ii++)
    {
      for(jj = 0; jj < xno; jj++)
      {
        wert = 0;
        for(kk = 0; kk < samplefactory; kk++)
    {
      for(ll = 0; ll < samplefactorx; ll++)
      {
        wert += *p_data++;
      }
      p_data += (imageW-samplefactorx);
    }
    p_data -= samplefactory * imageW - samplefactorx;
    *p_data2++ = (unsigned char)(wert/(samplefactory*samplefactorx));
      }
      if(ovx)
      {
        wert = 0;
        for(kk = 0; kk < samplefactory; kk++)
    {
      for(ll = 0; ll < ovx; ll++)
      {
        wert += *p_data++;
      }
      p_data += (imageW-ovx);
    }
    p_data -= samplefactory * imageW - ovx;
    *p_data2++ = (unsigned char)(wert/(samplefactory*ovx));
      }
      p_data += lineoffset + (samplefactory-1)*imageW;
    }
    if(ovy)
    {
      for(jj = 0; jj < xno; jj++)
      {
        wert = 0;
        for(kk = 0; kk < ovy; kk++)
    {
      for(ll = 0; ll < samplefactorx; ll++)
      {
        wert += *p_data++;
      }
      p_data += (imageW-samplefactorx);
    }
    p_data -= ovy * imageW - samplefactorx;
    *p_data2++ = (unsigned char)(wert/(ovy*samplefactorx));
      }
      if(ovx)
      {
        wert = 0;
        for(kk = 0; kk < ovy; kk++)
    {
      for(ll = 0; ll < ovx; ll++)
      {
        wert += *p_data++;
      }
      p_data += (imageW-ovx);
    }
    p_data -= ovy * imageW - ovx;
    *p_data2++ = (unsigned char)(wert/(ovy*ovx));
      }
    }
  }
  /*Both directions upsampling*/
  else if ((samplefactorx < 0) && (samplefactory < 0))
  {
    samplefactorx = -samplefactorx;
    samplefactory = -samplefactory;
    newx = samplefactorx * sourceW;
    yoff = newx * samplefactory - samplefactorx;
    for(ii = 0; ii < sourceH; ii++)
    {
      for(jj = 0; jj < sourceW; jj++)
      {
        for(kk = 0; kk < samplefactory; kk++)
    {
      memset(p_data2, *p_data, samplefactorx);
      p_data2 += newx;
    }
    p_data2 -= yoff;
    p_data++;
      }
      p_data2 += samplefactorx * samplefactory * sourceW - newx;
      p_data  += lineoffset;
    }
  }
  else if(samplefactorx > 0 )
  {
    xno = sourceW/samplefactorx;
    samplefactory *= -1;
    ovx = sourceW%samplefactorx;
    newx = xno;
    if(ovx) newx++;
    for(ii = 0; ii < sourceH; ii++)
    {
      for(jj = 0; jj < xno; jj++)
      {
        wert = 0;
    for(ll = 0; ll < samplefactorx; ll++)
    {
      wert += *p_data++;
    }    
    *p_data2++ = (unsigned char)(wert/samplefactorx);
      }
      if(ovx)
      {
        wert = 0;
    for(ll = 0; ll < ovx; ll++)
    {
      wert += *p_data++;
    }
    *p_data2++ = (unsigned char)(wert/ovx);
      }
      p_data += lineoffset;
      p_data2 -= newx;
      for(kk = 0; kk < samplefactory; kk++)
      {
        memcpy(p_data2+kk*newx, p_data2, newx);
      }
      p_data2 += newx * samplefactory;
    }
  }
  else /*x-up, y-down*/
  {
    yno = sourceH/samplefactory;
    ovy = sourceH%samplefactory;
    
    samplefactorx *= -1;
    
    for(ii = 0; ii < yno; ii++)
    {
      for(jj = 0; jj < sourceW; jj++)
      {
        wert = 0;
    for(kk = 0; kk < samplefactory; kk++)
    {
      wert += *p_data;
      p_data += imageW;
    }    
    *p_data2 = (unsigned char)(wert/samplefactory);
    memset(p_data2, *p_data2, samplefactorx);
    p_data2 += samplefactorx;
        p_data -= imageW * samplefactory - 1;
      }
      p_data += imageW * (samplefactory - 1) + lineoffset;
    }
    if(ovy)
    {
      for(jj = 0; jj < sourceW; jj++)
      {
        wert = 0;
    for(kk = 0; kk < ovy; kk++)
    {
      wert += *p_data;
      p_data += imageW;
    }    
    *p_data2 = (unsigned char)(wert/ovy);
     memset(p_data2, *p_data2, samplefactorx);
    p_data2 += samplefactorx;
    p_data -= imageW * ovy - 1;
      }
    }
  }
  return(1);
}


/*Positive samplefactor -> subsampling, negative -> enlarging         */
int subsample_rgb(unsigned char *p_image, int imageW, int imageH, 
              int sourceX, int sourceY, int sourceW, int sourceH,
              unsigned char *p_destData, int samplefactorx, 
          int samplefactory)
{
  int            ii, jj, kk, ll;  /*Countervariables                  */
  int            xno, yno;        /*full pixels x-Dir, y-Dir          */
  int            ovx, ovy;        /*Additional Pixel only partly cover*/
  int            lineoffset;      /*Jumpoffset to new line in origimg */
  int            newx;            /*New Width of the subsampled Image */
  int            yoff;            /*Jumpvalue in y-Direction          */
  int            wertr;           /*Accumulated New Pixelvalue red    */
  int            wertg;           /*Accumulated New Pixelvalue green  */
  int            wertb;           /*Accumulated New Pixelvalue blue   */
  unsigned char *p_data, *p_data2;/*Image-Data-Pointers               */
  
  if(!p_image || !p_destData )         return(0);
  if(!samplefactorx || !samplefactory) return(0);
  if((sourceX < 0) || (sourceY < 0))   return(0);
  if((sourceX + sourceW) > imageW)     return(0);
  if((sourceY + sourceH) > imageH)     return(0);
  
  
  lineoffset = imageW - sourceW;
  p_data     = p_image + 3*(sourceY * imageW + sourceX);
  p_data2    = p_destData;
  
  /*Both directions subsampling*/
  if((samplefactorx > 0) && (samplefactory > 0))
  {
    xno = sourceW/samplefactorx;
    yno = sourceH/samplefactory;
    ovx = sourceW%samplefactorx;
    ovy = sourceH%samplefactory;
    
    for(ii = 0; ii < yno; ii++)
    {
      for(jj = 0; jj < xno; jj++)
      {
        wertr = wertg = wertb = 0;
        for(kk = 0; kk < samplefactory; kk++)
	{
	  for(ll = 0; ll < samplefactorx; ll++)
	  {
            wertr += *p_data++;
            wertg += *p_data++;
            wertb += *p_data++;
	  }
	  p_data += 3*(imageW-samplefactorx);
	}
	p_data -= 3*(samplefactory * imageW - samplefactorx);
	*p_data2++ = (unsigned char)(wertr/(samplefactory*samplefactorx));
	*p_data2++ = (unsigned char)(wertg/(samplefactory*samplefactorx));
	*p_data2++ = (unsigned char)(wertb/(samplefactory*samplefactorx));
      }
      if(ovx)
      {
        wertr = wertg = wertb = 0;
        for(kk = 0; kk < samplefactory; kk++)
	{
	  for(ll = 0; ll < ovx; ll++)
	  {
            wertr += *p_data++;
            wertg += *p_data++;
            wertb += *p_data++;
	  }
	  p_data += 3*(imageW-ovx);
	}
	p_data -= 3*(samplefactory * imageW - ovx);
	*p_data2++ = (unsigned char)(wertr/(samplefactory*ovx));
	*p_data2++ = (unsigned char)(wertg/(samplefactory*ovx));
	*p_data2++ = (unsigned char)(wertb/(samplefactory*ovx));
      }
      p_data += 3*(lineoffset + (samplefactory-1)*imageW);
    }
    if(ovy)
    {
      for(jj = 0; jj < xno; jj++)
      {
        wertr = wertg = wertb = 0;
        for(kk = 0; kk < ovy; kk++)
	{
	  for(ll = 0; ll < samplefactorx; ll++)
	  {
            wertr += *p_data++;
            wertg += *p_data++;
            wertb += *p_data++;
	  }
	  p_data += 3*(imageW-samplefactorx);
	}
	p_data -= 3*(ovy * imageW - samplefactorx);
	*p_data2++ = (unsigned char)(wertr/(ovy*samplefactorx));
	*p_data2++ = (unsigned char)(wertg/(ovy*samplefactorx));
	*p_data2++ = (unsigned char)(wertb/(ovy*samplefactorx));
      }
      if(ovx)
      {
        wertr = wertg = wertb = 0;
        for(kk = 0; kk < ovy; kk++)
	{
	  for(ll = 0; ll < ovx; ll++)
	  {
            wertr += *p_data++;
            wertg += *p_data++;
            wertb += *p_data++;
	  }
	  p_data += 3*(imageW-ovx);
	}
	p_data -= 3*(ovy * imageW - ovx);
	*p_data2++ = (unsigned char)(wertr/(ovy*ovx));
	*p_data2++ = (unsigned char)(wertg/(ovy*ovx));
	*p_data2++ = (unsigned char)(wertb/(ovy*ovx));
      }
    }
  }
  /*Both directions upsampling*/
  else if ((samplefactorx < 0) && (samplefactory < 0))
  {
    samplefactorx = -samplefactorx;
    samplefactory = -samplefactory;
    newx = samplefactorx * sourceW;
    yoff = 3*(newx * samplefactory - samplefactorx);
    for(ii = 0; ii < sourceH; ii++)
    {
      for(jj = 0; jj < sourceW; jj++)
      {
        wertr = *p_data;
        wertg = *(p_data+1);
        wertb = *(p_data+2);
        for(kk = 0; kk < samplefactory; kk++)
	{
	  for(ll = 0; ll < samplefactorx; ll++)
	  {
            *p_data2++ = (unsigned char)wertr;
            *p_data2++ = (unsigned char)wertg;
            *p_data2++ = (unsigned char)wertb;
	  }
	  p_data2 += 3*(newx - samplefactorx);
	}
	p_data2 -= yoff;
	p_data  += 3;
      }
      p_data2 += 3*(newx * (samplefactory - 1));
      p_data  += 3*lineoffset;
    }
  }
  else if(samplefactorx > 0 )
  {
    xno = sourceW/samplefactorx;
    samplefactory *= -1;
    ovx = sourceW%samplefactorx;
    newx = xno;
    if(ovx) newx++;
    
    for(ii = 0; ii < sourceH; ii++)
    {
      for(jj = 0; jj < xno; jj++)
      {
        wertr = wertg = wertb = 0;
        for(ll = 0; ll < samplefactorx; ll++)
		{
          wertr += *p_data++;
          wertg += *p_data++;
          wertb += *p_data++;
		}    
        *p_data2++ = (unsigned char)(wertr/samplefactorx);
        *p_data2++ = (unsigned char)(wertg/samplefactorx);
        *p_data2++ = (unsigned char)(wertb/samplefactorx);
      }
      if(ovx)
      {
        wertr = wertg = wertb = 0;
        for(ll = 0; ll < ovx; ll++)
		{
          wertr += *p_data++;
          wertg += *p_data++;
          wertb += *p_data++;
		}
        *p_data2++ = (unsigned char)(wertr/ovx);
        *p_data2++ = (unsigned char)(wertg/ovx);
	    *p_data2++ = (unsigned char)(wertb/ovx);
      }
      p_data += 3*lineoffset;
      p_data2 -= 3*newx;
      for(kk = 0; kk < samplefactory; kk++)
      {
        memcpy(p_data2 + 3 * kk * newx, p_data2, 3 * newx);
      }
      p_data2 += 3 * newx * samplefactory;
    }
  }
  else /*x-up, y-down*/
  {
    yno = sourceH/samplefactory;
    ovy = sourceH%samplefactory;
    
    samplefactorx *= -1;
    
    for(ii = 0; ii < yno; ii++)
    {
      for(jj = 0; jj < sourceW; jj++)
      {
        wertr = wertg = wertb = 0;
	for(kk = 0; kk < samplefactory; kk++)
	{
	  wertr += *p_data;
	  wertg += *(p_data+1);
	  wertb += *(p_data+2);
	  p_data += 3*imageW;
	}    
	wertr /= samplefactory;
	wertg /= samplefactory;
	wertb /= samplefactory;
	for(ll = 0; ll < samplefactorx; ll++)
	{
	  *p_data2++ = (unsigned char)wertr;
	  *p_data2++ = (unsigned char)wertg;
	  *p_data2++ = (unsigned char)wertb;
	}
        p_data -= 3*(imageW * samplefactory - 1);
      }
      p_data += 3*(imageW * (samplefactory - 1) + lineoffset);
    }
    if(ovy)
    {
      for(jj = 0; jj < sourceW; jj++)
      {
        wertr = wertg = wertb = 0;
        for(kk = 0; kk < ovy; kk++)
        {
          wertr += *p_data++;
          wertg += *p_data++;
          wertb += *p_data;
          p_data += 3*imageW - 2;
        }    
        wertr /= ovy;
        wertg /= ovy;
        wertb /= ovy;
        for(ll = 0; ll < samplefactorx; ll++)
        {
          *p_data2++ = (unsigned char)wertr;
          *p_data2++ = (unsigned char)wertg;
          *p_data2++ = (unsigned char)wertb;
        }
        p_data -= 3*(imageW * ovy - 1);
      }
    }
  }
  return(1);
}
