I think I found a good use for alloca() to allocate memory. The purpose of this code is to perform a median filter on an image. I am using openmp so I didn't want to use anything which might cause an exception like new to allocate memory. Also each array would need to be local to the thread which makes things a bit more complicated. The solution I came up with was to allocate the arrays on the stack using alloca() since this should be much faster than new or malloc. I was just wondering what you guys think about it. Also let me know if you have any suggestions to speed up this function since the median filter is kind of slow.
#include "../../Image.hpp"
#include <utility>
#include <cstdlib>
using namespace cpimg;
Image Image::median_filter(int radius) const
{
img_assert(radius > 0, "Invalid radius.");
Image result(w, h);
int n = radius * 2 + 1;
auto median = [this, radius, n](dim_t r, dim_t c)
{
int size = 0;
dim_t istart = r - radius;
dim_t jstart = c - radius;
dim_t iend = r + radius;
dim_t jend = c + radius;
istart = istart < 0 ? 0 : istart;
jstart = jstart < 0 ? 0 : jstart;
iend = iend >= h ? h - 1 : iend;
jend = jend >= w ? w - 1 : jend;
int alloc = (iend - istart) * (jend - jstart) * sizeof(float);
float* reds = (float*)alloca(alloc);
float* greens = (float*)alloca(alloc);
float* blues = (float*)alloca(alloc);
for(dim_t i = istart; i < iend; i++)
{
for(dim_t j = jstart; j < jend; j++)
{
reds[size] = (*this)[i][j].red;
greens[size] = (*this)[i][j].green;
blues[size] = (*this)[i][j].blue;
for(int k = size; k > 0 && reds[k - 1] > reds[k]; k--)
std::swap(reds[k], reds[k - 1]);
for(int k = size; k > 0 && greens[k - 1] > greens[k]; k--)
std::swap(greens[k], greens[k - 1]);
for(int k = size; k > 0 && blues[k - 1] > blues[k]; k--)
std::swap(blues[k], blues[k - 1]);
size++;
}
}
Pixel m;
m.red = size % 2 ? reds[size / 2] : 0.5 * (reds[size / 2] + reds[size / 2 - 1]);
m.green = size % 2 ? greens[size / 2] : 0.5 * (greens[size / 2] + greens[size / 2 - 1]);
m.blue = size % 2 ? blues[size / 2] : 0.5 * (blues[size / 2] + blues[size / 2 - 1]);
return m;
};
#pragma omp parallel for
for(dim_t r = 0; r < h; r++)
{
for(dim_t c = 0; c < w; c++)
{
result[r][c] = median(r, c);
}
}
return result;
}