

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.1.1.260726 (26 July 2026)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2026
//_/_/  
//_/_/  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.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
/*! @file Bitmap.h
    @brief In-memory RGBA raster image (Bitmap) with drawing primitives, resizing, BMP file I/O and delta/RLE compression (BitmapUpdate).

    Pixels are stored as 32-bit RGBA in a contiguous buffer, row-major from
    the top-left. The GET_*_FROM_* macros manipulate packed pixel values and
    assume little-endian byte order (R in the lowest byte), matching the
    Windows BMP layout used by the file routines. BitmapUpdate carries either
    a full frame or a compressed difference so remote views can be refreshed
    incrementally. */
#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)
/*! @brief BMP file header (14 bytes), local packed definition so no windows.h dependency is needed. */
typedef struct tagBITMAPFILEHEADER_CM {
	CMWORD    bfType;
	CMDWORD   bfSize;
	CMWORD    bfReserved1;
	CMWORD    bfReserved2;
	CMDWORD   bfOffBits;
} BITMAPFILEHEADER_CM;

#pragma pack(2)
/*! @brief BMP info header (40 bytes, BITMAPINFOHEADER equivalent), packed to 2-byte alignment for direct file mapping. */
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()

/*! @brief One RGBA pixel value as separate byte components. */
typedef struct tagRGBA {
	CMBYTE red;
	CMBYTE green;
	CMBYTE blue;
	CMBYTE alpha;
} valRGBA;

/*! @brief Reference to one pixel: coordinates plus a pointer directly into the owning Bitmap's data (no copy). */
class Pixel {
public:
	Pixel() {x=0; y=0; value = NULL; }
	uint32 x;
	uint32 y;
	uint32* value;
};

class BitmapUpdate;

/*! @brief 32-bit RGBA raster image with drawing, compositing, scaling, BMP I/O and update-region tracking.

    Pixel layout: @c data holds width*height packed 32-bit pixels (@c size =
    width*height*4 bytes), row-major starting at the <b>top-left</b> corner
    with no per-row padding (stride is always width*4; constructors that take
    a @p linestep repack padded source rows during the copy). Within a pixel,
    byte order is R, G, B, A in increasing addresses, i.e. on a little-endian
    machine a pixel read as uint32 has R in the least significant byte — this
    is what the GET_*_FROM_RGBA macros assume. Note this is the opposite
    vertical order to a BMP file (bottom-up); the file routines flip rows on
    load/save via convertBitmapFileData().

    Ownership: the Bitmap owns @c data and frees it in the destructor and in
    reset()/init(). The constructor taking @c takeData=true adopts the
    caller's malloc'd buffer instead of copying — the caller must not free it
    afterwards. takeDataFromBitmap() similarly transfers the buffer between
    Bitmap objects, leaving the source empty. Methods documented as returning
    "caller owns" allocate fresh buffers/objects the caller must delete/free.

    Thread-safety: none — there is no internal locking; guard shared Bitmaps
    externally.

    Most drawing methods clip against the image bounds and return false on
    invalid input. The updateRegion box accumulates dirty areas between
    resetBitmapUpdates() calls so consumers can send incremental refreshes.

    @code
    Bitmap bmp(320, 240);
    bmp.eraseBitmap(Color(255, 255, 255));            // white background
    bmp.fillBox(10, 10, 100, 50, Color(255, 0, 0));   // red rectangle
    bmp.drawCircle(160, 120, 40, Color(0, 0, 255), 1.0, 1.0, false);
    bmp.saveToFile("out.bmp");

    // Incremental remote refresh:
    BitmapUpdate* full = bmp.getCompressedUpdate(false);  // RLE full frame
    Bitmap remote(full);                                  // remote side decodes
    delete full;
    bmp.fillBox(0, 0, 32, 32, Color(0, 255, 0));          // change something
    BitmapUpdate* diff = bmp - remote;                    // delta remote -> bmp
    remote.updateBitmap(diff, false);                     // remote now matches
    delete diff;
    @endcode */
