

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.0.0.170915_Beta4 (15 September 2017)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2017
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  and is released under the following
//_/_/  
//_/_/  EXTENDED BSD License
//_/_/
//_/_/  Redistribution and use in source and binary forms, with or without
//_/_/  modification, is permitted provided that the following conditions 
//_/_/  are met:
//_/_/
//_/_/  - Redistributions of source code must retain the above copyright 
//_/_/    and collaboration 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 the name of its copyright holders nor the names of its 
//_/_/    contributors may be used to endorse or promote products derived from 
//_/_/    this software without specific prior written permission.
//_/_/
//_/_/  - CADIA Clause: The license granted in and to the software under this 
//_/_/    agreement is a limited-use license. The software may not be used in 
//_/_/    furtherance of: (i) intentionally causing bodily injury or severe 
//_/_/    emotional harm to any person; (ii) invading the personal privacy or 
//_/_/    violating the human rights of any person; or (iii) committing or 
//_/_/    preparing for any act of war. 
//_/_/
//_/_/  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 THE COPYRIGHT OWNER 
//_/_/  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.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
#if !defined(_BITMAP_H_)
#define _BITMAP_H_

#include "MathClasses.h"
#include "DataMessage.h"

namespace cmlabs {

// #define GET_RGB_FROM_RGBA(a) (((unsigned char*)&a)[0] << 0) + (((unsigned char*)&a)[1] << 8) + (((unsigned char*)&a)[2] << 16)
#define GET_RGB_FROM_RGBA(a) (a & 0x00ffffff)
//#define GET_R_FROM_RGBA(a) (a & 0xff000000)
//#define GET_G_FROM_RGBA(a) (a & 0x00ff0000)
//#define GET_B_FROM_RGBA(a) (a & 0x0000ff00)
//#define GET_R_FROM_RGBA(a) (char)(a & 0x000000ff)
//#define GET_G_FROM_RGBA(a) (char)(a & 0x0000ff00)
//#define GET_B_FROM_RGBA(a) (char)(a & 0x00ff0000)
//#define GET_R_FROM_RGBA(a) ((unsigned char*)&a)[0]
//#define GET_G_FROM_RGBA(a) ((unsigned char*)&a)[1]
//#define GET_B_FROM_RGBA(a) ((unsigned char*)&a)[2]
#define GET_R_FROM_RGBA(a) (unsigned char)(a & 0x000000ff)
#define GET_G_FROM_RGBA(a) (unsigned char)((a & 0x0000ff00)>>8)
#define GET_B_FROM_RGBA(a) (unsigned char)((a & 0x00ff0000)>>16)
#define GET_RGB_FROM_GRAY(a) (unsigned int)(((unsigned int)a<<16) + ((unsigned int)a<<8) + (unsigned int)a)
#define GET_RGB_FROM_COMP(r,g,b) (unsigned int)((((unsigned int)b)<<16) + (((unsigned int)g)<<8) + (unsigned int)r)
#define GET_GRAY_FROM_RGB(a) (unsigned char)((GET_R_FROM_RGBA(a)+GET_G_FROM_RGBA(a)+GET_B_FROM_RGBA(a))/3)

// Red 0xF800 (5 bits of red) Green 0x07E0 (6 bits of green) Blue 0x001F (5 bits of blue) 
#define GET_DRGB_FROM_2RGBS(a,b) (((unsigned int)GET_R_FROM_RGBA(a)>>3)<<27) + (((unsigned int)GET_G_FROM_RGBA(a)>>2)<<21) + (((unsigned int)GET_B_FROM_RGBA(a)>>3)<<16) + (((unsigned int)GET_R_FROM_RGBA(b)>>3)<<11) + (((unsigned int)GET_G_FROM_RGBA(b)>>2)<<5) + (((unsigned int)GET_B_FROM_RGBA(b)>>3)<<0)
#define GET_FIRSTRGB_FROM_DRGB(a) ((unsigned int)((unsigned short)((a>>16)&0xF800)>>8)) | ((unsigned int)((unsigned short)((a>>16)&0xE000)>>13)) | ((unsigned int)((unsigned short)((a>>16)&0x07E0)<<5)) | ((unsigned int)((unsigned short)((a>>16)&0x0600))>>1) | ((unsigned int)((unsigned short)(a>>16)&0x001F)<<19) | (((unsigned int)(unsigned short)(a>>16)&0x001C)<<14)
#define GET_SECONDRGB_FROM_DRGB(a) ((unsigned int)((unsigned short)(a&0xF800)>>8)) | ((unsigned int)((unsigned short)(a&0xE000)>>13)) | ((unsigned int)((unsigned short)(a&0x07E0)<<5)) | ((unsigned int)((unsigned short)(a&0x0600))>>1) | ((unsigned int)((unsigned short)a&0x001F)<<19) | (((unsigned int)(unsigned short)a&0x001C)<<14)

#define DATACTRL 1
#define RLECTRL 2
#define DIFCTRL 3

typedef unsigned char CMBYTE;
typedef unsigned int CMUINT;
typedef unsigned int CMDWORD;
typedef unsigned short CMWORD;
typedef signed int CMLONG;

#pragma pack(2)
typedef struct tagBITMAPFILEHEADER_CM {
	CMWORD    bfType;
	CMDWORD   bfSize;
	CMWORD    bfReserved1;
	CMWORD    bfReserved2;
	CMDWORD   bfOffBits;
} BITMAPFILEHEADER_CM;

#pragma pack(2)
typedef struct tagBITMAPINFOHEADER_CM {
	CMDWORD   biSize;
	CMLONG    biWidth;
	CMLONG    biHeight;
	CMWORD    biPlanes;
	CMWORD    biBitCount;
	CMDWORD   biCompression;
	CMDWORD   biSizeImage;
	CMLONG    biXPelsPerMeter;
	CMLONG    biYPelsPerMeter;
	CMDWORD   biClrUsed;
	CMDWORD   biClrImportant;
	} BITMAPINFOHEADER_CM;
#pragma pack()

typedef struct tagRGBA {
	CMBYTE red;
	CMBYTE green;
	CMBYTE blue;
	CMBYTE alpha;
} valRGBA;

class Pixel {
public:
	Pixel() {x=0; y=0; value = NULL; }
	uint32 x;
	uint32 y;
	uint32* value;
};

class BitmapUpdate;

class Bitmap {
public:
	// Constructors
	Bitmap();
	Bitmap(uint32 w, uint32 h);
	Bitmap(char* imgData, uint32 w, uint32 h, bool takeData = false);
	Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, uint32 linestep);
	Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, const char* encoding);
	Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, const char* encoding, uint32 linestep);
	Bitmap(const char* filename);
	Bitmap(BitmapUpdate* update);
	Bitmap(DataMessage* msg);
	virtual ~Bitmap();
	bool init(uint32 w, uint32 h);
	bool init(const char* imgData, uint32 size, uint32 w, uint32 h, const char* encoding, uint32 linestep);

	DataMessage* toMessage();

	BitmapUpdate* operator -( const Bitmap &bitmap ) const;
	bool updateBitmap(BitmapUpdate* update, bool takeData);
	BitmapUpdate* runLengthEncode() const;
	BitmapUpdate* runLengthDestructiveEncode() const;

	bool reset();

	// Basic Functions
	bool setPixel(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha = 0);
	bool setPixel(uint32 pos, uint8 red, uint8 green, uint8 blue, uint8 alpha = 0);
	bool setPixelXOR(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha = 0);
	bool setPixelXOR(uint32 pos, uint8 red, uint8 green, uint8 blue, uint8 alpha = 0);

	Pixel getPixel(uint32 x, uint32 y);
	bool getPixel(Pixel* pixel);

	uint32 getPos(uint32 x, uint32 y);
	double getDPos(double x, double y);
	Pixel getXY(uint32 pos);

	Color getPixelColor(uint32 x, uint32 y);

	// Bitmap Functions
	bool eraseBitmap();
	bool eraseBitmap(uint8 r, uint8 g, uint8 b, uint8 a = 0);
	bool eraseBitmap(const Color& color);
	bool replaceColor(const Color& oldColor, const Color& newColor);

	bool fillBox(const Box& box, const Color& color);
	bool fillBox(uint32 x, uint32 y, uint32 w, uint32 h, const Color& color);

	bool putTransPixel(uint32 x, uint32 y, const Color& color, double weight);
	bool drawLine(const Line& line, const Color& color);
	bool drawLine(const PolyLine& polyline, const Color& color);
	bool drawBox(const Box& box, const Color& color);
	bool drawCircle(uint32 xCenter, uint32 yCenter, uint32 radius, const Color& color, double weight, double lineWidth, bool filled = false);
	bool putQuadPixel(uint32 xCenter, uint32 yCenter, uint32 x, uint32 y, const Color& color, double weight);

	bool drawBitmap(Bitmap* bitmap, uint32 x, uint32 y);
	bool drawBitmap(Bitmap* bitmap, uint32 x, uint32 y, uint32 w, uint32 h);
	bool drawBitmap(Bitmap* bitmap, const Point& p);
	bool drawBitmap(Bitmap* bitmap, const Box& box);
	bool drawBitmap(Bitmap* bitmap, uint32 srcx, uint32 srcy, uint32 dstx, uint32 dsty, uint32 w, uint32 h);

	Bitmap* getCopy(const Box& box);

	bool canBeResizedTo(uint32 width, uint32 height);
	Bitmap* getResizedCopy(uint32 w, uint32 h, bool proportional);
	Bitmap* getResizedCopy(double scale);
	bool resizeTo(uint32 w, uint32 h, bool proportional);
	bool copyDataFromBitmap(Bitmap* bitmap, bool shouldResize = false);
	bool takeDataFromBitmap(Bitmap* bitmap);
	double getBestResizeFactor(double factor);
	double getBestResizeFactors(double factor, int &scaleUp, int &scaleDown, int &scale66);
	char* createResizedData(uint32 newWidth, uint32 newHeight, int32 scaleUp, int32 scaleDown, int32 scale66);

	//bool shape(uint32 x1, uint32 y1, uint32 x2, uint32 y2, uint32 x3, uint32 y3);
	//bool shapeSlow(uint32 x1, uint32 y1, uint32 x2, uint32 y2, uint32 x3, uint32 y3);

	//// Advanced Functions
	//bool rotate(double angle);
	//bool rotateSlow(double angle);

	// File Routines
	bool readFromMemory(const char* data, uint32 size);
	bool readFromFile(const char* filename);
	bool saveToFile(const char* filename);

	static bool convertBitmapFileData(const char* src, uint32 width, uint32 height, uint32 depth, char* dst, uint32 dstlen);
	static char* convertBitmapFileDataRunLength(const char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen);
	static char* differenceBitmapFileData(char* orig, char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen);
	static char* differenceBitmapFileDataRunLength(char* orig, char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen);

	BitmapUpdate* getCompressedUpdate(bool destructive) const;

	char* getGrayScaleDataCopy(uint32 &len);
	bool copyGrayScaleData(char* src, uint32 len);

	//int getMaxUpdates();
	//bool setMaxUpdates(uint32 max);
	bool resetBitmapUpdates();
	bool setBitmapUpdated();
	bool addBitmapUpdateRegion(const Box& updateBox);
	bool hasBitmapBeenUpdated();
	bool hasBitmapBeenTotallyChanged();

	// Public variables
