summaryrefslogtreecommitdiffstats
path: root/source/LinearUpscale.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/LinearUpscale.h')
-rw-r--r--source/LinearUpscale.h162
1 files changed, 160 insertions, 2 deletions
diff --git a/source/LinearUpscale.h b/source/LinearUpscale.h
index f8ba45350..60aa005bd 100644
--- a/source/LinearUpscale.h
+++ b/source/LinearUpscale.h
@@ -26,8 +26,11 @@ Regular upscaling takes two arrays and "moves" the input from src to dst; src is
-/// Linearly interpolates values in the array between the equidistant anchor points; universal data type
-template<typename TYPE> void ArrayLinearUpscale2DInPlace(
+/**
+Linearly interpolates values in the array between the equidistant anchor points (upscales).
+Works in-place (input is already present at the correct output coords)
+*/
+template<typename TYPE> void LinearUpscale2DArrayInPlace(
TYPE * a_Array,
int a_SizeX, int a_SizeY, // Dimensions of the array
int a_AnchorStepX, int a_AnchorStepY // Distances between the anchor points in each direction
@@ -74,3 +77,158 @@ template<typename TYPE> void ArrayLinearUpscale2DInPlace(
+/**
+Linearly interpolates values in the array between the equidistant anchor points (upscales).
+Works on two arrays, input is packed and output is to be completely constructed.
+*/
+template<typename TYPE> void LinearUpscale2DArray(
+ TYPE * a_Src, ///< Source array of size a_SrcSizeX x a_SrcSizeY
+ int a_SrcSizeX, int a_SrcSizeY, ///< Dimensions of the src array
+ TYPE * a_Dst, ///< Dest array, of size (a_SrcSizeX * a_UpscaleX + 1) x (a_SrcSizeY * a_UpscaleY + 1)
+ int a_UpscaleX, int a_UpscaleY ///< Upscale factor for each direction
+)
+{
+ ASSERT(a_Src != NULL);
+ ASSERT(a_Dst != NULL);
+ ASSERT(a_SrcSizeX > 0);
+ ASSERT(a_SrcSizeY > 0);
+ ASSERT(a_UpscaleX > 0);
+ ASSERT(a_UpscaleY > 0);
+
+ // First interpolate columns (same-Y) where the anchor points are:
+ int idx = 0;
+ for (int y = 0; y < a_SrcSizeY; y++)
+ {
+ int DstY = y * a_UpscaleY;
+ for (int x = 0; x < a_SrcSizeX; x++)
+ {
+ int DstX = x * a_UpscaleX;
+ TYPE StartValue = a_Src[idx]; // [x, y]
+ TYPE EndValue = a_Src[idx + a_SrcSizeX]; // [x, y + 1]
+ TYPE Diff = EndValue - StartValue;
+ for (int CellY = 0; CellY <= a_UpscaleY; CellY++)
+ {
+ a_Dst[DstX + (DstY + CellY) * a_SizeY] = StartValue + Diff * CellY / a_AnchorStepY;
+ } // for CellY
+ } // for x
+ } // for y
+
+ // Now interpolate in rows (same-X), each row already has valid values in the anchor columns
+ int DstSizeY = a_SizeY * a_UpscaleY;
+ int DstSizeX = a_SizeX * a_UpscaleX;
+ for (int y = 0; y < DstSizeY; y++)
+ {
+ int Idx = y * DstSizeX;
+ for (int x = 0; x < a_SizeX; x++)
+ {
+ TYPE StartValue = a_Dst[Idx]; // [x, y] in the src coords
+ TYPE EndValue = a_Dst[Idx + a_UpscaleX]; // [x + 1, y] in the src coords
+ TYPE Diff = EndValue - StartValue;
+ for (int CellX = 0; CellX <= a_UpscaleX; CellX++)
+ {
+ a_Dst[Idx + CellX] = StartValue + CellX * Diff / a_UpscaleX;
+ } // for CellY
+ Idx += a_UpscaleX;
+ }
+ }
+}
+
+
+
+
+
+/**
+Linearly interpolates values in the array between the equidistant anchor points (upscales).
+Works on two arrays, input is packed and output is to be completely constructed.
+*/
+template<typename TYPE> void LinearUpscale3DArray(
+ TYPE * a_Src, ///< Source array of size a_SrcSizeX x a_SrcSizeY x a_SrcSizeZ
+ int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, ///< Dimensions of the src array
+ TYPE * a_Dst, ///< Dest array, of size (a_SrcSizeX * a_UpscaleX + 1) x (a_SrcSizeY * a_UpscaleY + 1) x (a_SrcSizeZ * a_UpscaleZ + 1)
+ int a_UpscaleX, int a_UpscaleY, int a_UpscaleZ ///< Upscale factor for each direction
+)
+{
+ // For optimization reasons, we're storing the upscaling ratios in a fixed-size arrays of these sizes
+ // Feel free to enlarge them if needed, but keep in mind that they're on the stack
+ const int MAX_UPSCALE_X = 128;
+ const int MAX_UPSCALE_Y = 128;
+ const int MAX_UPSCALE_Z = 128;
+
+ ASSERT(a_Src != NULL);
+ ASSERT(a_Dst != NULL);
+ ASSERT(a_SrcSizeX > 0);
+ ASSERT(a_SrcSizeY > 0);
+ ASSERT(a_SrcSizeZ > 0);
+ ASSERT(a_UpscaleX > 0);
+ ASSERT(a_UpscaleY > 0);
+ ASSERT(a_UpscaleZ > 0);
+ ASSERT(a_UpscaleX <= MAX_UPSCALE_X);
+ ASSERT(a_UpscaleY <= MAX_UPSCALE_Y);
+ ASSERT(a_UpscaleZ <= MAX_UPSCALE_Z);
+
+ // Pre-calculate the upscaling ratios:
+ TYPE RatioX[MAX_UPSCALE_X];
+ TYPE RatioY[MAX_UPSCALE_Y];
+ TYPE RatioZ[MAX_UPSCALE_Y];
+ for (int x = 0; x <= a_UpscaleX; x++)
+ {
+ RatioX[x] = (TYPE)x / a_UpscaleX;
+ }
+ for (int y = 0; y <= a_UpscaleY; y++)
+ {
+ RatioY[y] = (TYPE)y / a_UpscaleY;
+ }
+ for (int z = 0; z <= a_UpscaleZ; z++)
+ {
+ RatioZ[z] = (TYPE)z / a_UpscaleZ;
+ }
+
+ // Interpolate each XYZ cell:
+ int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1;
+ int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1;
+ int DstSizeZ = (a_SrcSizeZ - 1) * a_UpscaleZ + 1;
+ for (int z = 0; z < (a_SrcSizeZ - 1); z++)
+ {
+ int DstZ = z * a_UpscaleZ;
+ for (int y = 0; y < (a_SrcSizeY - 1); y++)
+ {
+ int DstY = y * a_UpscaleY;
+ int idx = y * a_SrcSizeX + z * a_SrcSizeX * a_SrcSizeY;
+ for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++)
+ {
+ int DstX = x * a_UpscaleX;
+ TYPE LoXLoYLoZ = a_Src[idx];
+ TYPE LoXLoYHiZ = a_Src[idx + a_SrcSizeX * a_SrcSizeY];
+ TYPE LoXHiYLoZ = a_Src[idx + a_SrcSizeX];
+ TYPE LoXHiYHiZ = a_Src[idx + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY];
+ TYPE HiXLoYLoZ = a_Src[idx + 1];
+ TYPE HiXLoYHiZ = a_Src[idx + 1 + a_SrcSizeX * a_SrcSizeY];
+ TYPE HiXHiYLoZ = a_Src[idx + 1 + a_SrcSizeX];
+ TYPE HiXHiYHiZ = a_Src[idx + 1 + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY];
+ for (int CellZ = 0; CellZ <= a_UpscaleZ; CellZ++)
+ {
+ TYPE LoXLoYInZ = LoXLoYLoZ + (LoXLoYHiZ - LoXLoYLoZ) * RatioZ[CellZ];
+ TYPE LoXHiYInZ = LoXHiYLoZ + (LoXHiYHiZ - LoXHiYLoZ) * RatioZ[CellZ];
+ TYPE HiXLoYInZ = HiXLoYLoZ + (HiXLoYHiZ - HiXLoYLoZ) * RatioZ[CellZ];
+ TYPE HiXHiYInZ = HiXHiYLoZ + (HiXHiYHiZ - HiXHiYLoZ) * RatioZ[CellZ];
+ for (int CellY = 0; CellY <= a_UpscaleY; CellY++)
+ {
+ int DestIdx = (DstZ + CellZ) * DstSizeX * DstSizeY + (DstY + CellY) * DstSizeX + DstX;
+ ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY * DstSizeZ);
+ TYPE LoXInY = LoXLoYInZ + (LoXHiYInZ - LoXLoYInZ) * RatioY[CellY];
+ TYPE HiXInY = HiXLoYInZ + (HiXHiYInZ - HiXLoYInZ) * RatioY[CellY];
+ for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++)
+ {
+ a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX];
+ }
+ } // for CellY
+ } // for CellZ
+ } // for x
+ } // for y
+ } // for z
+}
+
+
+
+
+