/****************************************************************************
** qdvdauthor.h file.
**
** This file handles the user input to generate a DVD menu.
** Please note that this is work in progress and depends also oin the
** developement of dvdauthor, which is at the moment in version 0.67.
** Future versions of dvdauthort might need changes to this file.
**
*****************************************************************************/

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

#include <qimage.h>

#ifdef HAVE_FREEIMAGE
#include <FreeImagePlus.h>
#endif

#include "global.h"
#include "qimagehelper.h"

QImageHelper::QImageHelper()
	: QImage ()
{

}

QImageHelper::QImageHelper (const QString &fileName, const char *format)
	: QImage (fileName, format)
{

}


QImageHelper::~QImageHelper ()
{

}

uint QImageHelper::countColors(QImage &image)
{
	// Okay, let us count the actual used colors ...
	// Now remember that the images are okay in size for this stupidly
	// simple algol to work.
	uint x, y, c, iCounter=0;
	bool *pArray = new bool [0x1000000];
	QRgb thePixel;
	if (!pArray)	{
		// Alternate algo to find out fast if > 4 colors
		QRgb rgbArray[MAX_MASK_COLORS+1];
		bool bFound = false;
		for (y=0;y<(uint)image.height();y++)	{
			for (x=0;x<(uint)image.width();x++)	{
				thePixel = image.pixel(x, y);
				// Filter out the alpha channel
				thePixel &= 0x00ffffff;
				for (c=0;c<iCounter;c++)	{
					if (rgbArray[c] == thePixel)
						bFound = true;
				}
				if (!bFound)
					rgbArray[iCounter++] = thePixel;
				bFound = false;
				if (iCounter > MAX_MASK_COLORS)
					return MAX_MASK_COLORS+1;
			}
		}
		return iCounter;
	}
	memset (pArray, 0, 0x1000000);
	for (y=0;y<(uint)image.height();y++)	{
		for (x=0;x<(uint)image.width();x++)	{
			thePixel = image.pixel(x, y);
			// Filter out the alpha channel
			thePixel &= 0x00ffffff;
			if (!pArray[(uint)thePixel])	{
				iCounter ++;
				pArray[(uint)thePixel] = 1;
			}
		}
	}
	delete []pArray;
	return iCounter;
}

bool QImageHelper::resize (int iWidth, int iHeight, int iResizeAlgorithm)
{
#ifdef HAVE_FREEIMAGE
	// So first we create a FreeImage - object.
	fipImage *pImage = (fipImage *)getFreeImage ();
	if (!pImage)
		iResizeAlgorithm = RESIZE_QT;
	switch (iResizeAlgorithm)	{
	case RESIZE_FILTER_BOX:
		pImage->rescale (iWidth, iHeight, FILTER_BOX);
		setFreeImage (pImage);
	break;
	case RESIZE_BICUBIC:
		pImage->rescale (iWidth, iHeight, FILTER_BICUBIC);
		setFreeImage (pImage);
	break;
	case RESIZE_BILINEAR:
		pImage->rescale (iWidth, iHeight, FILTER_BILINEAR);
		setFreeImage (pImage);
	break;
	case RESIZE_BSPLINE:
		pImage->rescale (iWidth, iHeight, FILTER_BSPLINE);
		setFreeImage (pImage);
	break;
	case RESIZE_CATMULLROM:
		pImage->rescale (iWidth, iHeight, FILTER_CATMULLROM);
		setFreeImage (pImage);
	break;
	case RESIZE_LANCZOS3:
		pImage->rescale (iWidth, iHeight, FILTER_LANCZOS3);
		setFreeImage (pImage);
	break;
	case RESIZE_QT:
	default:
		((QImage &)*this) = smoothScale(iWidth, iHeight);
	break;
	};
#else
	((QImage &)*this) = smoothScale(iWidth, iHeight);
#endif
	return true;
}

void *QImageHelper::getFreeImage()
{
// This function converts the QImage object into a FreeImage Object (DIB) and returns a pointer of this object.
// If FREEIMAGE is not defined, then we return simply NULL.
#ifdef HAVE_FREEIMAGE
	// So first we create a FreeImage - object.
	static fipImage freeImage;
	// Here is the cheap and dirty method. We store the QImage as png
	char *pTempFileName = tmpnam(NULL);
	save (QString(pTempFileName), "PNG");
	freeImage.load (pTempFileName);
	system ((const char *) QString ("rm %1").arg(pTempFileName));
	return (void *)&freeImage;
#else
	return NULL;
#endif
}

bool QImageHelper::setFreeImage(void *pImage)
{
// This function converts a FreeImage - object into a QImage object
// If FREEIMAGE is not defined, then we return simply NULL.
#ifdef HAVE_FREEIMAGE
	// So first we create a FreeImage - object.
	fipImage *pFreeImage = (fipImage *) pImage;
	// Here is the cheap and dirty method. We stroe the QImage as png
	char *pTempFileName = tmpnam(NULL);
	char *pNewFileName = new char[strlen (pTempFileName) + 5];
	sprintf (pNewFileName, "%s.png", pTempFileName);
	pFreeImage->save (pNewFileName);
	load (pNewFileName, "PNG");
	system ((const char *) QString ("rm %1").arg(pTempFileName));
#else
	return false;
#endif
	return true;
}

bool QImageHelper::dither (int iMaxColors, int iDitherMethod)
{
	iMaxColors ++;
#ifdef HAVE_FREEIMAGE
	// So first we create a FreeImage - object.
	fipImage *pImage = (fipImage *)getFreeImage ();
	if (!pImage)
		return false;
	pImage->colorQuantize (FIQ_NNQUANT);
	switch (iDitherMethod)	{
	case DITHER_NONE:
	break;
	case DITHER_FLOYD_STEINBERG:
		pImage->dither(FID_FS);
	break;
	case DITHER_BAYER4x4:
		pImage->dither(FID_BAYER4x4);
	break;
	case DITHER_BAYER8x8:
		pImage->dither(FID_BAYER8x8);
	break;
	case DITHER_CLUSTER6x6:
		pImage->dither(FID_CLUSTER6x6);
	break;
	case DITHER_CLUSTER8x8:
		pImage->dither(FID_CLUSTER8x8);
	break;
	case DITHER_CLUSTER16x16:
		pImage->dither(FID_CLUSTER16x16);
	break;
	};
	// And finally set the result to the QImage object
	setFreeImage (pImage);
#else
	return false;
#endif
	return true;
}
