summaryrefslogtreecommitdiffstats
path: root/Tools/AnvilStats
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/AnvilStats')
-rw-r--r--Tools/AnvilStats/AnvilStats.vcproj8
-rw-r--r--Tools/AnvilStats/ImageComposingCallback.cpp189
-rw-r--r--Tools/AnvilStats/ImageComposingCallback.h95
3 files changed, 292 insertions, 0 deletions
diff --git a/Tools/AnvilStats/AnvilStats.vcproj b/Tools/AnvilStats/AnvilStats.vcproj
index ed4ffa9a5..b6000ea3e 100644
--- a/Tools/AnvilStats/AnvilStats.vcproj
+++ b/Tools/AnvilStats/AnvilStats.vcproj
@@ -322,6 +322,14 @@
>
</File>
<File
+ RelativePath=".\ImageComposingCallback.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ImageComposingCallback.h"
+ >
+ </File>
+ <File
RelativePath=".\Processor.cpp"
>
</File>
diff --git a/Tools/AnvilStats/ImageComposingCallback.cpp b/Tools/AnvilStats/ImageComposingCallback.cpp
new file mode 100644
index 000000000..138821698
--- /dev/null
+++ b/Tools/AnvilStats/ImageComposingCallback.cpp
@@ -0,0 +1,189 @@
+
+// ImageComposingCallback.cpp
+
+// Implements the cImageComposingCallback class that implements a subset of cCallback for composing per-region images
+
+#include "Globals.h"
+#include "ImageComposingCallback.h"
+
+
+
+
+
+cImageComposingCallback::cImageComposingCallback(const AString & a_FileNamePrefix) :
+ m_FileNamePrefix(a_FileNamePrefix),
+ m_CurrentRegionX(INVALID_REGION_COORD),
+ m_CurrentRegionZ(INVALID_REGION_COORD),
+ m_ImageData(new int[32 * 16 * 32 * 16])
+{
+}
+
+
+
+
+
+cImageComposingCallback::~cImageComposingCallback()
+{
+ delete[] m_ImageData;
+}
+
+
+
+
+
+bool cImageComposingCallback::OnNewRegion(int a_RegionX, int a_RegionZ)
+{
+ ASSERT(m_CurrentRegionX == INVALID_REGION_COORD);
+ ASSERT(m_CurrentRegionZ == INVALID_REGION_COORD); // Has any previous region been finished properly?
+
+ m_CurrentRegionX = a_RegionX;
+ m_CurrentRegionZ = a_RegionZ;
+ OnEraseImage();
+
+ return CALLBACK_CONTINUE;
+}
+
+
+
+
+
+void cImageComposingCallback::OnRegionFinished(int a_RegionX, int a_RegionZ)
+{
+ ASSERT(m_CurrentRegionX != INVALID_REGION_COORD);
+ ASSERT(m_CurrentRegionZ != INVALID_REGION_COORD); // Has a region been started properly?
+ ASSERT(m_CurrentRegionX == a_RegionX);
+ ASSERT(m_CurrentRegionZ == a_RegionZ); // Is it the same region that has been started?
+
+ AString FileName = GetFileName(a_RegionX, a_RegionZ);
+ if (!FileName.empty())
+ {
+ OnBeforeImageSaved(a_RegionX, a_RegionZ, FileName);
+ SaveImage(FileName);
+ OnAfterImageSaved(a_RegionX, a_RegionZ, FileName);
+ }
+
+ m_CurrentRegionX = INVALID_REGION_COORD;
+ m_CurrentRegionZ = INVALID_REGION_COORD;
+}
+
+
+
+
+
+AString cImageComposingCallback::GetFileName(int a_RegionX, int a_RegionZ)
+{
+ return Printf("%s.%d.%d", m_FileNamePrefix.c_str(), a_RegionX, a_RegionZ);
+}
+
+
+
+
+
+void cImageComposingCallback::OnEraseImage(void)
+{
+ // By default erase the image to black:
+ EraseImage(0);
+}
+
+
+
+
+
+void cImageComposingCallback::EraseImage(int a_Color)
+{
+ for (int i = 0; i < PIXEL_COUNT; i++)
+ {
+ m_ImageData[i] = a_Color;
+ }
+}
+
+
+
+
+
+void cImageComposingCallback::EraseChunk(int a_Color, int a_RelChunkX, int a_RelChunkZ)
+{
+ int Base = a_RelChunkZ * IMAGE_HEIGHT + a_RelChunkX * 16;
+ for (int v = 0; v < 16; v++)
+ {
+ int BaseV = Base + v * IMAGE_HEIGHT;
+ for (int u = 0; u < 16; u++)
+ {
+ m_ImageData[BaseV + u] = a_Color;
+ }
+ } // for y
+}
+
+
+
+
+
+void cImageComposingCallback::SetPixel(int a_RelU, int a_RelV, int a_Color)
+{
+ ASSERT((a_RelU >= 0) && (a_RelU < IMAGE_WIDTH));
+ ASSERT((a_RelV >= 0) && (a_RelV < IMAGE_HEIGHT));
+
+ m_ImageData[a_RelU + IMAGE_WIDTH * a_RelV] = a_Color;
+}
+
+
+
+
+
+int cImageComposingCallback::GetPixel(int a_RelU, int a_RelV)
+{
+ if ((a_RelU < 0) || (a_RelU >= IMAGE_WIDTH) || (a_RelV < 0) || (a_RelV >= IMAGE_HEIGHT))
+ {
+ // Outside the image data
+ return -1;
+ }
+
+ return m_ImageData[a_RelU + IMAGE_WIDTH * a_RelV];
+}
+
+
+
+
+
+
+void cImageComposingCallback::SetPixelURow(int a_RelUStart, int a_RelV, int a_CountU, int * a_Pixels)
+{
+ ASSERT((a_RelUStart >= 0) && (a_RelUStart + a_CountU < IMAGE_WIDTH));
+ ASSERT((a_RelV >= 0) && (a_RelV < IMAGE_HEIGHT));
+ ASSERT(a_Pixels != NULL);
+
+ int Base = a_RelUStart + a_RelV * IMAGE_WIDTH;
+ for (int u = 0; u < a_CountU; u++)
+ {
+ m_ImageData[Base + u] = a_Pixels[u];
+ }
+}
+
+
+
+
+
+void cImageComposingCallback::SaveImage(const AString & a_FileName)
+{
+ cFile f(a_FileName, cFile::fmWrite);
+ if (!f.IsOpen())
+ {
+ return;
+ }
+
+ // Header for BMP files (is the same for the same-size files)
+ static const unsigned char BMPHeader[] =
+ {
+ 0x42, 0x4D, 0x36, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ } ;
+
+ f.Write(BMPHeader, sizeof(BMPHeader));
+ f.Write(m_ImageData, PIXEL_COUNT * 4);
+}
+
+
+
+
diff --git a/Tools/AnvilStats/ImageComposingCallback.h b/Tools/AnvilStats/ImageComposingCallback.h
new file mode 100644
index 000000000..c04dc869f
--- /dev/null
+++ b/Tools/AnvilStats/ImageComposingCallback.h
@@ -0,0 +1,95 @@
+
+// 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);
+
+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);
+} ;
+
+
+
+