class Bitmap {
public:
	// Constructors
	Bitmap(); //!< Empty 0x0 bitmap.
	Bitmap(uint32 w, uint32 h); //!< Allocate a w x h bitmap (uninitialized pixels).
	Bitmap(char* imgData, uint32 w, uint32 h, bool takeData = false); //!< Wrap or copy existing RGBA data. @param imgData RGBA pixel buffer. @param w,h Dimensions in pixels. @param takeData Take ownership instead of copying.
	Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, uint32 linestep); //!< Copy from a buffer with per-row stride @p linestep bytes.
	Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, const char* encoding); //!< Convert from another pixel encoding (e.g. "RGB", "GRAY", "YUV") into RGBA.
	Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, const char* encoding, uint32 linestep); //!< Convert from another encoding with explicit stride.
	Bitmap(const char* filename); //!< Load from a BMP file.
	Bitmap(BitmapUpdate* update); //!< Reconstruct from a (full) BitmapUpdate.
	Bitmap(DataMessage* msg); //!< Deserialize from a DataMessage produced by toMessage().
	virtual ~Bitmap();
	bool init(uint32 w, uint32 h); //!< (Re)allocate as w x h. @return true on success.
	bool init(const char* imgData, uint32 size, uint32 w, uint32 h, const char* encoding, uint32 linestep); //!< (Re)initialize from encoded data. @return true on success.

	DataMessage* toMessage(); //!< Serialize into a new DataMessage (caller owns). @return Message or NULL.

	BitmapUpdate* operator -( const Bitmap &bitmap ) const; //!< Difference update transforming @p bitmap into this image. @return New update (caller owns).
	bool updateBitmap(BitmapUpdate* update, bool takeData); //!< Apply a full/RLE/diff update. @param update The update to apply. @param takeData Steal the update's buffer when possible. @return true on success.
	BitmapUpdate* runLengthEncode() const; //!< RLE-compress the full image. @return New update (caller owns).
	BitmapUpdate* runLengthDestructiveEncode() const; //!< RLE-compress, allowed to modify this image's buffer for speed. @return New update.

	bool reset(); //!< Release pixel data and return to the empty state. @return true.

	bool mirror(bool horizontal, bool vertical); //!< Flip in place along the requested axes. @return true on success.

	// Basic Functions
	bool setPixel(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha = 0); //!< Set the pixel at (x,y). @return false when out of bounds.
	bool setPixel(uint32 pos, uint8 red, uint8 green, uint8 blue, uint8 alpha = 0); //!< Set the pixel at linear index @p pos.
	bool setPixelXOR(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha = 0); //!< XOR the color into the pixel at (x,y) (reversible marker drawing).
	bool setPixelXOR(uint32 pos, uint8 red, uint8 green, uint8 blue, uint8 alpha = 0); //!< XOR the color into the pixel at linear index @p pos.

	Pixel getPixel(uint32 x, uint32 y); //!< Get a Pixel referencing (x,y); value pointer is NULL when out of bounds.
	bool getPixel(Pixel* pixel); //!< Fill @p pixel->value from its x/y coordinates. @return false when out of bounds.

	uint32 getPos(uint32 x, uint32 y); //!< Linear pixel index of (x,y) = y*width+x.
	double getDPos(double x, double y); //!< Fractional linear index for sub-pixel coordinates.
	Pixel getXY(uint32 pos); //!< Inverse of getPos(): coordinates for a linear index.

	Color getPixelColor(uint32 x, uint32 y); //!< Pixel color at (x,y) as a Color value (black when out of bounds).

	// Bitmap Functions
	bool eraseBitmap(); //!< Fill with black/zero. @return true on success.
	bool eraseBitmap(uint8 r, uint8 g, uint8 b, uint8 a = 0); //!< Fill with the given RGBA color.
	bool eraseBitmap(const Color& color); //!< Fill with @p color.
	bool replaceColor(const Color& oldColor, const Color& newColor); //!< Replace every exact occurrence of @p oldColor with @p newColor.

	bool fillBox(const Box& box, const Color& color); //!< Fill a rectangle (clipped to the image). @return true on success.
	bool fillBox(uint32 x, uint32 y, uint32 w, uint32 h, const Color& color); //!< Fill a rectangle given by scalars.

	bool putTransPixel(uint32 x, uint32 y, const Color& color, double weight); //!< Alpha-blend @p color onto the pixel with fraction @p weight [0,1] (anti-aliasing helper).
	bool drawLine(const Line& line, const Color& color); //!< Draw a (possibly anti-aliased) line segment.
	bool drawLine(const PolyLine& polyline, const Color& color); //!< Draw every segment of a polyline.
	bool drawBox(const Box& box, const Color& color); //!< Draw a rectangle outline.
	bool drawCircle(uint32 xCenter, uint32 yCenter, uint32 radius, const Color& color, double weight, double lineWidth, bool filled = false); //!< Draw a circle. @param xCenter,yCenter Center in pixels. @param radius Radius in pixels. @param color Stroke/fill color. @param weight Blend fraction. @param lineWidth Stroke width. @param filled Fill the disc when true.
	bool putQuadPixel(uint32 xCenter, uint32 yCenter, uint32 x, uint32 y, const Color& color, double weight); //!< Plot the 4 symmetric points of a circle octant (internal helper for drawCircle()).

	bool drawBitmap(Bitmap* bitmap, uint32 x, uint32 y); //!< Blit @p bitmap with its upper-left corner at (x,y).
	bool drawBitmap(Bitmap* bitmap, uint32 x, uint32 y, uint32 w, uint32 h); //!< Blit @p bitmap scaled/clipped into a w x h area at (x,y).
	bool drawBitmap(Bitmap* bitmap, const Point& p); //!< Blit at a Point.
	bool drawBitmap(Bitmap* bitmap, const Box& box); //!< Blit into a Box area.
	bool drawBitmap(Bitmap* bitmap, uint32 srcx, uint32 srcy, uint32 dstx, uint32 dsty, uint32 w, uint32 h); //!< Blit a w x h sub-region from (srcx,srcy) of @p bitmap to (dstx,dsty).

	Bitmap* getCopy(const Box& box); //!< Extract a sub-image (caller owns). @return New bitmap or NULL.

	bool canBeResizedTo(uint32 width, uint32 height); //!< Check whether the integer-ratio resizer supports this target size.
	Bitmap* getResizedCopy(uint32 w, uint32 h, bool proportional); //!< Resized copy (caller owns). @param w,h Target dimensions in pixels. @param proportional Preserve aspect ratio (letterboxing target size).
	Bitmap* getResizedCopy(double scale); //!< Resized copy by uniform factor @p scale.
	bool resizeTo(uint32 w, uint32 h, bool proportional); //!< Resize in place. @return true on success.
	bool copyDataFromBitmap(Bitmap* bitmap, bool shouldResize = false); //!< Copy pixels from @p bitmap; optionally resize this image to fit.
	bool takeDataFromBitmap(Bitmap* bitmap); //!< Steal the pixel buffer from @p bitmap (which becomes empty); no copy.
	double getBestResizeFactor(double factor); //!< Snap @p factor to the nearest factor achievable by the fast integer resizers.
	double getBestResizeFactors(double factor, int &scaleUp, int &scaleDown, int &scale66); //!< Decompose @p factor into up/down/66% passes used by createResizedData(). @return Achieved factor.
	char* createResizedData(uint32 newWidth, uint32 newHeight, int32 scaleUp, int32 scaleDown, int32 scale66); //!< Produce a resized pixel buffer using the given pass counts (caller frees).

	//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); //!< Parse a BMP file image from memory. @return true on success.
	bool readFromFile(const char* filename); //!< Load a BMP file. @return true on success.
	bool saveToFile(const char* filename); //!< Save as a BMP file. @return true on success.

	static bool convertBitmapFileData(const char* src, uint32 width, uint32 height, uint32 depth, char* dst, uint32 dstlen); //!< Convert raw BMP pixel rows (bottom-up, padded) into the internal top-down RGBA layout. @return true on success.
	static char* convertBitmapFileDataRunLength(const char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen); //!< As convertBitmapFileData() but RLE-compressing on the fly. @return Allocated buffer (caller frees).
	static char* differenceBitmapFileData(char* orig, char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen); //!< Encode the difference between two frames. @return Allocated diff buffer (caller frees).
	static char* differenceBitmapFileDataRunLength(char* orig, char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen); //!< Difference encoding + RLE compression. @return Allocated buffer (caller frees).

	BitmapUpdate* getCompressedUpdate(bool destructive) const; //!< Full-frame update, RLE compressed. @param destructive Allow modifying this bitmap's buffer for speed. @return New update.

	char* getGrayScaleDataCopy(uint32 &len); //!< 8-bit grayscale copy of the image. @param[out] len Buffer size. @return Allocated buffer (caller frees).
	bool copyGrayScaleData(char* src, uint32 len); //!< Fill this RGBA image from an 8-bit grayscale buffer of matching size. @return true on success.

	//int getMaxUpdates();
	//bool setMaxUpdates(uint32 max);
	bool resetBitmapUpdates(); //!< Clear the dirty-region tracking. @return true.
	bool setBitmapUpdated(); //!< Mark the whole image as changed. @return true.
	bool addBitmapUpdateRegion(const Box& updateBox); //!< Grow the dirty region to include @p updateBox. @return true.
	bool hasBitmapBeenUpdated(); //!< @return true when any region changed since the last reset.
	bool hasBitmapBeenTotallyChanged(); //!< @return true when the dirty region covers the whole image.

	// Public variables
