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


		MCPixelBucket.h


		Copyright: (c) 2001 Eovia Corp. All rights reserved.


		Author:	Sree
		Date:	12/12/97

		Revision History

		when		who			what & why
		==========	==========	======================================================
		10/15/99	Greg		Padded PixelBucketType to force the size to 32 bits
		5/25/99		Ian			Added TMCCompatiblePixelBucket() this is a pixel bucket
								that can be blit to the screen quickly.
		4/2/99		Ian			Added fReserved field, and Accessor.
		12/01/98	Nba			fixed problem with fRowInc when stride is 0
		12/02/98	dsm			added BuildFromPixelBucket
		11/19/98	Nba			Fixed RowPtrX (uses RowInc); Fixed FlipRows (uses RowPixelByte)
		11/19/98	tsh/sree	added ColInc, ColInc16 and ColInc32
		11/11/98	sree		added pixel stride member and accompanying changes, see Notes: below
		11/02/98	sree		fixed bug in subslicing for upsidedown buckets
		10/29/98	Nba			rolled back changes for a minimal PixelBucket
		09/29/98	ssk			added Invalidate method
		09/09/98	Nba			removed MCMemory.h, put in MCMemoryCopy.h, and use new/delete instead of MCMalloc/Free
		09/09/98	Nba			added back inclusion of MCMemory.h for inlines (uses MCmalloc, etc)
		09/09/98	cph			removed include of MCMemory.h
		07/15/98	nba			added fRow16Inc -> RowInc16 and Padding16Inc
		07/09/98	nba			added eChannel2_14 for fixed 16 bit channels
		06/01/98	ssk			added SetMEMBER methods
		05/20/98	eml			made accessors in TMCPixelBucket const
		04/06/98	pbk			Fixed compilation errors when Debug_ is on
		05/24/98    cph			Added more PixelBucketTypes, needed for Painter
*****************************************************************************************/

#if CP_PRAGMA_ONCE
#pragma once
#endif

#ifndef __MCPixelBucket__
#define __MCPixelBucket__

#include "MCAssert.h"
#include "MCBasicTypes.h"
#include "MCBasicDefines.h"
#include "MCMath.h"
#include "MCMemoryCopy.h"
#include "MCRect.h"
#include <memory.h>

// =================================================================================================================
// known TMCPixelBucket types 
// =================================================================================================================
enum PixelBucketType
{
	eDefault			= 0, 	//assume from bit depth
	
	//64 bit formats
	eARGB64,
	eCMYK64,
	eChannel64,
	
	//32 bit formats
	eARGB,
	eCMYK32,
	eChannel32,
	
	//24 bit formats
	eYUV,
	eLAB,
	
	//16 bit formats
	e555RGB,					
	e655RGB,
	e556RGB,
	e565RGB,
	eChannel2_14,
	eChannel16,
	
	//8 bit formats
	// eGrayScale is the only mode supported. The others aren't developed yet.
	eIndexedColor,				
	eGrayScale,
	e322RGB,
	e232RGB,
	e233RGB,
	e222RGB,
	
	eMaxPixelBucketType = 0x7FFFFFFF // to force 4 bytes
};

/// \addtogroup MCCore
/// \{

/// TMCPixelBucket is an abstraction used to manipulate a block of pixels (bitmap).
/// The block is generally padded for alignment, so you must use BaseAddress() + rowIndex * RowBytes() 
/// to find the begining of a row.
///
/// TMCPixelBucket does NOT own its memory. It is generally used in conjunction with a TMCOffscreen, or with a memory bloc
/// that was allocated for it (and that you need to delete).
///
/// <B>Note:</B>
///    - fStride may be less than fDepth, though the default case is fStride==fDepth
///    - fWidth*fBytesStride <= fRowBytes
///
///    - Int32Aligned()         true if row is int32 aligned
///    - ByteStrideAligned()    true if pixelstride in bits can be expressed accurately in bytes
///    - DepthStrideEqual()     true if fStride==fDepth
///
///    - PixelPtrX() functions may fail if ByteStrideAligned() is false
///    - PixelPtrX() functions may fail if fStride is not a multiple of fDepth increments
///    - PixelPtrX() functions ARE SLOW... they are provided only for convenience
///
///    - Rectangles and other Coordinates for pixel buckets are in pixels
///
class TMCPixelBucket
{
	protected:

