Optimized Integer Scaling
Downloadable Source:
IntegerScale.cpp
Introduction
Viewable Source
Introduction
This is very similar to the non-optimized integer scaling tutorial. To optimize the code as much as possible we precalculate where possible. The big optimization is once we've calculated one scaled row rather than recalculate it scale - 1 times we copy it.
Except for the line "dest[ ((h*scale * width*scale) + (hrepeat * width*scale)) + (w*scale + wrepeat)] = source[(h*width) + w];" the new integer scale is a little trickier to read, but by removing so many calculations the speed increase is significant.
The Source:
// IntegerScale.cpp
#include <iostream>
#include "include/S.h"
using namespace std;
/************************************************************
* This is the speed optimized version of our IntegerScale()
* function. Readability is a distant second to speed.
* We pre-calculate everything we can rather than calculating
* over and over in the inner for loops. Where we can't
* pre-calculate, we move the calculation as "high" up in the
* for loop chain as we can. We move definitions of variables
* out of the loops so they're defined once rather than every
* iteration. Instead of rebuilding a row scale times we
* calculate it once, then copy it scale-1 times. It is a
* much quicker algorithm, but it's also much more difficult
* to read or explain. After seeing the original, unoptomized
* scale function, it should be easier to see what this one
* is doing.
************************************************************/
int main()
{
// All the variables that can be pre-calculated
// and do not change in the for loops
const int width = S::sw(); // The original Array's width
const int height = S::sh(width); // The original Array's height
const int scale = S::ss(width); // How many times to scale the image
const int s_size = width*height; // Size of source image
const int widthscale = width*scale;
const int scalewidthscale = scale*widthscale;
const int heightscale = height*scale;
// Our source and destination arrays
int source[s_size]; // Original Array
int dest[scalewidthscale * height]; // Scaled Array
// Pointers for the line we're going to copy
int *repeat; // Address of first element of row we're copying
int *traverserepeat; // Address of the element we're copying
int *traversedest; // Address we're copying to in dest array
// Setup our source "image"
for(int x = 0; x < s_size; ++x)
source[x]=x;
cout << "\n\n";
S::print_rect(width, height, &source[0]);
cout << "\n\n";
// The following for loop iterators
// defined out of the for loop to
// avoid recreating them every time
// we drop out of the inner loops
int hrepeat = 0; // height repeat
int w = 0; // width counter
int wrepeat = 0; // width repeat
// Integers we calculate as high up in the for loops
// as possible
int hscalewidthscale; // h * scale * width * scale
int wscale; // w * scale
int hwidth; // h * width
for(int h = 0; h < height; ++h) // Source Height Position
{
hscalewidthscale = h*scalewidthscale;
// Set the address of the first element of the array
// We're going to copy
repeat=&dest[hscalewidthscale];
for(; hrepeat < scale; ++hrepeat) // Repeat a full row scale times
{
if(hrepeat==0) // This is a new line in the source image
{
for(; w < width; ++w) // Source width Offset
{
wscale = w*scale;
hwidth = h*width;
// Repeat individual pixel scale times
for(; wrepeat < scale; ++wrepeat)
dest[hscalewidthscale + wscale + wrepeat] = source[ hwidth + w];
wrepeat = 0;
}
w = 0;
}
else
{
// The initial element we're going to copy
traverserepeat=repeat;
// The initial element to copy to dest[]
traversedest=&repeat[hrepeat*widthscale];
for(; w < width; ++w)
{
wscale = w*scale;
for(; wrepeat < scale; ++wrepeat)
{
// Copy a value into dest[]
*traversedest=*traverserepeat;
// Traverse the array we're
// copying from and into
++traversedest;
++traverserepeat;
}
wrepeat=0;
}
w = 0;
}
}
hrepeat = 0;
}
S::print_rect(widthscale,heightscale,&dest[0]);
cout << "\n" << endl;
return(0);
}