//	JString name;
//	JTime timestamp;
	uint32 width;  //!< Width in pixels.
	uint32 height; //!< Height in pixels.
	uint32 size;   //!< Data buffer size in bytes (width*height*4).
	char* data;    //!< Pixel data, 32-bit RGBA, row-major top-down.
	Box updateRegion; //!< Accumulated dirty region since the last resetBitmapUpdates().

//	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); //!< Round to nearest integer (helper for pixel math).

	//HTMLPage* toHTMLBitmap();
	char* toBitmapFileFormat(uint32& len); //!< Serialize this image as a complete BMP file in memory. @param[out] len File size. @return Allocated buffer (caller frees).
	/*! @brief Convert raw RGBA data into a BMP file image in memory. @param data Source pixels. @param size Source size in bytes. @param width,height Dimensions in pixels. @param[out] len File size. @return Allocated buffer (caller frees). */
	static char* DataToBitmapFileFormat(const char* data, uint32 size, uint32 width,
		uint32 height, uint32& len);
	/*! @brief As above, with an explicit source row stride @p linestep in bytes. */
	static char* DataToBitmapFileFormat(const char* data, uint32 size, uint32 width,
		uint32 height, uint32 linestep, uint32& len);
	/*! @brief Convert pixel data in another encoding (e.g. "RGB", "GRAY", "YUV") to a BMP file image. */
	static char* DataToBitmapFileFormat(const char* data, uint32 size, uint32 width,
		uint32 height, const char* encoding, uint32& len);
	/*! @brief Encoded-source variant with an explicit row stride. */
	static char* DataToBitmapFileFormat(const char* data, uint32 size, uint32 width,
		uint32 height, const char* encoding, uint32 linestep, uint32& len);

	/*! @brief General pixel-format converter between named encodings.
	    @param data Source pixels. @param size Source size in bytes. @param width,height Dimensions.
	    @param srcEncoding Source format name. @param linestep Source row stride in bytes. @param targetEncoding Destination format name.
	    @param[out] len Destination size. @return Allocated buffer (caller frees) or NULL when a conversion is unsupported. */
	static char* DataToEncodingFormat(const char* data, uint32 size, uint32 width,
		uint32 height, const char* srcEncoding, uint32 linestep, const char* targetEncoding, uint32& len);

	/*! @brief Self test for Bitmap and BitmapUpdate. @return true when all checks pass. */
	static bool UnitTest();
};