//	JString name;
//	JTime timestamp;
	uint32 width;
	uint32 height;
	uint32 size;
	char* data;
	Box updateRegion;

//	int byteDepth;
//	int byteWidth;
//	int planes;
//	long size;
//	char* data;

//	long* N;
//	long* P;
//	int* L;
//	Color bgColor;
//	Color fgColor;
//	Bitmap* altBitmap;
//	char* eraseLine;

	// Math Helper Routines
	int32 round(double d);

	//HTMLPage* toHTMLBitmap();
	char* toBitmapFileFormat(uint32& len);
	static char* DataToBitmapFileFormat(const char* data, uint32 size, uint32 width,
		uint32 height, uint32& len);
	static char* DataToBitmapFileFormat(const char* data, uint32 size, uint32 width,
		uint32 height, uint32 linestep, uint32& len);
	static char* DataToBitmapFileFormat(const char* data, uint32 size, uint32 width,
		uint32 height, const char* encoding, uint32& len);
	static char* DataToBitmapFileFormat(const char* data, uint32 size, uint32 width,
		uint32 height, const char* encoding, uint32 linestep, uint32& len);

	static char* DataToEncodingFormat(const char* data, uint32 size, uint32 width,
		uint32 height, const char* srcEncoding, uint32 linestep, const char* targetEncoding, uint32& len);
};

