/******************************************************************************
 JImage.h

	Interface for the JImage class

	Copyright © 1996-99 by John Lindal. All rights reserved.

 ******************************************************************************/

#ifndef _H_JImage
#define _H_JImage

#include <JRect.h>
#include <jColor.h>
#include <JError.h>
#include <JXPM.h>

class JImageMask;
class JColormap;

class JImage
{
public:

	enum FileType
	{
		kUnknownType,
		kGIFType,
		kPNGType,
		kJPEGType,
		kXPMType,
		kXBMType
	};

public:

	JImage(const JCoordinate width, const JCoordinate height, JColormap* colormap);
	JImage(const JImage& source);

	virtual ~JImage();

	JCoordinate	GetWidth() const;
	JCoordinate	GetHeight() const;
	JRect		GetBounds() const;

	JColormap*			GetColormap() const;
	virtual JColorIndex	GetColor(const JCoordinate x, const JCoordinate y) const = 0;
	virtual void		SetColor(const JCoordinate x, const JCoordinate y,
								 const JColorIndex color) = 0;

	virtual JBoolean	GetMask(JImageMask** mask) const = 0;

	JError	WriteGIF(const JCharacter* fileName,
					 const JBoolean compressColorsToFit,
					 const JBoolean interlace = kFalse) const;
	JError	WritePNG(const JCharacter* fileName,
					 const JBoolean interlace = kFalse) const;
	JError	WriteJPEG(const JCharacter* fileName) const;

	static FileType	GetFileType(const JCharacter* fileName);

	// called by JImageMask

	virtual unsigned long	GetSystemColor(const JColorIndex color) const = 0;
	virtual unsigned long	GetSystemColor(const JCoordinate x, const JCoordinate y) const = 0;

protected:

	void	SetDimensions(const JCoordinate width, const JCoordinate height);

	JError	ReadGIF(const JCharacter* fileName);
	JError	ReadPNG(const JCharacter* fileName);
	JError	ReadJPEG(const JCharacter* fileName);
	void	ReadFromJXPM(const JXPM& pixmap);

	virtual void	SetImageData(const JSize colorCount, const JColorIndex* colorTable,
								 unsigned short** imageData,
								 const JBoolean hasMask, const unsigned long maskColor) = 0;

	JError	AllocateImageData(const JSize w, const JSize h, unsigned short** data,
							  unsigned short*** cols);

private:

	JCoordinate	itsWidth;
	JCoordinate	itsHeight;
	JColormap*	itsColormap;	// we don't own this

private:

	// not allowed

	const JImage& operator=(const JImage& source);

public:

	// JError classes

	static const JCharacter* kUnknownFileType;
	static const JCharacter* kFileIsNotGIF;
	static const JCharacter* kGIFNotAvailable;
	static const JCharacter* kFileIsNotPNG;
	static const JCharacter* kPNGNotAvailable;
	static const JCharacter* kFileIsNotJPEG;
	static const JCharacter* kJPEGNotAvailable;
	static const JCharacter* kFileIsNotXPM;
	static const JCharacter* kFileIsNotXBM;
	static const JCharacter* kTooManyColors;

	static const JCharacter* kUnknownFileTypeMsg;
	static const JCharacter* kFileIsNotGIFMsg;
	static const JCharacter* kGIFNotAvailableMsg;
	static const JCharacter* kFileIsNotPNGMsg;
	static const JCharacter* kPNGNotAvailableMsg;
	static const JCharacter* kFileIsNotJPEGMsg;
	static const JCharacter* kJPEGNotAvailableMsg;
	static const JCharacter* kFileIsNotXPMMsg;
	static const JCharacter* kFileIsNotXBMMsg;
	static const JCharacter* kTooManyColorsMsg;

	class UnknownFileType : public JError
		{
		public:

			UnknownFileType()
				:
				JError(kUnknownFileType, kUnknownFileTypeMsg)
			{ };
		};

	class FileIsNotGIF : public JError
		{
		public:

			FileIsNotGIF()
				:
				JError(kFileIsNotGIF, kFileIsNotGIFMsg)
			{ };
		};

	class GIFNotAvailable : public JError
		{
		public:

			GIFNotAvailable()
				:
				JError(kGIFNotAvailable, kGIFNotAvailableMsg)
			{ };
		};

	class FileIsNotPNG : public JError
		{
		public:

			FileIsNotPNG()
				:
				JError(kFileIsNotPNG, kFileIsNotPNGMsg)
			{ };
		};

	class PNGNotAvailable : public JError
		{
		public:

			PNGNotAvailable()
				:
				JError(kPNGNotAvailable, kPNGNotAvailableMsg)
			{ };
		};

	class FileIsNotJPEG : public JError
		{
		public:

			FileIsNotJPEG()
				:
				JError(kFileIsNotJPEG, kFileIsNotJPEGMsg)
			{ };
		};

	class JPEGNotAvailable : public JError
		{
		public:

			JPEGNotAvailable()
				:
				JError(kJPEGNotAvailable, kJPEGNotAvailableMsg)
			{ };
		};

	class FileIsNotXPM : public JError
		{
		public:

			FileIsNotXPM()
				:
				JError(kFileIsNotXPM, kFileIsNotXPMMsg)
			{ };
		};

	class FileIsNotXBM : public JError
		{
		public:

			FileIsNotXBM()
				:
				JError(kFileIsNotXBM, kFileIsNotXBMMsg)
			{ };
		};

	class TooManyColors : public JError
		{
		public:

			TooManyColors()
				:
				JError(kTooManyColors, kTooManyColorsMsg)
			{ };
		};
};


/******************************************************************************
 Dimensions

 ******************************************************************************/

inline JCoordinate
JImage::GetWidth()
	const
{
	return itsWidth;
}

inline JCoordinate
JImage::GetHeight()
	const
{
	return itsHeight;
}

inline JRect
JImage::GetBounds()
	const
{
	return JRect(0, 0, itsHeight, itsWidth);
}

inline void
JImage::SetDimensions
	(
	const JCoordinate width,
	const JCoordinate height
	)
{
	itsWidth  = width;
	itsHeight = height;
}

/******************************************************************************
 GetColormap

 ******************************************************************************/

inline JColormap*
JImage::GetColormap()
	const
{
	return itsColormap;
}

#endif
