add --test-precision option for commandline

parent 8bab9a5f
...@@ -136,6 +136,7 @@ _Coloritto { ...@@ -136,6 +136,7 @@ _Coloritto {
// beware that copy by value works as long as the original // beware that copy by value works as long as the original
// color is not freed - this caveat only applies to the key/value pairs // color is not freed - this caveat only applies to the key/value pairs
// of the copies, not the rest of the struct. // of the copies, not the rest of the struct.
float delta_E;
}; };
struct struct
...@@ -148,6 +149,8 @@ _ColorittoCollection { ...@@ -148,6 +149,8 @@ _ColorittoCollection {
}; };
int use_ui = 0; int use_ui = 0;
int test_precision = 0;
int use_repl = 0;
...@@ -448,7 +451,10 @@ ColorLemma { ...@@ -448,7 +451,10 @@ ColorLemma {
Coloritto *color; Coloritto *color;
/* keep many/most key=vals from parsing, but normalize spectrum */ /* keeps many/most key=vals from parsing, but spectrum is normalized
to internal representation - which should be at 5nm or 10nm and as wide
as or wider than perceptual to yield accurate tristimulus values out.
*/
} ColorLemma; } ColorLemma;
...@@ -890,6 +896,18 @@ void xyz_to_xy (float x, float y, float z, ...@@ -890,6 +896,18 @@ void xyz_to_xy (float x, float y, float z,
} }
} }
static int compare_delta_e (const void *a, const void *b, void *userdata)
{
const Coloritto *la = a;
const Coloritto *lb = b;
if (la->delta_E < lb->delta_E)
return -1;
else if (la->delta_E > lb->delta_E)
return 1;
return 0;
}
#ifdef HAVE_MRG #ifdef HAVE_MRG
static int compare_depths (const void *a, const void *b, void *userdata) static int compare_depths (const void *a, const void *b, void *userdata)
{ {
...@@ -1702,6 +1720,90 @@ coloritto_set_display_icc (const char *icc_data, int icc_length) ...@@ -1702,6 +1720,90 @@ coloritto_set_display_icc (const char *icc_data, int icc_length)
ColorittoDef print_spaces = 0; ColorittoDef print_spaces = 0;
void
analyze_precision (ColorittoCollection *cc)
{
int count = coloritto_collection_count (cc);
int total = 0;
double sum_delta_E = 0.0;
double min_delta_E = 100.0;
double max_delta_E = 0.0;
int max_no = 0;
for (int i = 1; i <= count; i++)
{
Coloritto *color = coloritto_collection_get_no (cc, i);
const char *name = coloritto_get_name (color);
if (name[0] == 'H' &&
name[4] == '_' &&
name[5] == 'L')
{
float exact_LCH[3];
float exact_Lab[3];
//double delta_E;
exact_LCH[2] = atoi (&name[1]);
exact_LCH[0] = atoi (strchr(name, 'L')+1);
exact_LCH[1] = atoi (strchr(name, 'C')+1);
coloritto_ensure (color, COLORITTO_LAB);
babl_process (babl_fish (babl_format ("CIE LCH(ab) float"),
babl_format ("CIE Lab float")),
exact_LCH, exact_Lab, 1);
//fprintf (stderr, "%s\n", name);
//fprintf (stderr, "%f %f %f\n", exact_LCH[2], exact_LCH[0], exact_LCH[1]);
// fprintf (stderr, "%f %f %f\n", exact_LCH[2], exact_LCH[0], exact_LCH[1]);
#define sq(a) ((a)*(a))
color->delta_E = sqrt ( sq(color->lab[0]-exact_Lab[0]) +
sq(color->lab[1]-exact_Lab[1]) +
sq(color->lab[2]-exact_Lab[2]));
#undef sq
total ++;
sum_delta_E += color->delta_E;
if (color->delta_E < min_delta_E)
min_delta_E = color->delta_E;
if (color->delta_E > max_delta_E)
{
max_delta_E = color->delta_E;
max_no = i;
}
//fprintf (stderr, "%f\n", delta_E);
}
}
fprintf (stderr, "%i-%i %inm ", LUZ_SPECTRUM_START, LUZ_SPECTRUM_END, LUZ_SPECTRUM_GAP);
//fprintf (stderr, "%i colors\n", total);
fprintf (stderr, "ΔE* avg:%f", sum_delta_E / total);
fprintf (stderr, " min: %f", min_delta_E);
if (max_no){
Coloritto *color = coloritto_collection_get_no (cc, max_no);
float triplet[3];
fprintf (stderr, " max: %f", max_delta_E);
luz_list_sort (&cc->list, compare_delta_e, NULL);
fprintf (stderr, "\n");
int no = 0;
for (LuzList *l = cc->list; l && no < 10; l = l->next, no++)
{
color = l->data;
coloritto_get (color, COLORITTO_LCH, triplet);
fprintf (stderr, "%s ΔE* %f LCH: %2.4f %2.4f %2.4f\n",
coloritto_get_name (color), color->delta_E,
triplet[2], triplet[0], triplet[1]);
}
}
}
char * char *
coloritto_collection_to_text (ColorittoCollection *cc) coloritto_collection_to_text (ColorittoCollection *cc)
{ {
...@@ -1765,7 +1867,7 @@ if (1){ ...@@ -1765,7 +1867,7 @@ if (1){
if colcond(COLORITTO_SPECTRUM_ON_WHITE) if colcond(COLORITTO_SPECTRUM_ON_WHITE)
{ {
coloritto_get (color, COLORITTO_LCH, triplet); coloritto_get (color, COLORITTO_LCH, triplet);
luz_string_append_printf (str, "spectr HLC:%2.0f %2.0f %2.0f\n", triplet[2], triplet[0], triplet[1]); luz_string_append_printf (str, "spectr HLC:%2.4f %2.4f %2.4f\n", triplet[2], triplet[0], triplet[1]);
} }
} }
...@@ -1773,7 +1875,6 @@ if (1){ ...@@ -1773,7 +1875,6 @@ if (1){
return luz_string_dissolve (str); return luz_string_dissolve (str);
} }
int use_repl = 0;
static void parse_args (int argc, char **argv) static void parse_args (int argc, char **argv)
...@@ -1783,6 +1884,7 @@ static void parse_args (int argc, char **argv) ...@@ -1783,6 +1884,7 @@ static void parse_args (int argc, char **argv)
if (!strcmp (argv[i], "--ui")) use_ui = 1; if (!strcmp (argv[i], "--ui")) use_ui = 1;
else if (!strcmp (argv[i], "-ui")) use_ui = 1; else if (!strcmp (argv[i], "-ui")) use_ui = 1;
else if (!strcmp (argv[i], "-repl")) use_repl = 1; else if (!strcmp (argv[i], "-repl")) use_repl = 1;
else if (!strcmp (argv[i], "--test-precision")) test_precision = 1;
else if (!strcmp (argv[i], "-c")){ else if (!strcmp (argv[i], "-c")){
if (!argv[i+1] || argv[i+1][0]=='-') if (!argv[i+1] || argv[i+1][0]=='-')
{ {
...@@ -1805,7 +1907,7 @@ static void parse_args (int argc, char **argv) ...@@ -1805,7 +1907,7 @@ static void parse_args (int argc, char **argv)
} }
else if (argv[i][0]=='-') else if (argv[i][0]=='-')
{ {
fprintf (stderr, "unknown option '%s'\n", argv[i]); fprintf (stderr, "unknown option '%s' recognized -c <srg|xyz|xyZ|lab|lcg|set> --ui and --test-precision -\n", argv[i]);
exit (-1); exit (-1);
} }
else else
...@@ -1862,6 +1964,15 @@ main (int argc, char **argv) ...@@ -1862,6 +1964,15 @@ main (int argc, char **argv)
{ {
argvs_eval ("argvs"); argvs_eval ("argvs");
} }
else if (test_precision)
{
LuzList *l;
for (l = palettes; l; l = l->next)
{
ColorittoCollection *cc = l->data;
analyze_precision (cc);
}
}
else else
{ {
LuzList *l; LuzList *l;
......
...@@ -723,7 +723,7 @@ luz_parse_spectrum (Luz *luz, char *spectrum) ...@@ -723,7 +723,7 @@ luz_parse_spectrum (Luz *luz, char *spectrum)
if (band > 3) if (band > 3)
{ {
float nm_start = num_array[0]; float nm_start = num_array[0];
float nm_gap = num_array[1]; float nm_gap = num_array[1];
float nm_scale = num_array[2]; float nm_scale = num_array[2];
int bands = band - 3; int bands = band - 3;
...@@ -734,69 +734,39 @@ luz_parse_spectrum (Luz *luz, char *spectrum) ...@@ -734,69 +734,39 @@ luz_parse_spectrum (Luz *luz, char *spectrum)
#define STRATEGY_LINEAR 1 #define STRATEGY_LINEAR 1
#define STRATEGY_TENT 2 #define STRATEGY_TENT 2
int strategy = STRATEGY_TENT; int strategy = STRATEGY_NEAREST;
// 5nm:
// 1.5 TENT : 49.89287 97.56120 155.17508
// 1.0 TENT : 49.92163 98.19018 155.12943
// 0.5 TENT : 49.94464 98.69678 155.09358
// 0.3 TENT : 49.95459 98.91650 155.07816
// 0.2 TENT : 49.95920 99.01872 155.07101
// LINEAR : 49.96898 99.23534 155.05602
// NEAREST : 50.83529 99.49268 152.33022
// 10nm:
// 1.5 TENT : 49.73328 94.14050 155.44125
// 1.0 TENT : 50.00582 100.00207 154.99348
// 0.5 TENT : 49.93114 98.38665 155.11391
// 0.3 TENT : 49.96164 99.04399 155.06436
// 0.2 TENT : 49.97580 99.35043 155.04147
// LINEAR : 49.86871 96.60445 155.24734
// NEAREST : 50.00582 100.00207 154.99348
// 0.2 tent
// 5nm 49.96898 99.23535 155.05602
// 10nm 49.99241 99.77881 155.02098
// 0.1 tent
// 5nm 49.96898 99.23535 155.05602
// 10nm 50.00036 99.89520 155.00360
// 0.08 tent
// 5nm 49.96898 99.23535 155.05602
// 10nm 50.00309 99.94878 154.99847
// 0.05 tent
// 5nm 49.96898 99.23535 155.05602
// 10nm 50.00309 99.94878 154.99847
if (fabs (nm_gap - LUZ_SPECTRUM_GAP) < 0.1) if (fabs (nm_gap - LUZ_SPECTRUM_GAP) < 0.1)
{ {
strategy = STRATEGY_NEAREST; strategy = STRATEGY_NEAREST;
} }
#if 1
else if (nm_gap < LUZ_SPECTRUM_GAP) else if (nm_gap < LUZ_SPECTRUM_GAP)
{ {
strategy = STRATEGY_LINEAR; strategy = STRATEGY_TENT; // XXX this is the case we have tent for,
// but nearest give better avg delta E
//strategy = STRATEGY_NEAREST;
} }
else if (nm_gap > LUZ_SPECTRUM_GAP) else if (nm_gap > LUZ_SPECTRUM_GAP)
{ {
strategy = STRATEGY_TENT; strategy = STRATEGY_LINEAR;
} }
#endif
switch (strategy) switch (strategy)
{ {
case STRATEGY_TENT: case STRATEGY_TENT:
for (i = 0; i < LUZ_SPECTRUM_BANDS; i++) for (i = 0; i < LUZ_SPECTRUM_BANDS; i++)
{ {
double tent_size = 0.1;
double tent_fragment = tent_size / 32;
double sum = 0.0; double sum = 0.0;
double sum_parts = 0.0; double sum_parts = 0.0;
for (double ts = -0.08; ts < 0.08; ts+=0.001) for (double ts = -tent_size; ts < tent_size; ts+= tent_fragment)
{ {
double part = (0.08-fabs(ts)) + 0.001; double part = (tent_size-fabs(ts)) + 0.001;
double valA = 0.0; double valA = 0.0;
double valB = 0.0; double valB = 0.0;
double val; double val;
...@@ -830,13 +800,20 @@ luz_parse_spectrum (Luz *luz, char *spectrum) ...@@ -830,13 +800,20 @@ luz_parse_spectrum (Luz *luz, char *spectrum)
nm = LUZ_SPECTRUM_START + LUZ_SPECTRUM_GAP * i; nm = LUZ_SPECTRUM_START + LUZ_SPECTRUM_GAP * i;
ip = (nm - nm_start) / nm_gap; ip = (nm - nm_start) / nm_gap;
if (ip >= 0 && ip < bands)
valA = num_array[ (int)(3 + floor ( ip ))];
if (ip >= 0 && ip < bands - 1) if (ip >= 0 && ip < bands - 1)
{
valA = num_array[ (int)(3 + floor ( ip ))];
valB = num_array[ (int)(3 + floor ( ip + 1 ))]; valB = num_array[ (int)(3 + floor ( ip + 1 ))];
d = ip - floor(ip); d = ip - floor(ip);
val = valA * (1.0-d) + valB * d;
val = valA * (1.0-d) + valB * d; }
else
{
if (ip < 0)
val = num_array[3];
else
val = num_array[bands-1];
}
s.bands[i] = val * nm_scale; s.bands[i] = val * nm_scale;
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>. * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
* *
* Copyright 2014,2016,2018 Øyind Kolås <pippin@gimp.org> * Copyright 2014,2016,2018,2019 Øyvind Kolås <pippin@gimp.org>
*/ */
/* ideas: /* ideas:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment