Reputation: 1491
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
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
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