/*********************************************************************
 * This file is part of the PRAPI library.
 *
 * Copyright (C) 2001-2003 Topi Mäenpää
 * Copyright (C) 2001 Jaakko Viertola
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.7 $
 *********************************************************************/

#ifndef _SGNDIFF_H
#define _SGNDIFF_H

#include "CircularLocalSampler.h"

namespace prapi { namespace texture {

	/**
	 * A class for calculating signed differences from an matrix. For
	 * each pixel, a local neighborhood is formed, and the difference
	 * between the center pixel and one of the neighbors is calculated.
	 * The difference is used as a feature value for the center pixel.
	 * Assuming 8 bit matrices, the signed differences vary in range
	 * [-255,255].
	 **/
	template <class T> class SgnDiff : public CircularLocalSampler<T,T>
	{
	public:
		/**
		 * Create a SgnDiff object that calculates the signed difference
		 * with the given distance, i.e. <i>predicate</i>.
		 **/
		SgnDiff(unsigned int predicate=1) : CircularLocalSampler<T,T>(8u,predicate,false), _uiDiffIndex(0) {}
		
		T getValue(int center, util::List<T>& surrounding) { return surrounding[_uiDiffIndex]-center; }

		/**
		 * Set the difference index. The number of samples in
		 * CircularLocalSampler determines the maximum possible difference
		 * index. By default, 0 is used, which typically means the
		 * difference in positive x axis direction.
		 *
		 * @exception InvalidArgumentException if <i>index</i> is greater
		 * than or equal to the number of neighborhood samples
		 **/
		void setDifferenceIndex(unsigned int index) throw (util::InvalidArgumentException&);

		/**
		 * Get the difference index.
		 **/
		unsigned int getDifferenceIndex() const { return _uiDiffIndex;}

	private:
		unsigned int _uiDiffIndex;
	};

	template <class T> void SgnDiff<T>::setDifferenceIndex(unsigned int index) throw (util::InvalidArgumentException&)
	{
		if (index >= _uiSamples)
			throw util::InvalidArgumentException("SgnDiff::setDifferenceIndex(int): difference index too large.");
		_uiDiffIndex = index;
	}	
}}

#endif