/*! @brief Shrink an RGBA image to 2/3 size (3→2 pixel averaging). @param bytesource Source pixels. @param[in,out] cols,rows Dimensions, updated to the new size. @return Allocated buffer (caller frees). */
char* ImageResizeDown66(char* bytesource, uint32 &cols, uint32 &rows);
/*! @brief Shrink an RGBA image by an integer factor (box averaging). @param bytesource Source pixels. @param factor Divisor. @param[in,out] cols,rows Updated dimensions. @return Allocated buffer (caller frees). */
char* ImageResizeDown(char* bytesource, uint32 &cols, uint32 &rows, uint32 factor);
/*! @brief Enlarge an RGBA image to 3/2 size (2→3 pixel interpolation). @param bytesource Source pixels. @param[in,out] cols,rows Updated dimensions. @return Allocated buffer (caller frees). */
char* ImageResizeUp66(char* bytesource, uint32 &cols, uint32 &rows);
/*! @brief Enlarge an RGBA image by an integer factor (pixel replication). @param bytesource Source pixels. @param factor Multiplier. @param[in,out] cols,rows Updated dimensions. @return Allocated buffer (caller frees). */
char* ImageResizeUp(char* bytesource, uint32 &cols, uint32 &rows, uint32 factor);



/*! @brief Transportable image update: either a full frame or a compressed (RLE and/or difference) delta against a previous frame.

    Produced by Bitmap::operator-, runLengthEncode() and getCompressedUpdate();
    consumed by Bitmap::updateBitmap(). Difference-typed updates (DIF,
    DIFRUNLENGTH) are only meaningful when applied to a bitmap holding the
    exact frame they were diffed against, and of matching dimensions; applying
    them to anything else yields garbage pixels. Only FULL-equivalent payloads
    can be decoded standalone via toBitmap(). The object owns @c data and
    releases it in reset()/destructor. */
