/**
 * This file describes the image geometry of 2-D graphics.
 * Classes described here are IGImage and IGImagePixelAccessor.
 *
 *   IBM Open Class Library
 *   (C) Copyright International Business Machines Corporation,  1997
 *   Licensed Material - Program-Property of IBM - All Rights Reserved.
 *
 */

// Revision: 78 1.47.1.17 source/albert/graph2d/igimage.hpp, 2d, ioc.v400, 980918 

#ifndef _IGIMAGE_
#define _IGIMAGE_

#include <i2dghand.hpp>          // IPresSpaceHandle

#include <igbase2d.hpp>
#include <ibcolor.hpp>
#include <icolmap.hpp>
#include <icoordsy.hpp>

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

class IGrafPort;
class IGrafMatrix;
class IRect2D;
class IGImageDeviceContext;

class IBitmapData;

#pragma enum(4)
#pragma pack(push,4)

/**
 * IGImage is a device-independent, uneditable, pixel-based geometry.
 */
class IGImage  {
public :
	IDataStream& operator>>=(IDataStream& toWhere) const;
	IDataStream& operator<<=(IDataStream& fromWhere);
	virtual void writeToStream( IDataStream& toWhere ) const;
	virtual void readFromStream( IDataStream& toWhere );

	/** Image type. */
	enum EImageType {
		kMonochrome1Bit=0,
		k16Color4Bit,
		k256Color8Bit,
		kTrueColor24Bit
	};

	/**
	 * Default constructor. Creates empty handles, empty device context, and empty graphics port.
	 */
	IGImage();

	/**
	 * Creates an IGImage with the specified width, height, and type.
	 */		
	IGImage(
		unsigned long width,
		unsigned long height,
		EImageType theType,	
		ICoordinateSystem::EOrientation orientation=
			ICoordinateSystem::applicationOrientation(),
		IColorMap* colmap = &(IColorMap::defaultColorMap()));


	/**
	 * Copy constructor.
	 */		
	IGImage(const IGImage&);

	/**
	 * Creates an IGImage using a bitmap handle.
	 */		
	IGImage(const IBitmapHandle& bitmapHandle);
       	
	/**
	 * Creates an IGImage as a mask image. Only the specified color is allowed to be seen.
	 */		
	IGImage(
		const IGImage& origImage,
		const IBaseColor& tranparentColor);

	/**
	 * Creates an IGImage which is a subregion of an image.
	 */		
	IGImage(const IGImage&,
			const IGRect2D&);

	~IGImage();

	/**
	 * Returns the raster bounds (the rectangle defining the active area) of the image.
	 */		
	IGRect2D rasterBounds() const;

	/**
	 * Creates a color table for this image.
	 */		
	IRGBAColorArray*	createColorTable()const;

	/**
	 * Creates a new IGrafPort of this image.
	 */		
	IGrafPort* grafPort();

	/**
	 * Reflects the image horizontally.
	 * Reflects the image horizontally. This function invalidates the previous "handle()" call. "handle()" needs to be called again in
	 * order to get a valid handle for IGImage.
	 */		
	IGImage& reflectHorizontally();

	/**
	 * Reflects the image vertically.
	 * Reflects the image vertically. This function invalidates the previous "handle()" call. "handle()" needs to be called again in
	 * order to get a valid handle for IGImage.
	 */		
	IGImage& reflectVertically();

	/**
	 * Rotates the image by 180 degrees.
	 * Rotates the image by 180 degrees. This function invalidates the previous "handle()" call. "handle()" needs to be called again in
	 * order to get a valid handle for IGImage.
	 */		
	IGImage& rotateBy180();

	/**
	 * Rotates the image by 270 degrees.
	 * Rotates the image by 270 degrees. This function invalidates the previous "handle()" call. "handle()" needs to be called again in
	 * order to get a valid handle for IGImage.
	 */		
	IGImage& rotateBy270();

	/**
	 * Rotates the image by 90 degrees.
	 * Rotates the image by 90 degrees. This function invalidates the previous "handle()" call. "handle()" needs to be called again in
	 * order to get a valid handle for IGImage.
	 */		
	IGImage& rotateBy90();

