Introduction to 2D Linux Game Programming/Algorithms/Simple Software Transformations/Optimized Integer Scaling

From Wikibooks, open books for an open world
< Introduction to 2D Linux Game Programming
Jump to: navigation, search

Optimized Image Scaling [edit]

This takes the previous, non-optimzed version of the integer scaling program and changes a few things to make it much quicker.

The Source: [edit]

// 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);
}