[gegl] ink-simulator: do inerpolation on LUT
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] ink-simulator: do inerpolation on LUT
- Date: Fri, 21 Mar 2014 03:23:23 +0000 (UTC)
commit ab70f7686a6f5cc18fa172497ea2d01b256bb038
Author: Øyvind Kolås <pippin gimp org>
Date: Fri Mar 21 04:21:25 2014 +0100
ink-simulator: do inerpolation on LUT
Do stochastic simulation for a 64x64x64 RGB cube on demand, then linear
interpolation of values within that cube; getting rid of noise.
operations/workshop/ink-simulator.c | 217 ++++++++++++++++++++++++-----------
1 files changed, 150 insertions(+), 67 deletions(-)
---
diff --git a/operations/workshop/ink-simulator.c b/operations/workshop/ink-simulator.c
index bf3d81b..5a5abd5 100644
--- a/operations/workshop/ink-simulator.c
+++ b/operations/workshop/ink-simulator.c
@@ -30,9 +30,7 @@
"ink3=yellow\n"\
"ink4=black\n"\
"\n"\
-"inklimit=3.0\n"\
-"iterations=32\n"\
-"bail=0.0004\n"
+"inklimit=3.0\n"
gegl_chant_register_enum (ink_sim_mode)
enum_value (GEGL_INK_SIMULATOR_PROOF, "proof")
@@ -54,6 +52,8 @@ gegl_chant_enum (mode, _("mode"), GeglInkSimMode, ink_sim_mode, GEGL_INK_SIMULAT
#include <math.h>
#define SPECTRUM_BANDS 20
+#define LUT_DIM 64
+#define LUT_ITERATIONS 256
typedef struct _Config Config;
typedef struct _Ink Ink;
@@ -77,7 +77,6 @@ struct _Ink {
/* per ink inklimit as well? */
};
-#define LUT_DIM 100
typedef struct _InkMix InkMix;
struct _InkMix {
@@ -90,22 +89,34 @@ struct _Config {
Spectrum substrate;
Ink ink_def[4];
int inks;
- int iterations;
- float bail;
float ink_limit;
InkMix lut[LUT_DIM*LUT_DIM*LUT_DIM];
};
+static inline int lut_indice (float val, float *delta)
+{
+ int v = floor (val * (LUT_DIM - 1));
+ if (v < 0) v = 0; if (v >= (LUT_DIM-1)) v = LUT_DIM - 2;
+ if (delta)
+ {
+ *delta = ((val * (LUT_DIM - 1)) - v);
+ g_assert (*delta >= 0.0);
+ g_assert (*delta <= 1.0);
+ }
+ return v;
+}
+
+static inline int lut_index (int ri, int gi, int bi)
+{
+ return ri * LUT_DIM * LUT_DIM + gi * LUT_DIM + bi;
+}
+
static inline int rgb_to_lut_index (float red, float green, float blue)
{
- int r = floor (red * LUT_DIM);
- int g = floor (green * LUT_DIM);
- int b = floor (blue * LUT_DIM);
- if (r < 0) r = 0; if (r >= LUT_DIM) r = LUT_DIM - 1;
- if (g < 0) g = 0; if (g >= LUT_DIM) g = LUT_DIM - 1;
- if (b < 0) b = 0; if (b >= LUT_DIM) b = LUT_DIM - 1;
- return r * LUT_DIM * LUT_DIM + g * LUT_DIM + b;
+ return lut_index (lut_indice (red, NULL),
+ lut_indice (green, NULL),
+ lut_indice (blue, NULL));
}
static Config config;
@@ -130,7 +141,7 @@ static Spectrum STANDARD_OBSERVER_S = {{
//#define TRANSMITTANCE_MAGENTA
{{1.0,0.7,0.9,0.85,0.8,0.7,0.64,0.54,0.5,0.38,0.6,0.8,0.9,1.0,1.0,1.0,1.0,0.9,0.9,0.9}}
#define TRANSMITTANCE_RED {{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0}}
-#define TRANSMITTANCE_GREEN {{0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}}
+#define TRANSMITTANCE_GREEN {{0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0}}
#define TRANSMITTANCE_BLUE {{0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
#define TRANSMITTANCE_BLACK {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
#define TRANSMITTANCE_GRAY
{{0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5}}
@@ -193,7 +204,7 @@ static inline void add_ink (Spectrum *s, const Spectrum *illuminant, const Spect
}
}
-static inline float spectrum_integrate (const Spectrum *s, const Spectrum *is, float scale)
+static float spectrum_integrate (const Spectrum *s, const Spectrum *is, float scale)
{
float result = 0.0;
int i;
@@ -241,13 +252,13 @@ static inline Spectrum inks_to_spectrum (Config *config, float *ink_levels)
return spec;
}
-static inline void inks_to_rgb (Config *config, float *ink_levels, float *rgba)
+static inline void spectral_proof (Config *config, float *ink_levels, float *rgba)
{
Spectrum spec = inks_to_spectrum (config, ink_levels);
spectrum_to_rgba (&spec, rgba);
}
-static inline double colordiff_squared (float *cola, float *colb)
+static inline double colordiff (float *cola, float *colb)
{
return
(cola[0]-colb[0])*(cola[0]-colb[0])+
@@ -255,30 +266,18 @@ static inline double colordiff_squared (float *cola, float *colb)
(cola[2]-colb[2])*(cola[2]-colb[2]);
}
-static inline void rgb_to_inks (Config *config, float *rgb, float *ink_levels)
+static inline void rgb_to_inks_stochastic (Config *config,
+ float *rgb,
+ float *ink_levels,
+ int iterations,
+ float rrange)
{
float best[8] = {0.5,0.5,0.5,0.5,0.5};
float bestdiff = 3;
int i;
- int lutidx = rgb_to_lut_index (rgb[0], rgb[1], rgb[2]);
- float rrange;
- int iterations;
-
-again: /* if on first run we seeded LUT */
-
- if (config->lut[lutidx].defined)
- {
- for (i = 0; i < 4; i++)
- best[i] = config->lut[lutidx].level[i];
- rrange = 0.03;
- iterations = config->iterations;
- }
- else
- {
- rrange = 0.6;
- iterations = 128;
- }
+ for (i = 0; i < config->inks; i++)
+ best[i] = ink_levels[i];
for (i = 0; i < iterations; i++)
{
@@ -288,7 +287,7 @@ again: /* if on first run we seeded LUT */
float diff;
float inksum = 0;
- do{
+ do {
inksum = 0.0;
for (j = 0; j < config->inks; j++)
{
@@ -299,35 +298,109 @@ again: /* if on first run we seeded LUT */
}
} while (inksum > config->ink_limit);
- inks_to_rgb (config, attempt, softrgb);
- diff = colordiff_squared (rgb, softrgb) + (inksum / 100.0) * (inksum / 100.0);
+ spectral_proof (config, attempt, softrgb);
+ diff = colordiff (rgb, softrgb) + (inksum / 100.0) * (inksum / 100.0);
if (diff < bestdiff)
{
bestdiff = diff;
for (j = 0; j < config->inks; j++)
best[j] = attempt[j];
- if (diff < config->bail) /* bail early */
+ if (diff < 0.0001) /* close enough */
i = 10000;
}
}
- if (config->lut[lutidx].defined == 0)
+ for (i = 0; i < config->inks; i++)
+ ink_levels[i] = best[i];
+}
+
+static inline float * ensure_lut (Config *config, int ri, int gi, int bi)
+{
+ int l_index;
+ int i;
+
+ if (ri >= LUT_DIM ||
+ gi >= LUT_DIM ||
+ bi >= LUT_DIM)
{
- config->lut[lutidx].defined = 1;
- for (i = 0; i < 4; i++)
- config->lut[lutidx].level[i] = best[i];
- goto again;
+ //g_warning ("oops");
+ return &config->lut[0].level[0];
}
- else
+
+ l_index = lut_index (ri, gi, bi);
+ if (!config->lut[l_index].defined)
{
- //for (i = 0; i < 4; i++)
- // config->lut[lutidx].level[i] = best[i];
+ float trgb[3] = {(float)ri / LUT_DIM, (float)gi / LUT_DIM, (float)bi / LUT_DIM };
+ for (i = 0; i < config->inks; i++)
+ {
+ config->lut[l_index].level[i] = 0.5;
+ }
+ rgb_to_inks_stochastic (config, trgb, &config->lut[l_index].level[0], LUT_ITERATIONS, 0.5);
+ config->lut[l_index].defined = 1;
}
+ return &config->lut[l_index].level[0];
+}
- for (i = 0; i < config->inks; i++)
- ink_levels[i] = best[i];
+static inline void lerp_inks (int inks, float *ink_res, const float *inka, const float *inkb, float delta)
+{
+ int i;
+ for (i = 0; i < inks; i++)
+ {
+ ink_res[i] = inka[i] * (1.0 - delta) + inkb[i] * delta;
+ }
+}
+
+static inline void rgb_to_inks (Config *config, float *rgb, float *ink_levels)
+{
+ float rdelta, gdelta, bdelta;
+ int ri = lut_indice (rgb[0], &rdelta);
+ int gi = lut_indice (rgb[1], &gdelta);
+ int bi = lut_indice (rgb[2], &bdelta);
+ float *ink_corner[8];
+ float temp1[4];
+ float temp2[4];
+ float temp3[4];
+ float temp4[4];
+
+#if 0
+ numbering of corners, and positions of R,G,B axes
+
+ 6
+ /\
+ / \
+ 7/ d \5
+ |\ /|
+ | \4/ |
+ 3\B G|2 |
+ \ | /1
+ \|/R
+ 0
+
+#endif
+
+ ink_corner[0] = ensure_lut (config, ri + 0, gi + 0, bi + 0);
+ ink_corner[1] = ensure_lut (config, ri + 1, gi + 0, bi + 0);
+ ink_corner[2] = ensure_lut (config, ri + 1, gi + 0, bi + 1);
+ ink_corner[3] = ensure_lut (config, ri + 0, gi + 0, bi + 1);
+
+ ink_corner[4] = ensure_lut (config, ri + 0, gi + 1, bi + 0);
+ ink_corner[5] = ensure_lut (config, ri + 1, gi + 1, bi + 0);
+ ink_corner[6] = ensure_lut (config, ri + 1, gi + 1, bi + 1);
+ ink_corner[7] = ensure_lut (config, ri + 0, gi + 1, bi + 1);
+
+ lerp_inks (config->inks, temp1, ink_corner[0], ink_corner[1], rdelta);
+ lerp_inks (config->inks, temp2, ink_corner[3], ink_corner[2], rdelta);
+ lerp_inks (config->inks, temp3, ink_corner[4], ink_corner[5], rdelta);
+ lerp_inks (config->inks, temp4, ink_corner[7], ink_corner[6], rdelta);
+ lerp_inks (config->inks, temp1, temp1, temp3, gdelta);
+ lerp_inks (config->inks, temp2, temp2, temp4, gdelta);
+ lerp_inks (config->inks, ink_levels, temp1, temp2, bdelta);
}
+
+
+
+
static gboolean
process (GeglOperation *op,
void *in_buf,
@@ -343,12 +416,31 @@ process (GeglOperation *op,
switch (o->mode)
{
case GEGL_INK_SIMULATOR_PROOF:
- while (samples--)
- {
- inks_to_rgb (&config, in, out);
- in += 4;
- out += 4;
- }
+ {
+ gint x = roi->x;
+ gint y = roi->y;
+
+ gint actual_inks = config.inks;
+
+ while (samples--)
+ {
+ int foo = (x / 16);
+ config.inks = MIN (foo, actual_inks);
+ spectral_proof (&config, in, out);
+ in += 4;
+ out += 4;
+
+ x++;
+ if (x>=roi->x + roi->width)
+ {
+ x=roi->x;
+ y++;
+ }
+
+ }
+
+ config.inks = actual_inks;
+ }
break;
case GEGL_INK_SIMULATOR_SEPARATE:
while (samples--)
@@ -375,7 +467,7 @@ process (GeglOperation *op,
gint actual_inks = config.inks;
rgb_to_inks (&config, in, temp);
config.inks = MIN(foo, actual_inks);
- inks_to_rgb (&config, temp, out);
+ spectral_proof (&config, temp, out);
config.inks = actual_inks;
in += 4;
@@ -477,14 +569,6 @@ static void parse_config_line (GeglOperation *operation,
if (config.ink_limit < 0.2)
config.ink_limit = 0.2;
}
- else if (g_str_has_prefix (line, "bail"))
- {
- config.bail = strchr(line, '=') ? g_strtod (strchr (line, '=')+1, NULL) : 3.0;
- }
- else if (g_str_has_prefix (line, "iterations"))
- {
- config.iterations = strchr(line, '=') ? g_strtod (strchr (line, '=')+1, NULL) : 3.0;
- }
else
for (i = 0; i < 4; i++)
{
@@ -511,10 +595,9 @@ static void parse_config (GeglOperation *operation)
return;
memset (&config, 0, sizeof (config));
+ g_warning ("blanking");
for (i = 0; i < 4; i++) config.ink_def[i].scale = 1.0;
config.ink_limit = 4.0;
- config.iterations = 32;
- config.bail = 0.00001;
str = g_string_new ("");
while (*p)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]