Irbis
Irbis

Reputation: 1491

pointer to texture data - flip data vertically

I use a library for loading textures which returns a pointer to data, image width and height. I would like to flip a texture data vertically so I have created the following function:

void FlipYTexture(const unsigned int width, const unsigned int height, uint8_t* data)
{
    const unsigned int rowsSwapCount = height / 2;
    const unsigned int maxRowIndex = height - 1;

    for (int i = 0; i < rowsSwapCount; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            const unsigned int currentDataIndex = width * i + j;
            const unsigned int swapDataIndex = width * (maxRowIndex - i) + j;

            uint8_t temp = data[currentDataIndex];
            data[currentDataIndex] = data[swapDataIndex];
            data[swapDataIndex] = temp;
        }
    } 
}

Is there any way to optimize that function and/or implement it simpler ?

Upvotes: 0

Views: 242

Answers (2)

Richard Hodges
Richard Hodges

Reputation: 69854

Factoring out the inner loop to a standard algorithm, and using simplified pointer arithmetic:

#include <cstdint>
#include <algorithm>

void FlipYTexture(unsigned width, unsigned height, uint8_t* data)
{
    auto row_offset = [&](unsigned row)
    {
        return row * height;
    };

    // pointer arithmetic once up front
    auto first_row = data + row_offset(0);
    auto last_row = data + row_offset(height / 2);
    auto other_row = data + row_offset(height);

    // swap each row
    for ( ; first_row != last_row ; first_row += width )
    {
        other_row -= width;
        std::swap_ranges(first_row, first_row + width, other_row);
    }
}

Upvotes: 0

Scott Hutchinson
Scott Hutchinson

Reputation: 1721

If you could change the data parameter from a pointer to an array reference, then this would be a simpler option, though I don't know that it would be faster without testing it with typical input data.

#include <algorithm>

template<typename T, size_t N> 
void FlipYTexture(const unsigned int width, const unsigned int height, T(&data)[N]) {
    std::reverse(std::begin(data), std::end(data));
}

If you must keep the data parameter as a pointer, then you could at least use std::swap:

#include <utility>

void FlipYTexture(const unsigned int width, const unsigned int height, uint8_t* data) {
    const unsigned int rowsSwapCount = height / 2;
    const unsigned int maxRowIndex = height - 1;

    for (unsigned int i = 0; i < rowsSwapCount; ++i) {
        for (unsigned int j = 0; j < width; ++j) {
            const unsigned int currentDataIndex = width * i + j;
            const unsigned int swapDataIndex = width * (maxRowIndex - i) + j;
            std::swap(data[currentDataIndex], data[swapDataIndex]);
        }
    }
}

Upvotes: 1

Related Questions