Procházet zdrojové kódy

image: significantly reduce the blue noise algorithm complexity.

undefined
Sam Hocevar před 10 roky
rodič
revize
7b34d5094b
1 změnil soubory, kde provedl 22 přidání a 15 odebrání
  1. +22
    -15
      src/image/kernel.cpp

+ 22
- 15
src/image/kernel.cpp Zobrazit soubor

@@ -98,22 +98,29 @@ Array2D<float> Image::BlueNoiseKernel(ivec2 size)
} }


/* Helper function to find voids and clusters */ /* Helper function to find voids and clusters */
auto best = [&] (Array2D<float> const &p, float val, float mul) -> ivec2 auto setdot = [&] (Array2D<vec2> &p, ivec2 pos, float val)
{
float const delta = val - p[pos][0];
p[pos][0] = val;

for (int j = 0; j < gsize.y; ++j)
for (int i = 0; i < gsize.x; ++i)
p[(pos.x + i - gsize.x / 2 + size.x) % size.x]
[(pos.y + j - gsize.y / 2 + size.y) % size.y][1]
+= gaussian[i][j] * delta;
};

auto best = [&] (Array2D<vec2> const &p, float val, float mul) -> ivec2
{ {
float maxval = -size.x * size.y; float maxval = -size.x * size.y;
ivec2 coord(0, 0); ivec2 coord(0, 0);
for (int y = 0; y < size.y; ++y) for (int y = 0; y < size.y; ++y)
for (int x = 0; x < size.x; ++x) for (int x = 0; x < size.x; ++x)
{ {
if (p[x][y] != val) if (p[x][y][0] != val)
continue; continue;


float total = 0.0f; float total = p[x][y][1];
for (int j = 0; j < gsize.y; ++j)
for (int i = 0; i < gsize.x; ++i)
total += gaussian[i][j] *
p[(x + i - gsize.x / 2 + size.x) % size.x]
[(y + j - gsize.y / 2 + size.y) % size.y];
if (total * mul > maxval) if (total * mul > maxval)
{ {
maxval = total * mul; maxval = total * mul;
@@ -125,16 +132,16 @@ Array2D<float> Image::BlueNoiseKernel(ivec2 size)
}; };


/* Generate an array with about 10% random dots */ /* Generate an array with about 10% random dots */
Array2D<float> dots(size); Array2D<vec2> dots(size);
int const ndots = (size.x * size.y + 9) / 10; int const ndots = (size.x * size.y + 9) / 10;
memset(dots.Data(), 0, dots.Bytes()); memset(dots.Data(), 0, dots.Bytes());
for (int n = 0; n < ndots; ) for (int n = 0; n < ndots; )
{ {
int x = lol::rand(size.x); int x = lol::rand(size.x);
int y = lol::rand(size.y); int y = lol::rand(size.y);
if (dots[x][y]) if (dots[x][y][0])
continue; continue;
dots[x][y] = 1.0f; setdot(dots, ivec2(x, y), 1.0f);
++n; ++n;
} }


@@ -142,9 +149,9 @@ Array2D<float> Image::BlueNoiseKernel(ivec2 size)
for (;;) for (;;)
{ {
ivec2 bestcluster = best(dots, 1.0f, 1.0f); ivec2 bestcluster = best(dots, 1.0f, 1.0f);
dots[bestcluster] = 0.0f; setdot(dots, bestcluster, 0.0f);
ivec2 bestvoid = best(dots, 0.0f, -1.0f); ivec2 bestvoid = best(dots, 0.0f, -1.0f);
dots[bestvoid] = 1.0f; setdot(dots, bestvoid, 1.0f);
if (bestcluster == bestvoid) if (bestcluster == bestvoid)
break; break;
} }
@@ -154,7 +161,7 @@ Array2D<float> Image::BlueNoiseKernel(ivec2 size)
{ {
ivec2 bestcluster = best(dots, 1.0f, 1.0f); ivec2 bestcluster = best(dots, 1.0f, 1.0f);
ret[bestcluster] = (n + 1.0f) * epsilon; ret[bestcluster] = (n + 1.0f) * epsilon;
dots[bestcluster] = 0.0001f; setdot(dots, bestcluster, 0.0001f);
} }


/* Reorder all 0s and replace them with 0.0001 */ /* Reorder all 0s and replace them with 0.0001 */
@@ -162,7 +169,7 @@ Array2D<float> Image::BlueNoiseKernel(ivec2 size)
{ {
ivec2 bestvoid = best(dots, 0.0f, -1.0f); ivec2 bestvoid = best(dots, 0.0f, -1.0f);
ret[bestvoid] = (n + 1.0f) * epsilon; ret[bestvoid] = (n + 1.0f) * epsilon;
dots[bestvoid] = 0.0001f; setdot(dots, bestvoid, 0.0001f);
} }


return ret; return ret;


||||||
x
 
000:0
Načítá se…
Zrušit
Uložit