libvips/libsrc/other/im_spatres.c

147 lines
4.0 KiB
C

/* @(#) Function which changes the spatial resolution of an image according to
* @(#) step
* @(#)
* @(#) int im_spatres(in, out, step)
* @(#) IMAGE *in, *out;
* @(#) int step;
* @(#) Returns either 0 (sucess) or -1 (fail)
* @(#)
* @(#) Picture can have any number of channels (max 64).
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 08/11/1989.
* Modified on: 19/01/1990.
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
int
im_spatres( IMAGE *in, IMAGE *out, int step )
{
int x, y; /* horizontal and vertical direction */
int z; /* 0 <= z < channel */
int i, j;
int rounding, step2, sum;
unsigned char *values;
unsigned char *input, *cpinput, *cp2input, *line, *cpline, *pnt, *cpnt;
int os;
/* Check args */
if ( step < 1 )
{im_errormsg("im_spatres: Invalid step %d\n", step);return(-1);}
if ( (in->Xsize/step == 0)||(in->Ysize/step == 0) )
{im_errormsg("im_spatres: Invalid step %d\n", step);return(-1);}
if (im_iocheck(in, out) == -1)
{ im_errormsg("im_spatres: im_iocheck failed"); return(-1); }
if((in->Coding != IM_CODING_NONE)||(in->Bbits != 8)||(in->BandFmt !=IM_BANDFMT_UCHAR))
{ im_errormsg("im_spatres: wrong input"); return(-1); }
/* Prepare output */
if (im_cp_desc(out, in) == -1)
{ im_errormsg("im_spatres: im_cp_desc failed"); return(-1); }
out->Xsize = in->Xsize - in->Xsize%step;
out->Ysize = in->Ysize - in->Ysize%step;
if( im_setupout(out) == -1)
{ im_errormsg("im_spatres: im_setupout failed"); return(-1); }
/* Malloc buffer for one 'line' of input data */
os = in->Xsize * in->Bands;
line = (unsigned char *)calloc((unsigned)os, sizeof(char));
/* Malloc space for values */
values = (unsigned char *)calloc((unsigned)out->Bands, sizeof(char));
if ( line == NULL || values == NULL )
{ im_errormsg("im_spatres: calloc failed"); return(-1); }
step2 = step * step;
rounding = step2/2;
input = (unsigned char *)in->data;
for ( y = 0; y < out->Ysize; y += step )
{
cpinput = input;
input += os * step;
/* do the x loop out->Xsize / step times */
cpline = line;
for (x = 0; x < out->Xsize; x += step)
{
cp2input = cpinput;
cpinput += step * out->Bands; /* ??? */
for ( z = 0; z < out->Bands; z++ )
{
pnt = cp2input + z;
sum = 0;
for ( j = 0; j < step; j++ )
{
cpnt = pnt;
pnt += os;
for ( i = 0; i < step; i++ )
{
sum += (int)*cpnt;
cpnt += out->Bands;
}
}
*(values + z) = (PEL)((sum + rounding)/step2);
}
/* for this x, write step*bands data */
for ( j = 0; j < step; j++ )
for ( z = 0; z < out->Bands; z++ )
*cpline++ = *(values + z);
}
/* line is now ready. Write now step lines */
for (j = 0; j < step; j++)
if ( im_writeline ( y+j, out, (PEL *)line ) == -1 )
{
im_errormsg("im_spatres: im_writeline failed");
free ( (char *)line ); free ( (char *)values );
return( -1 );
}
} /* end of the for (..y..) loop */
free ( (char *)line ); free ( (char *)values );
return(0);
}