class BitmapUpdate
{
public:
	/*! @brief Payload encoding: FULL raw frame, RUNLENGTH RLE frame, RL16 16-bit RLE, DIF raw difference, DIFRUNLENGTH RLE difference, NONE empty. */
	enum Type { FULL, RUNLENGTH, RL16, DIF, DIFRUNLENGTH, NONE } type;
	// Constructors
	BitmapUpdate(); //!< Empty update.
	BitmapUpdate(uint32 w, uint32 h); //!< Pre-sized update for a w x h frame.
	BitmapUpdate(const char* filename, bool compress); //!< Load a BMP file as an update. @param filename BMP file path. @param compress RLE-compress the payload.
	virtual ~BitmapUpdate();
	bool init(uint32 w, uint32 h); //!< (Re)initialize for a w x h frame. @return true on success.
	bool reset(); //!< Release the payload. @return true.

	bool update(BitmapUpdate* update); //!< Merge a newer update into this one. @return true on success.

	Bitmap* toBitmap(); //!< Decode into a new full Bitmap (caller owns); requires a FULL-equivalent payload. @return Bitmap or NULL.
	//HTMLPage* toHTMLBitmap();

	bool setUpdateType(BitmapUpdate::Type updateType); //!< Set the payload encoding tag. @return true.
	BitmapUpdate::Type getUpdateType(); //!< @return Payload encoding tag.

	bool setFullUpdate(Bitmap* bitmap); //!< Fill as an uncompressed full frame from @p bitmap. @return true on success.
	bool readFromFile(const char* filename); //!< Load a BMP file as a FULL update. @return true on success.
	bool readFromFileRLE(const char* filename); //!< Load a BMP file and RLE-compress it. @return true on success.
	bool readFromFileDiff(const char* filename, Bitmap* oldBitmap); //!< Load a BMP file and store the difference against @p oldBitmap. @return true on success.
	bool readFromFileRLEDiff(const char* filename, Bitmap* oldBitmap); //!< Load, difference against @p oldBitmap and RLE-compress. @return true on success.

	uint32 width;  //!< Frame width in pixels.
	uint32 height; //!< Frame height in pixels.
	uint32 size;   //!< Payload size in bytes.
	char* data;    //!< Encoded payload (interpretation depends on @c type).
};


} // namespace cmlabs



#endif // _BITMAP_H_