char* ImageResizeDown66(char* bytesource, uint32 &cols, uint32 &rows);
char* ImageResizeDown(char* bytesource, uint32 &cols, uint32 &rows, uint32 factor);
char* ImageResizeUp66(char* bytesource, uint32 &cols, uint32 &rows);
char* ImageResizeUp(char* bytesource, uint32 &cols, uint32 &rows, uint32 factor);



class BitmapUpdate
{
public:
	enum Type { FULL, RUNLENGTH, RL16, DIF, DIFRUNLENGTH, NONE } type;
	// Constructors
	BitmapUpdate();
	BitmapUpdate(uint32 w, uint32 h);
	BitmapUpdate(const char* filename, bool compress);
	virtual ~BitmapUpdate();
	bool init(uint32 w, uint32 h);
	bool reset();

	bool update(BitmapUpdate* update);

	Bitmap* toBitmap();
	//HTMLPage* toHTMLBitmap();

	//	bool setWidth(int width);
	//	int getWidth();
	//	bool setHeight(int height);
	//	int getHeight();
	bool setUpdateType(BitmapUpdate::Type updateType);
	BitmapUpdate::Type getUpdateType();

	bool setFullUpdate(Bitmap* bitmap);
	bool readFromFile(const char* filename);
	bool readFromFileRLE(const char* filename);
	bool readFromFileDiff(const char* filename, Bitmap* oldBitmap);
	bool readFromFileRLEDiff(const char* filename, Bitmap* oldBitmap);

	uint32 width;
	uint32 height;
	uint32 size;
	char* data;
};


} // namespace cmlabs



#endif // _BITMAP_H_
