#ifndef _ImageScaler_h
#define _ImageScaler_h

/*!
 * this class scales images consisting of 4 components (RGBA)
 * to an arbitrary size using a 4-tap filter
 */
class ImageScaler {
public:

	struct Filter {
		unsigned  m_offset;
		short     m_coeff[4];
	};

	ImageScaler();
	~ImageScaler();

	//! set destination image and source image size
	void SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height );

	/*! process one pixel of source image; destination image is written while input is processed
	 * SetImageParameters() must be called first
	 */
	void PutSourcePixel( unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3 ) {
		m_hbuf[ (m_src_x++) & 3 ].Set( c0, c1, c2, c3 );

		TmpPixel      *bp = m_buffer + 4 * m_dst_x + (m_src_y & 3);
		const Filter  *fh;

		while ( (fh=m_hor_filters+m_dst_x)->m_offset == m_src_x ) {
			*bp = m_hbuf[0]*fh->m_coeff[0] + m_hbuf[1]*fh->m_coeff[1] + m_hbuf[2]*fh->m_coeff[2] + m_hbuf[3]*fh->m_coeff[3];
			m_dst_x++;
			bp += 4;
		}

		if ( m_src_x == m_src_width ) NextSourceLine();
	}

private:

	//! temporary image pixel class - a 4-element integer vector
	class TmpPixel {
	public:
		TmpPixel() {
		}

		TmpPixel( int c0, int c1, int c2, int c3 ) {
			Set(c0,c1,c2,c3);
		}

		void Set( int c0, int c1, int c2, int c3 ) {
			m_comp[0] = c0;
			m_comp[1] = c1;
			m_comp[2] = c2;
			m_comp[3] = c3;
		}

		TmpPixel operator*( int s ) const {
			return TmpPixel( m_comp[0]*s, m_comp[1]*s, m_comp[2]*s, m_comp[3]*s );
		}

		TmpPixel operator+( const TmpPixel &x ) const {
			return TmpPixel( m_comp[0] + x[0], m_comp[1] + x[1], m_comp[2] + x[2], m_comp[3] + x[3] );
		}

		// return component i=[0..3] - No range check!
		int operator[](unsigned i) const {
			return m_comp[i];
		}

	private:
		int  m_comp[4];
	};

	//! this is called whenever one input line is processed completely
	void NextSourceLine();

	TmpPixel   m_hbuf[4];      //! ring buffer for 4 input pixels
	char      *m_memory;       //! buffer container
	Filter    *m_hor_filters;  //! buffer for horizontal filters (one for each output image column)
	Filter    *m_ver_filters;  //! buffer for vertical   filters (one for each output image row)
	TmpPixel  *m_buffer;       //! buffer contains 4 horizontally filtered input lines, multiplexed
	unsigned  *m_dst_image;    //! pointer to destination image
	unsigned   m_dst_stride;   //! destination image stride
	unsigned   m_dst_width;    //! destination image width
	unsigned   m_dst_height;   //! destination image height
	unsigned   m_src_width;    //! source image width
	unsigned   m_src_height;   //! source image height
	unsigned   m_src_x;        //! x position of next source image pixel
	unsigned   m_src_y;        //! y position of source image line currently beeing processed
	unsigned   m_dst_x;        //! x position of next destination image pixel
	unsigned   m_dst_y;        //! x position of next destination image line
};

#endif  // _ImageScaler_h

