// ImageComposingCallback // Declares the cImageComposingCallback class that implements a subset of cCallback for composing per-region images #pragma once #include "Callback.h" /** Implements the plumbing for composing per-region images from multiple chunks. To use this class, create a descendant that writes the image data using SetPixel() or SetPixelURow() functions. For the purpose of this class the image data is indexed U (horz) * V (vert), to avoid confusion with other coords. The image is a 32bpp raw imagedata, written into a BMP file. */ class cImageComposingCallback : public cCallback { public: enum { INVALID_REGION_COORD = 99999, ///< Used for un-assigned region coords IMAGE_WIDTH = 32 * 16, IMAGE_HEIGHT = 32 * 16, PIXEL_COUNT = IMAGE_WIDTH * IMAGE_HEIGHT, ///< Total pixel count of the image data }; cImageComposingCallback(const AString & a_FileNamePrefix); virtual ~cImageComposingCallback(); // cCallback overrides: virtual bool OnNewRegion(int a_RegionX, int a_RegionZ) override; virtual void OnRegionFinished(int a_RegionX, int a_RegionZ) override; // New introduced overridable functions: /** Called when a file is about to be saved, to generate the filename */ virtual AString GetFileName(int a_RegionX, int a_RegionZ); /** Called before the file is saved */ virtual void OnBeforeImageSaved(int a_RegionX, int a_RegionZ, const AString & a_FileName) {} /** Called after the image is saved to a file */ virtual void OnAfterImageSaved(int a_RegionX, int a_RegionZ, const AString & a_FileName) {} /** Called when a new region is beginning, to erase the image data */ virtual void OnEraseImage(void); // Functions for manipulating the image: /** Erases the entire image with the specified color */ void EraseImage(int a_Color); /** Erases the specified chunk's portion of the image with the specified color. Note that chunk coords are relative * to the current region */ void EraseChunk(int a_Color, int a_RelChunkX, int a_RelChunkZ); /** Returns the current region X coord */ int GetCurrentRegionX(void) const { return m_CurrentRegionX; } /** Returns the current region Z coord */ int GetCurrentRegionZ(void) const { return m_CurrentRegionZ; } /** Sets the pixel at the specified UV coords to the specified color */ void SetPixel(int a_RelU, int a_RelV, int a_Color); /** Returns the color of the pixel at the specified UV coords; -1 if outside */ int GetPixel(int a_RelU, int a_RelV); /** Sets a row of pixels. a_Pixels is expected to be a_CountU pixels wide. a_RelUStart + a_CountU is assumed less * than image width */ void SetPixelURow(int a_RelUStart, int a_RelV, int a_CountU, int * a_Pixels); /** "Shades" the given color based on the shade amount given Shade amount 0 .. 63 shades the color from black to a_Color. Shade amount 64 .. 127 shades the color from a_Color to white. All other shade amounts have undefined results. */ static int ShadeColor(int a_Color, int a_Shade); /** Mixes the two colors in the specified ratio; a_Ratio is between 0 and 256, 0 returning a_Src */ static int MixColor(int a_Src, int a_Dest, int a_Ratio); protected: /** Prefix for the filenames, when generated by the default GetFileName() function */ AString m_FileNamePrefix; /** Coords of the currently processed region */ int m_CurrentRegionX, m_CurrentRegionZ; /** Raw image data; 1 MiB worth of data, therefore unsuitable for stack allocation. [u + IMAGE_WIDTH * v] */ int * m_ImageData; void SaveImage(const AString & a_FileName); };