/* @(#) Shrink any non-complex image by some x, y, factor. No interpolation!
 * @(#) Just average an area. Suitable for making quicklooks only!
 * @(#)
 * @(#) int 
 * @(#) im_shrink( in, out, xshrink, yshrink )
 * @(#) IMAGE *in, *out;
 * @(#) double xshrink, yshrink;
 * @(#)
 * @(#) Returns either 0 (success) or -1 (fail)
 * @(#)
 *
 * Copyright: 1990, N. Dessipris.
 *
 * Authors: Nicos Dessipris and Kirk Martinez
 * Written on: 29/04/1991
 * Modified on: 2/11/92, 22/2/93 Kirk Martinez - Xres Yres & cleanup 
 incredibly inefficient for box filters as LUTs are used instead of + 
 Needs converting to a smoother filter: eg Gaussian!  KM
 * 15/7/93 JC
 *	- rewritten for partial v2
 *	- ANSIfied
 *	- now shrinks any non-complex type
 *	- no longer cloned from im_convsub()
 *	- could be much better! see km comments above
 * 3/8/93 JC
 *	- rounding bug fixed
 * 11/1/94 JC
 *	- problems with .000001 and round up/down ignored! Try shrink 3738
 *	  pixel image by 9.345000000001
 * 7/10/94 JC
 *	- IM_NEW and IM_ARRAY added
 *	- more typedef
 * 3/7/95 JC
 *	- IM_CODING_LABQ handling added here
 * 20/12/08
 * 	- fall back to im_copy() for 1/1 shrink
 */

/*

    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*/

/* Our main parameter struct.
 */
typedef struct {
	double xshrink;		/* Shrink factors */
	double yshrink;
	int mw;			/* Size of area we average */
	int mh;
	int np;			/* Number of pels we average */
} ShrinkInfo;

/* Our per-sequence parameter struct. We hold an offset for each pel we
 * average.
 */
typedef struct {
	REGION *ir;
	int *off;
} SeqInfo;

/* Free a sequence value.
 */
static int
shrink_stop( void *vseq, void *a, void *b )
{
	SeqInfo *seq = (SeqInfo *) vseq;

	IM_FREEF( im_region_free, seq->ir );

	return( 0 );
}

/* Make a sequence value.
 */
static void *
shrink_start( IMAGE *out, void *a, void *b )
{
	IMAGE *in = (IMAGE *) a;
	ShrinkInfo *st = (ShrinkInfo *) b;
	SeqInfo *seq;

	if( !(seq = IM_NEW( out, SeqInfo )) )
		return( NULL );

	/* Init!
	 */
	seq->ir = NULL;
	seq->off = NULL;
	seq->ir = im_region_create( in );
	seq->off = IM_ARRAY( out, st->np, int );
	if( !seq->off || !seq->ir ) {
		shrink_stop( seq, in, st );
		return( NULL );
	}

	return( (void *) seq );
}

/* Integer shrink. 
 */
#define ishrink(TYPE) \
	for( y = to; y < bo; y++ ) { \
		TYPE *q = (TYPE *) IM_REGION_ADDR( or, le, y ); \
 		\
		for( x = le; x < ri; x++ ) { \
			int ix = x * st->xshrink; \
			int iy = y * st->yshrink; \
			TYPE *p = (TYPE *) IM_REGION_ADDR( ir, ix, iy ); \
 			\
			for( k = 0; k < ir->im->Bands; k++ ) { \
				int sum = 0; \
				int *t = seq->off; \
 				\
				for( z = 0; z < st->np; z++ ) \
					sum += p[*t++]; \
				 \
				*q++ = sum / st->np; \
				p++; \
			} \
		} \
	}

/* FP shrink.
 */
#define fshrink(TYPE) \
	for( y = to; y < bo; y++ ) { \
		TYPE *q = (TYPE *) IM_REGION_ADDR( or, le, y ); \
 		\
		for( x = le; x < ri; x++ ) { \
			int ix = x * st->xshrink; \
			int iy = y * st->yshrink; \
			TYPE *p = (TYPE *) IM_REGION_ADDR( ir, ix, iy ); \
 			\
			for( k = 0; k < ir->im->Bands; k++ ) { \
				double sum = 0; \
				int *t = seq->off; \
 				\
				for( z = 0; z < st->np; z++ ) \
					sum += p[*t++]; \
				 \
				*q++ = sum / st->np; \
				p++; \
			} \
		} \
	}

/* Shrink a REGION.
 */