		uint8*					fBaseAddress;			///< pointer to base address as a byte
		int32					fRowBytes;				///< length of each scanline in bytes
		int32					fWidth;					///< horizontal pixels
		int32					fHeight;				///< vertical pixels
		int32					fDepth;					///< bitdepth 8,24,32, etc.
		int32					fStride;				///< stride in bits, typically equally to fDepth
		int32					fPlanes;				///< fDepth/8, ie 1,3,4, etc.
		int32					fRightSideUp;			///< true if fBaseAddress points to first scanline
		
		// the following is precalculated (cached)
		int32					fRowPaddingBytes;		///< (bytes), padding at end of a scanline
		int32					fRowPixelBytes;			///< (bytes), the fWidth of a row (fRowBytes - fRowPaddingBytes)
		int32					fRowInc;				///< (bytes), to next sequential scanline
		int32					fPaddingInc;			///< (bytes), from end of scanline to next sequential scanline
		PixelBucketType			fType;					///< type of pixel bucket.
		boolean					fValid;					///< true if constructed properly

	private:
		friend class TMCOffscreen;
		void*	fReserved; ///< DO NOT TOUCH THIS ON PENALTY OF DEATH!!!!
	public:
		// =================================================================================================================
		// Data
		// =================================================================================================================
		inline int32					Width()			const {return fWidth;		}
		inline int32					Height()		const {return fHeight;		}
		inline int32					Depth()			const {return fDepth;		}
		inline int32					Stride()		const {return fStride;		}
		inline int32					Planes()		const {return fPlanes;		}
		inline int32					RightSideUp()	const {return fRightSideUp;	}
		inline PixelBucketType			Type()			const {return fType;		}
		inline void*					Reserved()		const {return fReserved;	}

		// the following are computed methods
		inline int32					Width1()		const {return fWidth - 1;	}
		inline int32					Height1()		const {return fHeight - 1;	}


		//the following are alignment verification methods
		inline boolean			DepthStrideEqual()		const {return fStride==fDepth;				}
		inline boolean			ByteStrideAligned()		const {return (fStride & 0x7) == 0;			}
		inline boolean			WordStrideAligned()		const {return (fStride & 0xF) == 0;			}
		inline boolean			LongStrideAligned()		const {return (fStride & 0x1F) == 0;		}
		inline int32			Int16Aligned()			const {return (fRowBytes&1)==0;				}
		inline int32			Int32Aligned()			const {return (fRowBytes&3)==0;				}

		// the following is precalculated (cached)
		inline int32			ByteStride()		const {MCAssertIfFalse(ByteStrideAligned()); return fStride>>3;		}
		inline int32			RowPaddingBytes()	const {return fRowPaddingBytes;										}
		inline int32			RowPixelBytes()		const {return fRowPixelBytes;										}
		inline void				Rect(TMCRect* r)	const {MCAssertIfFalse (r); r->Set(0,0,Width(),Height());			}
		inline void				Rect(TMCRect& r)	const {Rect (&r);													}
		inline TMCRect			Rect(void)			const {return TMCRect(0,0,Width(),Height());						}
		inline boolean			IsValid()			const {return fValid;												}

		
		// =================================================================================================================
		// Constructors
		// =================================================================================================================
		inline TMCPixelBucket();
		inline TMCPixelBucket	(uint8* baseAddressParam, int32 rowBytesParam, 
								 int32 widthParam, int32 heightParam,
								 int32 depthParam, int32 planesParam, 
								 boolean rightSideUpParam, PixelBucketType type = eDefault);

		inline TMCPixelBucket	(uint8* baseAddressParam, int32 rowBytesParam, 
								 int32 widthParam, int32 heightParam,
								 int32 depthParam, int32 pixelStride, int32 planesParam, 
								 boolean rightSideUpParam, PixelBucketType type = eDefault);

		inline explicit TMCPixelBucket	(TMCPixelBucket* pixelBucket);
		inline TMCPixelBucket	(TMCPixelBucket& pixelBucket, const TMCRect& subRect);
		

		// =================================================================================================================
		// Update Pixel Bucket Internals
		// =================================================================================================================
		inline void BuildCore	(uint8* baseAddressParam, int32 rowBytesParam, 
								 int32 widthParam, int32 heightParam,
								 int32 depthParam, int32 planesParam, 
								 boolean rightSideUpParam, PixelBucketType type = eDefault);

