/* @(#)  Program to calculate the stdev of the differnce image
 * @(#) at a given displacement vector
 *
 * Written : 25/11/1987
 * Author : N. Dessipris
 * Updated : 2/12/1991
 * 22/7/93 JC
 *	- im_incheck() added
 */

/*

	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., 51 Franklin Street, Fifth Floor, Boston, MA
	02110-1301  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 <glib/gi18n-lib.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <vips/vips.h>
#include <vips/vips7compat.h>
#include <vips/internal.h>

static int
im__mean_std_int_buffer(int *buffer, int size,
	double *pmean, double *pstd)
{
	double mean, std;
	register int i;
	int sumf;
	int temp;
	int *pbuffer;
	int sumf2;
	double correction; /* calulates the correction term for the variance */
	double variance;   /* = (sumf2 - correction)/n */

	if (size <= 0) {
		im_error("im_mean_std_int_buffer", "%s", _("wrong args"));
		return -1;
	}

	mean = 0.0;
	std = 0.0;
	sumf = 0;
	sumf2 = 0;
	pbuffer = buffer;
	for (i = 0; i < size; i++) {
		temp = *pbuffer++;
		sumf += temp;
		sumf2 += (temp * temp);
	}

	correction = ((double) (sumf * sumf)) / ((double) size);
	mean = ((double) sumf) / ((double) size);
	variance = (sumf2 - correction) / ((double) size);
	std = sqrt(variance);
	*pmean = mean;
	*pstd = std;

	return 0;
}

int
im_dif_std(IMAGE *im, int xpos, int ypos, int xsize, int ysize, int dx, int dy, double *pmean, double *pstd)
{
	PEL *input, *cpinput;
	double m, s;
	int *buf, *pbuf;
	int x, y;
	int ofst, bufsize;

	if (im_incheck(im))
		return -1;

	if ((im->Bands != 1) || (im->BandFmt != IM_BANDFMT_UCHAR)) {
		im_error("im_dif_std", "%s", _("Unable to accept input"));
		return -1;
	}
	if ((xpos + xsize + dx > im->Xsize) || (ypos + ysize + dy > im->Ysize)) {
		im_error("im_dif_std", "%s", _("wrong args"));
		return -1;
	}

	bufsize = xsize * ysize;
	buf = (int *) calloc((unsigned) bufsize, sizeof(int));
	if (buf == NULL) {
		im_error("im_dif_std", "%s", _("calloc failed"));
		return -1;
	}
	input = (PEL *) im->data;
	input += (ypos * im->Xsize + xpos);
	ofst = dy * im->Xsize + dx;
	pbuf = buf;
	for (y = 0; y < ysize; y++) {
		cpinput = input;
		input += im->Xsize;
		for (x = 0; x < xsize; x++) {
			*pbuf++ = ((int) (*cpinput)) - ((int) (*(cpinput + ofst)));
			cpinput++;
		}
	}

	m = 0.0;
	s = 0.0;
	if (im__mean_std_int_buffer(buf, bufsize, &m, &s)) {
		free((char *) buf);
		return -1;
	}
	free((char *) buf);

	*pmean = m;
	*pstd = s;

	return 0;
}