static int
shrink_gen( REGION *or, void *vseq, void *a, void *b )
{
	SeqInfo *seq = (SeqInfo *) vseq;
	ShrinkInfo *st = (ShrinkInfo *) b;
	REGION *ir = seq->ir;
	Rect *r = &or->valid;
	Rect s;
	int le = r->left;
	int ri = IM_RECT_RIGHT( r );
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int x, y, z, k;

	/* What part of the input image do we need? Very careful: round left
	 * down, round right up.
	 */
	s.left = r->left * st->xshrink;
	s.top = r->top * st->yshrink;
	s.width = ceil( IM_RECT_RIGHT( r ) * st->xshrink ) - s.left;
	s.height = ceil( IM_RECT_BOTTOM( r ) * st->yshrink ) - s.top;
	if( im_prepare( ir, &s ) )
		return( -1 );

	/* Init offsets for pel addressing. Note that offsets must be for the
	 * type we will address the memory array with.
	 */
	for( z = 0, y = 0; y < st->mh; y++ )
		for( x = 0; x < st->mw; x++ )
			seq->off[z++] = (IM_REGION_ADDR( ir, x, y ) - 
				IM_REGION_ADDR( ir, 0, 0 )) /
				IM_IMAGE_SIZEOF_ELEMENT( ir->im );

	switch( ir->im->BandFmt ) {
        case IM_BANDFMT_UCHAR: 		ishrink(unsigned char); break;
        case IM_BANDFMT_CHAR: 		ishrink(char); break; 
        case IM_BANDFMT_USHORT: 	ishrink(unsigned short); break;
        case IM_BANDFMT_SHORT: 		ishrink(short); break; 
        case IM_BANDFMT_UINT: 		ishrink(unsigned int); break; 
        case IM_BANDFMT_INT: 		ishrink(int);  break; 
        case IM_BANDFMT_FLOAT: 		fshrink(float); break; 
        case IM_BANDFMT_DOUBLE:		fshrink(double); break;

        default:
		im_error( "im_shrink", "%s", _( "unsupported input format" ) );
                return( -1 );
        }
 
	return( 0 );
}

static int 
shrink( IMAGE *in, IMAGE *out, double xshrink, double yshrink )
{
	ShrinkInfo *st;

	/* Check parameters.
	 */
	if( !in || vips_bandfmt_iscomplex( in->BandFmt ) ) {
		im_error( "im_shrink", "%s", _( "non-complex input only" ) );
		return( -1 );
	}
	if( xshrink < 1.0 || yshrink < 1.0 ) {
		im_error( "im_shrink", 
			"%s", _( "shrink factors should both be >1" ) );
		return( -1 );
	}
	if( im_piocheck( in, out ) )
		return( -1 );

	/* Prepare output. Note: we round the output width down!
	 */
	if( im_cp_desc( out, in ) )
		return( -1 );
	out->Xsize = in->Xsize / xshrink;
	out->Ysize = in->Ysize / yshrink;
	out->Xres = in->Xres / xshrink;
	out->Yres = in->Yres / yshrink;
	if( out->Xsize <= 0 || out->Ysize <= 0 ) {
		im_error( "im_shrink", 
			"%s", _( "image has shrunk to nothing" ) );
		return( -1 );
	}

	/* Build and attach state struct.
	 */
	if( !(st = IM_NEW( out, ShrinkInfo )) )
		return( -1 );
	st->xshrink = xshrink;
	st->yshrink = yshrink;
	st->mw = ceil( xshrink );
	st->mh = ceil( yshrink );
	st->np = st->mw * st->mh;

	/* Set demand hints. We want THINSTRIP, as we will be demanding a
	 * large area of input for each output line.
	 */
	if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) )
		return( -1 );

	/* Generate!
	 */
	if( im_generate( out, 
		shrink_start, shrink_gen, shrink_stop, in, st ) )
		return( -1 );

	return( 0 );
}

/* Wrap up the above: do IM_CODING_LABQ as well.
 */
int
im_shrink( IMAGE *in, IMAGE *out, double xshrink, double yshrink )
{
	if( xshrink == 1 && yshrink == 1 ) {
		return( im_copy( in, out ) );
	}
	else if( in->Coding == IM_CODING_LABQ ) {
		IMAGE *t[2];

		if( im_open_local_array( out, t, 2, "im_shrink:1", "p" ) ||
			im_LabQ2LabS( in, t[0] ) ||
			shrink( t[0], t[1], xshrink, yshrink ) ||
			im_LabS2LabQ( t[1], out ) )
			return( -1 );
	}
	else if( in->Coding == IM_CODING_NONE ) {
		if( shrink( in, out, xshrink, yshrink ) )
			return( -1 );
	}
	else {
		im_error( "im_shrink", "%s", _( "unknown coding type" ) );
		return( -1 );
	}

	return( 0 );
}