		inline void BuildCore	(uint8* baseAddressParam, int32 rowBytesParam, 
								 int32 widthParam, int32 heightParam,
								 int32 depthParam, int32 pixelStride, int32 planesParam, 
								 boolean rightSideUpParam, PixelBucketType type);

		inline void BuildFromPixelBucket(const TMCPixelBucket& pixelBucket, const TMCRect& subRect);

		inline void Invalidate ()	{BuildCore (NULL, 0, 0, 0, 0, 0, 0);	fValid = false;}

		
		inline boolean operator== (const TMCPixelBucket& other) const;
		// =================================================================================================================
		// Set Member Methods
		// =================================================================================================================
		inline void SetBaseAddress	(void *baseAddress)			{ fBaseAddress	= (uint8*) baseAddress;	 BuildCache();}
		inline void SetRowBytes		(int32 rowBytes)			{ fRowBytes		= rowBytes;				 BuildCache();}
		inline void SetWidth		(int32 width)				{ fWidth		= width;				 BuildCache();}
		inline void SetHeight		(int32 height)				{ fHeight		= height;				 BuildCache();}
		inline void SetDepth		(int32 depth)				{ fDepth		= depth;				 BuildCache();}
		inline void SetPlanes		(int32 planes)				{ fPlanes		= planes;				 BuildCache();}
		inline void SetRightSideUp	(boolean rightSide)			{ fRightSideUp	= rightSide;			 BuildCache();}
		inline void SetStride		(int32 stride)				{ fStride		= stride;				 BuildCache();}
		inline void SetType			(PixelBucketType type);

		// =================================================================================================================
		// Fast Set Member Methods - you MUST manually call BuildCache() after calling any of these functions!
		// =================================================================================================================
		inline void SetBaseAddressNoCache	(void *baseAddress)			{ fBaseAddress	= (uint8*) baseAddress;	 }
		inline void SetRowBytesNoCache		(int32 rowBytes)			{ fRowBytes		= rowBytes;				 }
		inline void SetWidthNoCache			(int32 width)				{ fWidth		= width;				 }
		inline void SetHeightNoCache		(int32 height)				{ fHeight		= height;				 }
		inline void SetDepthNoCache			(int32 depth)				{ fDepth		= depth;				 }
		inline void SetPlanesNoCache		(int32 planes)				{ fPlanes		= planes;				 }
		inline void SetRightSideUpNoCache	(boolean rightSide)			{ fRightSideUp	= rightSide;			 }
		inline void SetTypeNoCache			(PixelBucketType type)		{ fType			= type;					 }
		inline void SetStrideNoCache		(int32 stride)				{ fStride		= stride;				 }

		// =================================================================================================================
		// BuildCache - refresh cached values
		// =================================================================================================================
		inline void BuildCache();

		
		// =================================================================================================================
		// Scanline access functions
		// =================================================================================================================
		inline uint8*	BaseAddress()	const { return fBaseAddress;			}
		inline uint16*	BaseAddress16()	const { return (uint16*)fBaseAddress;	}
		inline uint32*	BaseAddress32()	const { return (uint32*)fBaseAddress;	}

		inline int32	RowBytes()		const { return fRowBytes;				}
		inline int16	RowBytes16()	const { return (fRowBytes+1)>>1;		} //row length in shorts
		inline int32	RowBytes32()	const { return (fRowBytes+3)>>2;		} //row length in longs

		inline uint8* 	RowPtr		(int32 row) const;
		inline uint16* 	RowPtr16	(int32 row) const;
		inline uint32* 	RowPtr32	(int32 row) const;

		inline uint8* 	PixelPtr	(int32 x, int32 y) const;
		inline uint16*	PixelPtr16	(int32 x, int32 y) const;
		inline uint32* 	PixelPtr32	(int32 x, int32 y) const;

		inline int32	RowInc()		const { return fRowInc;												}
		inline int32	RowInc16()		const { MCAssertIfFalse(Int16Aligned()); return fRowInc>>1;			}
		inline int32	RowInc32()		const { MCAssertIfFalse(Int32Aligned()); return fRowInc>>2;			}

