//
// Tools_IPImagEx.h
//
// Copyright (C) 2003 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef _INCLUDED_IPIMGEX_HPP_
#define _INCLUDED_IPIMGEX_HPP_

#include <math.h>
#include "ImageProcessing/Tools_IPImage.h"
#include "ImageProcessing/Tools_RGBTypes.h"
#include "ImageProcessing/Tools_Histogram.h"

// Scaling filter
class IPFilter
{
	public:
		typedef double (* Func) (double);
		IPFilter() {}
		IPFilter(double dbl, Func pfn) : dblWidth(dbl), pfnFunc(pfn) {}
		double dblWidth;
		Func pfnFunc;
};

// Standard filters
extern IPFilter const ip_filtDefault;
extern IPFilter const ip_filtBox;
extern IPFilter const ip_filtTriangle;
extern IPFilter const ip_filtBell;
extern IPFilter const ip_filtBSpline;
extern IPFilter const ip_filtLanczos3;
extern IPFilter const ip_filtMitchell;

class Tools_IPImageEx : public Tools_IPImage
{
	public:
		Tools_IPImageEx();
		Tools_IPImageEx(Tools_IPImageEx const & r);
		Tools_IPImageEx const & operator = (Tools_IPImageEx const & r);
		~Tools_IPImageEx();
		
		bool CreateByChangingColourDepth(Tools_IPImageEx const & src, unsigned psize);
		bool CreateByScaling(Tools_IPImageEx const & src, float xScale, float yScale, IPFilter const & filter = ip_filtDefault);
		bool CreateByScaling(Tools_IPImageEx const & src, unsigned width, unsigned height, IPFilter const & filter = ip_filtDefault);
		bool CreateByClipping(Tools_IPImageEx const & src, unsigned left, unsigned top, unsigned right, unsigned bottom);
		
		bool EnsurePalettized();
		bool RemoveUnusedColours();
		
		unsigned CountColoursUsed() const;
		
	private:
	
		bool CreateByScaling(Tools_IPImageEx const & src, unsigned width, unsigned height, float xScale, float yScale, IPFilter const & filter);
		
		void MakeHist() const;
		void ClearHist() const;
		
		mutable HHHashHistogram * pHist;
};

inline Tools_IPImageEx::Tools_IPImageEx()
	: pHist(NULL)
{
}

inline Tools_IPImageEx::Tools_IPImageEx(Tools_IPImageEx const & r)
	: Tools_IPImage(r)
	, pHist(NULL)
{
	if (r.pHist)
	{
		pHist = new HHHashHistogram(*r.pHist);
		bModified = false;
	}
}

inline Tools_IPImageEx const & Tools_IPImageEx::operator = (Tools_IPImageEx const & r)
{
	Tools_IPImage::operator = (r);
	
	if (&r != this)
	{
		if (pHist) delete pHist;
		pHist = NULL;
		if (r.pHist)
		{
			pHist = new HHHashHistogram(*r.pHist);
			bModified = false;
		}
	}
	return *this;
}

inline Tools_IPImageEx::~Tools_IPImageEx()
{
	if (pHist) delete pHist;
}

inline bool Tools_IPImageEx::CreateByScaling(Tools_IPImageEx const & src, float xScale, float yScale, IPFilter const & filter)
{
	// determine the width and height of the new image
	
	return CreateByScaling(
		src,
		unsigned(ceil(float(src.GetWidth()) * xScale)),
		unsigned(ceil(float(src.GetHeight()) * yScale)),
		xScale,
		yScale,
		filter
	);
}

inline bool Tools_IPImageEx::CreateByScaling(Tools_IPImageEx const & src, unsigned width, unsigned height, IPFilter const & filter)
{
	// determine the scale factor of the new image
	
	return CreateByScaling(
		src,
		width,
		height,
		float(width) / float(src.GetWidth()),
		float(height) / float(src.GetHeight()),
		filter
	);
}


#endif // ! _INCLUDED_IPIMGEX_HPP_
