///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004 Intel Corporation 
// All rights reserved. 
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are met: 
//
// * Redistributions of source code must retain the above copyright notice, 
// this list of conditions and the following disclaimer. 
// * Redistributions in binary form must reproduce the above copyright notice, 
// this list of conditions and the following disclaimer in the documentation 
// and/or other materials provided with the distribution. 
// * Neither name of Intel Corporation nor the names of its contributors 
// may be used to endorse or promote products derived from this software 
// without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////

#ifndef IMAGE_H
#define IMAGE_H

#include "ipp.h"

class Image8u
{
private:
	Ipp8u* pData_;
	int stride_;
	IppiSize size_;
	int channelCount_;

public:
//	Constructors
	Image8u();
	Image8u(IppiSize size, int channelCount);
	Image8u(int w, int h, int channelCount);
	Image8u(const Image8u* pImage);

//  Destructor
	~Image8u();

//  Initialization
	int InitAlloc(int w, int h, int channelCount);
	int InitAlloc(IppiSize size, int channelCount)
		{ return InitAlloc(size.width, size.height, channelCount); }
	int Alloc();
	void Free();

//  Accessors
	virtual IppiSize GetSize() const;
	virtual int GetStride() const;
	virtual const Ipp8u* GetConstData() const;
	virtual const Ipp8u* GetConstData(int x, int y) const;
	virtual Ipp8u* GetData();
	virtual Ipp8u* GetData(int x, int y);

	int GetChannelCount() const { return channelCount_; }

//  Copy Methods
	IppStatus CopyFrom_R(const Ipp8u* pSrcData, int srcW, int srcH,
						 int srcStride, int dstX, int dstY);

	IppStatus CopyFrom_R(const Ipp32f* pSrcData,
		int srcW, int srcH, int srcStride,
		int dstX, int dstY );

	IppStatus CopyFrom(const Ipp8u* pSrcData, int srcStride) {
		return CopyFrom_R(pSrcData, size_.width, size_.height, srcStride, 0, 0);
	}

	IppStatus CopyFrom_R(const Ipp8u* pSrcData, IppiSize srcSize, int srcStride,
			 IppiPoint dstOffset) {
		return CopyFrom_R(pSrcData, srcSize.width, srcSize.height, dstOffset.x,
			   dstOffset.y, srcStride);
	}

	IppStatus CopyFrom(const Image8u* pSrcImage) {
		return CopyFrom_R(pSrcImage->GetConstData(), pSrcImage->GetSize().width,
				pSrcImage->GetSize().height, pSrcImage->GetStride(), 0, 0);
	}
		
	IppStatus CopyFrom_R(const Image8u* pSrcImage, IppiSize srcSize,
						 IppiPoint dstOffset) {
		return CopyFrom_R(pSrcImage->GetConstData(), srcSize.width, srcSize.height,
				   pSrcImage->GetStride(), dstOffset.x, dstOffset.y);
	}

	
	IppStatus CopyFrom_R(const Image8u* pSrcImage,
		int srcX, int srcY,	int srcW, int srcH,
		int dstX, int dstY)
	{
		return CopyFrom_R(
			pSrcImage->GetConstData(srcX,srcY),
			srcW, srcH, pSrcImage->GetStride(),
			dstX, dstY);
	}

	IppStatus CopyFrom_R(const Image8u* pSrcImage, int srcW, int srcH,
						 int dstX, int dstY) {
		return CopyFrom_R(pSrcImage->GetConstData(), srcW, srcH, pSrcImage->GetStride(),
				   dstX, dstY);
	}

	IppStatus CopySettings(const Image8u* pImage);
	IppStatus Clone(const Image8u* pImage);

	// Utilities
	int View(int isModal=1) const
	{ return View("", isModal); }
	int View(const char* pTitle, int isModal) const;
	int View(const char* pTitle, int isModal,
			 IppiSize size) const;
	int View(const char* pTitle, int isModal,
			 IppiSize size, int x, int y) const;

	void Zero();
	int LoadBMP(const char* pFilename);

	virtual int CheckCompat(const Image8u* pImage) const;
	virtual IppiSize GetOverlap(IppiSize size) const;
	virtual IppiRect GetOverlap(IppiRect rect) const;
	virtual IppiRect GetOverlap(IppiRect rect1, IppiRect rect2) const;
	virtual IppiSize GetOverlap(const Image8u* pImage) const;
	virtual IppiRect GetOverlap(const Image8u* pImage, IppiPoint p) const;

//	IppStatus Add_I(Image8u* pImage);
//	IppStatus Add_R(Image8u* pImage1, Image8u* pImage2);
//	IppStatus Add_IR(Ipp8u* pData
};

#endif