		inline int32	ColInc()		const { return ByteStride();										}
		inline int32	ColInc16()		const { MCAssertIfFalse(Int16Aligned()); return ByteStride() >> 1;	}
		inline int32	ColInc32()		const { MCAssertIfFalse(Int32Aligned()); return ByteStride() >> 2;	}

		inline int32	PaddingInc()	const { return fPaddingInc;											}
		inline int32	Padding16Inc()	const { MCAssertIfFalse(Int16Aligned()); return fPaddingInc>>1;		}
		inline int32	Padding32Inc()	const { MCAssertIfFalse(Int32Aligned()); return fPaddingInc>>2;		}

		// =================================================================================================================
		// FlipRows - convience function for blitting
		// =================================================================================================================
		inline boolean					FlipRows();
};


/// \}



/// We use this class to tell us when we need to call DestroyCompatiblePixelBucket
/// instead of deleting the TMCPixelBucket. 
/// So you only get this class from CreateCompatiblePixelBucket() and you must
/// delete it with DestroyCompatiblePixelBucket().
///
class TMCCompatiblePixelBucket : public TMCPixelBucket
{
};


// =================================================================================================================
// 
// =================================================================================================================
// =================================================================================================================
// TMCPixelBucket Implementation
// =================================================================================================================
// =================================================================================================================
// 
// =================================================================================================================

// =================================================================================================================
// Constructor
// =================================================================================================================
inline TMCPixelBucket::TMCPixelBucket(void)
{
	fValid			= false;
	fBaseAddress	= NULL;
	fReserved		= NULL;
}

// =================================================================================================================
// Constructor - no stride
// =================================================================================================================
inline TMCPixelBucket::TMCPixelBucket(uint8* baseAddressParam, int32 rowBytesParam, 
									  int32 widthParam, int32 heightParam,
									  int32 depthParam, int32 planesParam, 
									  boolean rightSideUpParam, PixelBucketType type)
{
	BuildCore(	baseAddressParam, rowBytesParam, widthParam, heightParam,
				depthParam, planesParam, rightSideUpParam, type);

	fReserved = NULL;
}

// =================================================================================================================
// Constructor - with stride
// =================================================================================================================
inline TMCPixelBucket::TMCPixelBucket(uint8* baseAddressParam, int32 rowBytesParam, 
									  int32 widthParam, int32 heightParam,
									  int32 depthParam, int32 strideParam, int32 planesParam, 
									  boolean rightSideUpParam, PixelBucketType type)
{
	BuildCore(baseAddressParam, rowBytesParam, widthParam, heightParam,
			  depthParam, strideParam, planesParam, rightSideUpParam, type);

	fReserved = NULL;
}

// =================================================================================================================
// Constructor
// =================================================================================================================
inline TMCPixelBucket::TMCPixelBucket(TMCPixelBucket* pixelBucket)
{
	fValid = false;

	if(MCVerify(pixelBucket!= NULL))
	{
		if(MCVerify(pixelBucket->IsValid()))
		{
			fReserved = pixelBucket->fReserved;

			BuildCore(	pixelBucket->BaseAddress(), pixelBucket->RowBytes(), 
						pixelBucket->Width(), pixelBucket->Height(),
						pixelBucket->Depth(), pixelBucket->Stride(), pixelBucket->Planes(), 
						(boolean)pixelBucket->RightSideUp(), pixelBucket->Type());
		}
	}
}

// =================================================================================================================
// Constructor
// =================================================================================================================
inline TMCPixelBucket::TMCPixelBucket(TMCPixelBucket& pixelBucket, const TMCRect& subRect)
{
	fValid = false;

	BuildFromPixelBucket(pixelBucket, subRect);
}

// =================================================================================================================
// BuildCore
// =================================================================================================================
inline void TMCPixelBucket::BuildCore(uint8* baseAddressParam, int32 rowBytesParam, 
									  int32 widthParam, int32 heightParam,
									  int32 depthParam, int32 planesParam, 
									  boolean rightSideUpParam, PixelBucketType type)
{
	BuildCore(	baseAddressParam, rowBytesParam, widthParam, heightParam,
				depthParam, depthParam, planesParam, rightSideUpParam, type);
}