	/**
	 * Transposes the image.
	 * Transposes the image. This function invalidates the previous "handle()" call. "handle()" needs to be called again in
	 * order to get a valid handle for IGImage.
	 */		
	IGImage& transposeXForY();

	/**
	 * Scales the image to a specified new size.
	 * Scales the image to a specified new size. This function invalidates the previous "handle()" call. "handle()" needs to be called again in
	 * order to get a valid handle for IGImage.
	 */		
	IGImage& sizeTo(const IGPoint2D& newSize);

	// Image modification at the pixel level - use the IGImagePixelAccessor class below for
	// more convience functions.

	/**
	 * Gets the handle fo the image.
	 * Gets the handle fo the image. Previous "handle()" call becomes invalid if one of the following functions is called:
	 *     reflectHorizontally, reflectVertically, rotateBy180, rotateBy90, transposeXForY, and sizeTo.
	 * return the image handle nt and os2 is HBITMAP and that in aix is pixmap
	 */		
	IBitmapHandle handle() const;

	//return the image handle nt adn os2 is HBITMAP and that in aix is ximage
	unsigned long imageHandle() const;

	/**
	 * Calculates and returns the boundary, in user space, for the specified image. This is the WYSIWYG bounds.
	 */		
	static IGRect2D imageBounds(const IGImage& theImage);

	/**
	 * Tests two images for equality.
	 */
	bool operator==(const IGImage&) const;

	/**
	 * Tests two images for inequality.
	 */
	bool operator!=(const IGImage&) const;

	/**
	 * Assignment operator.
	 */
	const IGImage& operator=(const IGImage& source);

	/**
	 * Sets the Transparency flag
	 */
	void setTransparencyFlag(bool );

	/**
	 * Gets the Transparency flag
	 */
	bool transparencyFlag() const;

	/**
	 * Sets the Transparency Color
	 */
	void setTransparencyColor(const IBaseColor& clr);

	/**
	 * Gets the Transparency Color
	 */
	IBaseColor transparencyColor() const;

	/**
	 * Gets the handle fo the mask image.
	 */		
	IBitmapHandle maskImageHandle() const;

	/**
	 * Gets the Image ColorTable
	 */
	IRGBAColorArray imageColorTable() const;

	// to capture the bitmap image from a given device, such as a screen device...
	static IBitmapHandle captureImage(
		IPresSpaceHandle& srcDeviceContext,
		const IGRect2D& imageArea);

	// someother ICLUI function uses this also...
	IBitmapHandle copyBitmap( ) const;
/*-------------------------------- Accessors -----------------------------------
| addRef           - Increment the use count and return the current use count. |
| removeRef        - Decrement the use count and return the current use count. |
| useCount         - Return the current use count.                             |
-------------------------------- Accessors -----------------------------------*/
unsigned long
  addRef           ( ),
  removeRef        ( ),
  useCount         ( ) const;

private:

#if defined(IC_WIN)
friend class IGdiDevice;
friend class IGdiWin95ScaleFontContext;
#elif defined(IC_PM)
friend class IGpiDevice;
friend class IGpiEmulator;
#elif defined(IC_MOTIF)
friend class IXDevice; //uses pixelBuffer
friend class IXImageDevice; //uses setImageSyncFlag, IGdiImageDevice also
#endif

friend class IGdiImageDevice;
friend class IGImageDeviceContext;
friend class IGImagePixelAccessor;

friend class IGraph2DTestHelper;
friend class IPrintGrafDevice; // IPrintGrafDevice::renderImage
friend class ICustomButtonDrawEvent; // ICustomButtonDrawEvent::grafPort
friend class IDMTBarButtonItem; // IDMTBarButtonItem::IDMTBarButtonItem
friend class IDMMenuItem; // IDMMenuItem::IDMMenuItem
	// the function deviceContext is dangerous to use because it confuses ownership...
	// instead one should use the createDeviceContext function below
	IPresSpaceHandle deviceContext() const;				// this should be obsolete!!!
	IGImageDeviceContext* createDeviceContext() const;


friend class IImageConverter; //uses adoptBitmapData, createBmpDataFromPixBuf
	void adoptBitmapData(IBitmapData *);
	IBitmapData* createBmpDataFromPixBuf(IPixelBuffer*);