// =================================================================================================================
// BuildCore
// =================================================================================================================
inline void TMCPixelBucket::BuildCore(uint8* baseAddressParam, int32 rowBytesParam, 
									  int32 widthParam, int32 heightParam,
									  int32 depthParam, int32 strideParam, int32 planesParam, 
									  boolean rightSideUpParam, PixelBucketType type)
{
	fValid				= false;

	fBaseAddress		= baseAddressParam;
	fRowBytes			= rowBytesParam;
	fWidth				= widthParam;
	fHeight				= MC_AbsL (heightParam);	//abs(fHeight) in case it's negative
	fDepth				= depthParam;
	fStride				= strideParam;
	fPlanes				= planesParam;
	fRightSideUp		= rightSideUpParam;

	fType				= type;
	fValid				= true;

	BuildCache();
}

// =================================================================================================================
// BuildFromPixelBucket
// =================================================================================================================
inline void TMCPixelBucket::BuildFromPixelBucket(const TMCPixelBucket& pixelBucket, const TMCRect& subRect)
{
	fValid				= false;

	if(!pixelBucket.IsValid())						{ MCAssertIfFalse(0); return; }
	
	if(subRect.Empty())								{ MCAssertIfFalse(0); return; }

	fReserved = pixelBucket.fReserved;

	TMCRect	pixelBucketRect	= pixelBucket.Rect();
	TMCRect	srect = subRect;
	if(!pixelBucketRect.Intersect(subRect))			{ MCAssertIfFalse(0); return; }

	int32		row				=  pixelBucket.RightSideUp() ? srect.top : srect.bottom - 1;
	uint8*		newBaseAddress	=  pixelBucket.RowPtr (row) + ((srect.left * pixelBucket.Depth())>>3);


	BuildCore(	newBaseAddress, pixelBucket.RowBytes(), 
				srect.GetWidth(), srect.GetHeight(),
				pixelBucket.Depth(), pixelBucket.Stride(), pixelBucket.Planes(), 
				(boolean)pixelBucket.RightSideUp(), pixelBucket.Type());
}

// =================================================================================================================
// BuildCache
// =================================================================================================================
inline void TMCPixelBucket::BuildCache()
{
	if(!IsValid())		{ MCAssertIfFalse(0); return; }

	fRowPixelBytes		= fPlanes * fWidth;
	fRowPaddingBytes	= fRowBytes - fRowPixelBytes;
	if (fStride == 0) // constant case
	{
		MCAssert(fRowBytes == 0);
		fPaddingInc			= 0;
		fRowInc				= 0;
	}
	else
	{
		fRowInc				= fRightSideUp ? fRowBytes				: -fRowBytes;
		fPaddingInc			= fRightSideUp ? fRowPaddingBytes		: fRowPaddingBytes - (fRowBytes<<1);
	}
}

// =================================================================================================================
// RowPtr
// =================================================================================================================
inline uint8* TMCPixelBucket::RowPtr(int32 row) const
{
#if Debug_
	if(!IsValid())							{ MCAssertIfFalse(0); return NULL; }
	if(!( (row >= 0) && (row < fHeight) ))	{ MCAssertIfFalse(0); return NULL; }
#endif //Debug_
	if(!fRightSideUp) row = row + 1 - fHeight ;	//invert row (RowInc is negative too)
	return fBaseAddress + fRowInc * row;	
}

// =================================================================================================================
// RowPtr32
// =================================================================================================================
inline uint32* TMCPixelBucket::RowPtr32(int32 row) const
{
#if Debug_
	if(!IsValid())							{ MCAssertIfFalse(0); return NULL; }
	if(!( (row >= 0) && (row < fHeight) ))	{ MCAssertIfFalse(0); return NULL; }
#endif //Debug_
	if(!fRightSideUp) row = row + 1 - fHeight ;	//invert row (RowInc is negative too)
	return BaseAddress32() + RowInc32() * row;	
}

// =================================================================================================================
// RowPtr16
// =================================================================================================================
inline uint16* TMCPixelBucket::RowPtr16(int32 row) const
{
#if Debug_
	if(!IsValid())							{ MCAssertIfFalse(0); return NULL; }
	if(!( (row >= 0) && (row < fHeight) ))	{ MCAssertIfFalse(0); return NULL; }
#endif //Debug_
	if(!fRightSideUp) row = row + 1 - fHeight ;	//invert row (RowInc is negative too)
	return BaseAddress16() + RowInc16() * row;
}