	IBitmapData* bitmapData() const;
	void setImageSyncFlag(bool);

#ifdef IC_MOTIF
#ifndef NO_IGIMAGEPIXELACCESSOR
#define NO_IGIMAGEPIXELACCESSOR
	bool pixel(const IGPoint2D& position, IBaseColor& valueOfThePixelReturned) const;
	void setPixel(const IGPoint2D& position, const IBaseColor& valueOfThePixel);
#endif //NO_IGIMAGEPIXELACCESSOR
#endif //IC_MOTIF

private:
	ICoordinateSystem::EOrientation fOrientation;
	IGrafPort* fGrafPort;
	IBitmapData*	fBmpData;
	IColorMap*	fColorMap;
};

/**
 * IGImagePixelAccessor is used to facilitate pixel level image modification functions.
 * IGImagePixelAccessor is used to facilitate pixel level image modification functions.
 * This is designed to be a trancient convenience object to be created on the stack to
 * access the pixels of a image. This should not be copied, assigned or streamed ...
 */

class IGImagePixelAccessor {
public:
	/** Defined various type of image formats. */
	enum EImageFormat {
			kUNKNOWN=-2,
			kCOMPRESS=-1,
  			kBMP=0,
  			kGIF,
  			kJPG,
  			kXPM
  		};

	/** Defines various image dither methods. */
	enum EDitherType {
		kNoDither,
		kErrorDither,
		kHalftoneDither
	};

   /**
	* Constructs an IGImagePixelAccessor using an IGImage as reference.
    */
	IGImagePixelAccessor(const IGImage& referencedImage);

	~IGImagePixelAccessor();

	/**
	 * Gets the value of the specified pixel.
	 */
	bool pixel(const IGPoint2D&, IBaseColor& valueOfThePixelReturned) const;

	/**
	 * Sets the value of the specified pixel.
	 */
	void setPixel(const IGPoint2D&, const IBaseColor& valueOfThePixel);

	/**
	 * Gets the values of a row of pixels.
	 * Gets the values of a row of pixels. The starting point and the length of the row are specified.
   * The length of the row is specified through the size of the IRGBColorArray.
	 */
	bool pixelRow(
	const IGPoint2D&,
	IRGBAColorArray& valueOfThePixelsReturned) const;

	/**
	 * Sets the values of a row of pixels.
	 * Sets the values of a row of pixels. The starting point and the length of the row are specified.
   * The length of the row is specified through the size of the IRGBColorArray.
	 */
	void setPixelRow(
	const IGPoint2D&,
	const IRGBAColorArray& valueOfThePixels);

	/**
	 * Reads an image from a file with specified format.
	 */
	static IBitmapHandle loadFromFile(
				const IString& imageFilename,
				EImageFormat imageFormat = kUNKNOWN,
				EDitherType ditherStyle = kNoDither);

	static IGImage* loadImageFromFile( const IString& imageFilename);
	/**
	 * Outputs the image into a file using the specified filename and format.
   * Outputs the image into a file using the specified filename and format.
   * NOTE: The GIF format is inherently an 8-bit format. Attempting to write
   * a GIF file using this function while specifying other than 8 bits per
   * pixel will result in a runtime error
	 */
	static void writeToFile(const IString& imageFilename, EImageFormat imageFormat,
				IBitmapHandle bmp);
	
	static void writeImageToFile(const IString& imageFilename, EImageFormat imageFormat,
				IGImage* );
private:
	IBitmapHandle fDummy;
	IGImage *fImage;


	// the following functions are disabled...
	IGImagePixelAccessor();
	IGImagePixelAccessor(const IGImagePixelAccessor& src);
	IGImagePixelAccessor& operator=(const IGImagePixelAccessor& src);
};

#pragma pack(pop)
#pragma enum(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

#endif // _IGIMAGE_