// =================================================================================================================
// PixelPtr
// =================================================================================================================
inline uint8* TMCPixelBucket::PixelPtr(int32 x, int32 y) const
{
#if Debug_
	if(!IsValid())							{ MCAssertIfFalse(0); return NULL; }
	if(!((x >= 0) && (x < fWidth)))			{ MCAssertIfFalse(0); return NULL; }
	if(!((y >= 0) && (y < fHeight)))		{ MCAssertIfFalse(0); return NULL; }
	MCAssertIfFalse (ByteStrideAligned());
#endif //Debug_

	return RowPtr(y) + x*ByteStride();
}

// =================================================================================================================
// PixelPtr16
// =================================================================================================================
inline uint16* TMCPixelBucket::PixelPtr16(int32 x, int32 y) const
{
#if Debug_
	if(!IsValid())							{ MCAssertIfFalse(0); return NULL; }
	if(!((x >= 0) && (x < fWidth)))			{ MCAssertIfFalse(0); return NULL; }
	if(!((y >= 0) && (y < fHeight)))		{ MCAssertIfFalse(0); return NULL; }
	MCAssertIfFalse (WordStrideAligned());
#endif //Debug_
	
	uint8* pixptr = RowPtr(y) + x*ByteStride();
#if Debug_
	MCAssertIfFalse (((uint32)pixptr&1) == 0);
#endif //Debug_
	return (uint16*)pixptr;
}

// =================================================================================================================
// PixelPtr32
// =================================================================================================================
inline uint32* TMCPixelBucket::PixelPtr32(int32 x, int32 y) const
{
#if Debug_
	if(!IsValid())							{ MCAssertIfFalse(0); return NULL; }
	if(!((x >= 0) && (x < fWidth)))			{ MCAssertIfFalse(0); return NULL; }
	if(!((y >= 0) && (y < fHeight)))		{ MCAssertIfFalse(0); return NULL; }
	MCAssertIfFalse (LongStrideAligned());
#endif //Debug_

	uint8* pixptr = RowPtr(y) + x*ByteStride();
#if Debug_
	MCAssertIfFalse (((uint32)pixptr&3) == 0);
#endif //Debug_
	return (uint32*)pixptr;
}
boolean TMCPixelBucket::operator== (const TMCPixelBucket& other) const
{
	if (!IsValid())
		return !other.IsValid();
	
	boolean canBeEqual = (fRowBytes == other.fRowBytes) &&
		(fWidth == other.fWidth) &&
		(fHeight == other.fHeight) &&
		(fDepth == other.fDepth) &&
		(fStride == other.fStride) &&
		(fPlanes == other.fPlanes) &&
		(fRightSideUp == other.fRightSideUp) && 
		(fType == other.fType);
	if (canBeEqual)
		canBeEqual = memcmp(fBaseAddress, other.fBaseAddress, fRowBytes * fHeight) == 0;
	return canBeEqual;
}

// =================================================================================================================
// FlipRows
// =================================================================================================================
inline boolean	TMCPixelBucket::FlipRows()
{
	if(!IsValid())							{ MCAssertIfFalse(0); return false; }

	const uint32 tempRowBytes				= fRowPixelBytes;
	int32	fHeight_1						= fHeight - 1;
	int32	height_half						= fHeight / 2;
	uint8	*tmpPtr							= new uint8[tempRowBytes];
	uint8	*topPtr, *bottomPtr;

	if(!tmpPtr)								{ MCAssertIfFalse(0); return false; }

	for(int32 loop = 0; loop < height_half; loop++)
	{
		topPtr		= RowPtr (loop);
		bottomPtr	= RowPtr (fHeight_1 - loop);
		
		MCmemcpy	(tmpPtr, topPtr, tempRowBytes);		// copy top to temp
		MCmemcpy	(topPtr, bottomPtr, tempRowBytes);	// copy bottom to top
		MCmemcpy	(bottomPtr, tmpPtr, tempRowBytes);	// copy temp to bottom
	}
				
	delete []tmpPtr;
	return true;
}

// =================================================================================================================
// SetType
// =================================================================================================================
inline void TMCPixelBucket::SetType(PixelBucketType type)
{
#if Debug_
	// In 8bits mode, eGrayScale is the only option supported. The others aren't developed yet.
	if( fDepth == 8 ) MCAssert( type == eGrayScale );
#endif

	fType = type;
	BuildCache();
}

#endif