[gegl] Update, fix and improve negative-darkroom operation * Rework emulsion dye model to (hopefully) prope



commit 3d5e9bc8be061c1f52ffe375f06f8e3e15d22f56
Author: JonnyRobbie <marcodv seznam cz>
Date:   Fri May 14 09:55:24 2021 +0200

    Update, fix and improve negative-darkroom operation
    * Rework emulsion dye model to (hopefully) properly simulate colors
      (this also fixes issue with multigrade paper)
    * Rework color filter model with UI improvements.
    * Rework sensitivity matrix calculation to (hopefully) properly
      represent paper properties.
    * Add more black and white papers.

 operations/common/negative-darkroom.c              | 205 ++++++++++++---------
 .../negative-darkroom-curve-enum.c                 |   6 +
 .../negative-darkroom-curve-enum.h                 | 151 +++++++++++++--
 3 files changed, 253 insertions(+), 109 deletions(-)
---
diff --git a/operations/common/negative-darkroom.c b/operations/common/negative-darkroom.c
index dde1c1a56..96abd3f07 100644
--- a/operations/common/negative-darkroom.c
+++ b/operations/common/negative-darkroom.c
@@ -1,5 +1,5 @@
 /* This file is an image processing operation for GEGL
-* foo
+* 
 * GEGL is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
@@ -12,15 +12,12 @@
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
-*
-* Copyright 2015 Red Hat, Inc.
 */
 
 #include "config.h"
 #include <glib/gi18n-lib.h>
 #include <math.h>
 #include <stdio.h>
-
 #ifdef GEGL_PROPERTIES
 
 #include "negative-darkroom/negative-darkroom-curve-enum.c"
@@ -29,50 +26,55 @@ property_enum (curve, _("Characteristic curve"),
                NegCurve, neg_curve, 0)
        description(_("Hardcoded characteristic curve and color data"))
 
-property_double (exposure, _("Exposure"), -9.0)
+property_double (exposure, _("Exposure"), 0.0)
        description(_("Base enlargement exposure"))
-       value_range (-20, 10)
-       ui_range (-15, 0)
+       value_range (-10, 10)
+       ui_range (-5, 5)
 
-property_double (expC, _("Filter cyan"), 0.0)
-       description(_("Cyan exposure compensation for the negative image"))
-       value_range (-3, 3)
+property_double (expC, _("Cyan filter"), 60)
+       description(_("Cyan filter compensation for the negative image"))
+       value_range (0, 300)
+       ui_range (0, 180)
 
-property_double (expM, _("Filter magenta"), 0.0)
-       description(_("Magenta exposure compensation for the negative image"))
-       value_range (-3, 3)
+property_double (expM, _("Magenta filter"), 60)
+       description(_("Magenta filter compensation for the negative image"))
+       value_range (0, 300)
+       ui_range (0, 180)
 
-property_double (expY, _("Filter yellow"), 0.0)
-       description(_("Yellow exposure compensation for the negative image"))
-       value_range (-3, 3)
+property_double (expY, _("Yellow filter"), 60)
+       description(_("Yellow filter compensation for the negative image"))
+       value_range (0, 300)
+       ui_range (0, 180)
 
 property_boolean (clip, _("Clip base + fog"), TRUE)
        description (_("Clip base + fog to have a pure white output value"))
 
 property_double (boost, _("Density boost"), 1.0)
        description(_("Boost paper density to take advantage of increased dynamic range of a monitor compared 
to a photographic paper"))
-       value_range (1, 3)
+       value_range (0.25, 4)
+       ui_range (1, 2)
 
 property_double (dodge, _("Dodge/burn multiplier"), 1.0)
        description(_("The f-stop of dodge/burn for pure white/black auxillary input"))
        value_range (-4.0, 4.0)
+       ui_range (0, 2)
 
 property_boolean (preflash, _("Enable preflashing"), FALSE)
        description (_("Show preflash controls"))
 
-property_double (flashC, _("Cyan preflash"), 0)
-       description(_("Preflash the negative with cyan light to reduce contrast of the print"))
-       value_range (0, 1)
+property_double (flashC, _("Red preflash"), 0)
+       description(_("Preflash the negative with red light to reduce contrast of the print"))
+       value_range (0, 0.05)
        ui_meta("visible", "preflash")
 
-property_double (flashM, _("Magenta preflash"), 0)
-       description(_("Preflash the negative with magenta light to reduce contrast of the print"))
-       value_range (0, 1)
+property_double (flashM, _("Green preflash"), 0)
+       description(_("Preflash the negative with green light to reduce contrast of the print"))
+       value_range (0, 0.05)
        ui_meta("visible", "preflash")
 
-property_double (flashY, _("Yellow preflash"), 0)
-       description(_("Preflash the negative with yellow light to reduce contrast of the print"))
-       value_range (0, 1)
+property_double (flashY, _("Blue preflash"), 0)
+       description(_("Preflash the negative with blue light to reduce contrast of the print"))
+       value_range (0, 0.05)
        ui_meta("visible", "preflash")
 
 #else
@@ -81,6 +83,8 @@ property_double (flashY, _("Yellow preflash"), 0)
 #define GEGL_OP_NAME     negative_darkroom
 #define GEGL_OP_C_SOURCE negative-darkroom.c
 
+#define EPSILON 0.00001
+
 #include "gegl-op.h"
 
 // Color space
@@ -155,6 +159,12 @@ array_min (gfloat * x, guint n)
        return(min);
 }
 
+static inline gfloat
+clampE (gfloat x)
+{
+       return(x <= EPSILON ? EPSILON : x);
+}
+
 static gboolean
 process (GeglOperation       *operation,
         void                *in_buf,
@@ -182,61 +192,82 @@ process (GeglOperation       *operation,
        gfloat g = 0;
        gfloat b = 0;
 
+       gfloat x = 0;
+       gfloat y = 0;
+       gfloat z = 0;
+
+       gfloat exp = pow(2, o->exposure);
+
        // Calculate base+fog
        if (o->clip)
        {
-               Dfogc = array_min(curves[o->curve].ry, curves[o->curve].rn) * o->boost;
-               Dfogm = array_min(curves[o->curve].gy, curves[o->curve].gn) * o->boost;
-               Dfogy = array_min(curves[o->curve].by, curves[o->curve].bn) * o->boost;
+               Dfogc = array_min(curves[o->curve].ry,
+                                 curves[o->curve].rn) * o->boost;
+               Dfogm = array_min(curves[o->curve].gy,
+                                 curves[o->curve].gn) * o->boost;
+               Dfogy = array_min(curves[o->curve].by,
+                                 curves[o->curve].bn) * o->boost;
+       }
+
+       if (!aux)
+       {
+               rcomp = pow(2, (-o->expC) / 30);
+               gcomp = pow(2, (-o->expM) / 30);
+               bcomp = pow(2, (-o->expY) / 30);
        }
 
        for (glong i = 0; i < n_pixels; i++)
        {
-               /*printf("---\n");*/
                /*printf("Input XYZ intensity %f %f %f\n", in[0], in[1], in[2]);*/
 
                // Calculate exposure compensation from global+filter+dodge
-               if (!aux)
-               {
-                       rcomp = o->exposure + o->expC;
-                       gcomp = o->exposure + o->expM;
-                       bcomp = o->exposure + o->expY;
-               }
-               else
+               if (aux)
                {
-                       rcomp = o->exposure + o->expC + 2*o->dodge*(aux[0]-0.5);
-                       gcomp = o->exposure + o->expM + 2*o->dodge*(aux[1]-0.5);
-                       bcomp = o->exposure + o->expY + 2*o->dodge*(aux[2]-0.5);
+                       rcomp = pow(2, ((-o->expC) / 30) -
+                                       (2 * o->dodge * (aux[0] - 0.5)));
+                       gcomp = pow(2, ((-o->expM) / 30) -
+                                       (2 * o->dodge * (aux[1] - 0.5)));
+                       bcomp = pow(2, ((-o->expY) / 30) -
+                                       (2 * o->dodge * (aux[2] - 0.5)));
                        aux  += 3;
                }
 
-               /*printf("===\nRGB compensation %f %f %f\n", rcomp, gcomp, bcomp);*/
-
-               // Calculate RGB from XYZ using paper sensitivity
-               r = in[0] * curves[o->curve].rsens.X +
-                   in[1] * curves[o->curve].gsens.X +
-                   in[2] * curves[o->curve].bsens.X;
-               g = in[0] * curves[o->curve].rsens.Y +
-                   in[1] * curves[o->curve].gsens.Y +
-                   in[2] * curves[o->curve].bsens.Y;
-               b = in[0] * curves[o->curve].rsens.Z +
-                   in[1] * curves[o->curve].gsens.Z +
-                   in[2] * curves[o->curve].bsens.Z;
-
-               /*printf("Linear RGB intensity %f %f %f\n", r, g, b);*/
-
-               // Apply the preflash
-               r = r + o->flashC;
-               g = g + o->flashM;
-               b = b + o->flashY;
-
-               /*printf("Linear RGB intensity after preflash %f %f %f\n", r, g, b);*/
-
-               // Logarithmize the input and apply compensation
-               r = log(r / pow(2, rcomp)) / log(10);
-               g = log(g / pow(2, gcomp)) / log(10);
-               b = log(b / pow(2, bcomp)) / log(10);
-
+               // Convert to CIERGB primaries for color filter balance
+               x =    0.41847*in[0] -   0.15866*in[1] - 0.082835*in[2];
+               y =  -0.091169*in[0] +   0.25243*in[1] + 0.015708*in[2];
+               z = 0.00092090*in[0] - 0.0025498*in[1] +  0.17860*in[2];
+
+               // Apply preflash
+               x = x + o->flashC;
+               y = y + o->flashM;
+               z = z + o->flashY;
+
+               // Apply color filters and exposure
+               x = x * rcomp * exp;
+               y = y * gcomp * exp;
+               z = z * bcomp * exp;
+
+               // Simulate emulsion spectral sensitivity with
+               // sensitivity matrix
+               r = clampE(x * curves[o->curve].rsens.X +
+                          y * curves[o->curve].rsens.Y +
+                          z * curves[o->curve].rsens.Z);
+               g = clampE(x * curves[o->curve].gsens.X +
+                          y * curves[o->curve].gsens.Y +
+                          z * curves[o->curve].gsens.Z);
+               b = clampE(x * curves[o->curve].bsens.X +
+                          y * curves[o->curve].bsens.Y +
+                          z * curves[o->curve].bsens.Z);
+
+               // Scale the emulsion response
+               r *= 5000;
+               g *= 5000;
+               b *= 5000;
+
+               // Logarithmize the input
+               r = log10(r);
+               g = log10(g);
+               b = log10(b);
                /*printf("Logarithmic RGB intensity %f %f %f\n", r, g, b);*/
 
                // Apply the DH curve
@@ -252,6 +283,7 @@ process (GeglOperation       *operation,
                               curves[o->curve].by,
                               curves[o->curve].bn,
                               b);
+               /*printf("Raw RGB density %f %f %f\n", r, g, b);*/
 
                // Apply density boost
                r = r * o->boost;
@@ -262,27 +294,19 @@ process (GeglOperation       *operation,
                r -= Dfogc;
                g -= Dfogm;
                b -= Dfogy;
-
-               /*printf("RGB density %f %f %f\n", r, g, b);*/
-
-               // Exponentiate to get the linear representation in tramsmittance back
-               r = 1-1/pow(10, r);
-               g = 1-1/pow(10, g);
-               b = 1-1/pow(10, b);
-
-               /*printf("RGB absolute transparency %f %f %f\n", r, g, b);*/
-
-               // Calculate and return XYZ
-               out[0] = 1 - (r * curves[o->curve].cdens.X) -
-                            (g * curves[o->curve].mdens.X) -
-                            (b * curves[o->curve].ydens.X);
-               out[1] = 1 - (r * curves[o->curve].cdens.Y) -
-                            (g * curves[o->curve].mdens.Y) -
-                            (b * curves[o->curve].ydens.Y);
-               out[2] = 1 - (r * curves[o->curve].cdens.Z) -
-                            (g * curves[o->curve].mdens.Z) -
-                            (b * curves[o->curve].ydens.Z);
-
+               /*printf("Adjusted RGB density %f %f %f\n", r, g, b);*/
+
+               // Simulate dye density with exponentiation to get
+               // the CIEXYZ tramsmittance back
+               out[0] = (1 / pow(10, r * curves[o->curve].cdens.X)) *
+                        (1 / pow(10, g * curves[o->curve].mdens.X)) *
+                        (1 / pow(10, b * curves[o->curve].ydens.X));
+               out[1] = (1 / pow(10, r * curves[o->curve].cdens.Y)) *
+                        (1 / pow(10, g * curves[o->curve].mdens.Y)) *
+                        (1 / pow(10, b * curves[o->curve].ydens.Y));
+               out[2] = (1 / pow(10, r * curves[o->curve].cdens.Z)) *
+                        (1 / pow(10, g * curves[o->curve].mdens.Z)) *
+                        (1 / pow(10, b * curves[o->curve].ydens.Z));
                /*printf("XYZ output %f %f %f\n", out[0], out[1], out[2]);*/
 
                in   += 3;
@@ -310,9 +334,10 @@ gegl_op_class_init (GeglOpClass *klass)
        gegl_operation_class_set_keys (operation_class,
                "name",           "gegl:negative-darkroom",
                "title",          _("Negative Darkroom"),
-               "categories",     "color",
+               "categories" ,    "color",
                "reference-hash", "d492ac8ef38c336aa79e63b7f39f6139",
-               "description", _("Simulate a negative film enlargement in an analog darkroom."),
+               "description",    _("Simulate a negative film enlargement in "
+                                 "an analog darkroom."),
                NULL);
 }
 
diff --git a/operations/common/negative-darkroom/negative-darkroom-curve-enum.c 
b/operations/common/negative-darkroom/negative-darkroom-curve-enum.c
index db425f6c1..6e39a7bfa 100644
--- a/operations/common/negative-darkroom/negative-darkroom-curve-enum.c
+++ b/operations/common/negative-darkroom/negative-darkroom-curve-enum.c
@@ -4,4 +4,10 @@ enum_start(neg_curve)
        enum_value (NEG_ILFOBROM2, "ilfobrom2", N_("Ilford Ilfobrom Galerie FB 2"))
        enum_value (NEG_ILFOBROM3, "ilfobrom3", N_("Ilford Ilfobrom Galerie FB 3"))
        enum_value (NEG_ILFOBROM4, "ilfobrom4", N_("Ilford Ilfobrom Galerie FB 4"))
+       enum_value (NEG_ILFORDMG4, "ilfordmg4", N_("Ilford Multigrade IV RC Deluxe"))
+       enum_value (NEG_FOMABROMC, "fomabromc", N_("Foma Fomabrom C"))
+       enum_value (NEG_FOMABROMN, "fomabromn", N_("Foma Fomabrom N"))
+       enum_value (NEG_FOMABROMSP, "fomabromsp", N_("Foma Fomabrom Sp"))
+       enum_value (NEG_FOMABROMS, "fomabroms", N_("Foma Fomabrom S"))
+       enum_value (NEG_FOMABROMVAR, "fomabromvar", N_("Foma Fomabrom Variant III"))
 enum_end (NegCurve)
diff --git a/operations/common/negative-darkroom/negative-darkroom-curve-enum.h 
b/operations/common/negative-darkroom/negative-darkroom-curve-enum.h
index e36651ae2..118811b56 100644
--- a/operations/common/negative-darkroom/negative-darkroom-curve-enum.h
+++ b/operations/common/negative-darkroom/negative-darkroom-curve-enum.h
@@ -1,5 +1,6 @@
-static HDCurve curves[5] = {
+static HDCurve curves[11] = {
 {
+// Fujicolor Crystal Archive Digital Pearl Paper
 .rx = (gfloat[]){0.944085027726432, 1.0854898336414, 1.26016635859519, 1.38909426987061, 1.49722735674677, 
1.59288354898336, 1.67606284658041, 1.73844731977819, 1.83410351201479, 1.94639556377079, 2.10027726432532, 
2.15850277264325, 2.22088724584103, 2.28327171903882, 2.33733826247689, 2.39556377079482, 2.46210720887246, 
2.55360443622921, 2.64510166358595, 2.76571164510166, 2.85720887245841, 2.95702402957486, 3.04436229205176},
 .ry = (gfloat[]){0.103950103950104, 0.103950103950104, 0.116424116424116, 0.141372141372141, 
0.182952182952183, 0.249480249480249, 0.328482328482329, 0.415800415800416, 0.611226611226611, 
0.906444906444906, 1.38877338877339, 1.55509355509356, 1.72972972972973, 1.88357588357588, 2.02079002079002, 
2.13721413721414, 2.23700623700624, 2.36590436590437, 2.45738045738046, 2.54885654885655, 2.6029106029106, 
2.64449064449064, 2.66528066528067},
 .rn = 23,
@@ -9,14 +10,15 @@ static HDCurve curves[5] = {
 .bx = (gfloat[]){0.944085027726432, 1.1728280961183, 1.29343807763401, 1.4681146025878, 1.54297597042514, 
1.6677449168207, 1.7634011090573, 1.83826247689464, 1.93391866913124, 2.04205175600739, 2.13770794824399, 
2.20841035120148, 2.28327171903882, 2.33733826247689, 2.43715341959335, 2.49537892791128, 2.62014787430684, 
2.73243992606285, 2.81977818853974, 2.91127541589649, 3.05683918669131},
 .by = (gfloat[]){0.062370062370063, 0.070686070686071, 0.087318087318087, 0.128898128898129, 
0.17047817047817, 0.291060291060291, 0.436590436590437, 0.602910602910603, 0.860706860706861, 
1.21829521829522, 1.57172557172557, 1.8045738045738, 1.995841995842, 2.1039501039501, 2.24116424116424, 
2.30769230769231, 2.39085239085239, 2.43243243243243, 2.45322245322245, 2.46569646569647, 2.47817047817048},
 .bn = 21,
-.rsens = {1.5489263994697402, -0.7601427199734186, -0.13159136565865906},
-.gsens = {-0.6578318104480959, 1.365755119785612, 0.2388452773956612},
-.bsens = {-0.31414778017785455, 0.4138731583264843, 0.8534088408788981},
-.cdens = {0.5817794731231579, 0.3075301664892215, 0.007804784733728515},
-.mdens = {0.25642580250752084, 0.6574414690762187, 0.04462033446059675},
-.ydens = {0.1617947243693214, 0.03502836443455983, 0.9475748808056746}
+.rsens = {13.216626122512007, -8.227588994124007, 5.5928592740343674},
+.gsens = {-1.892225727743786, 18.471992221986618, 2.3648557587980648},
+.bsens = {-0.48215460646731667, 3.7273454493862825, 19.69174710002292},
+.cdens = {0.4481979852989705, 0.314585869218717, 0.059960861345768876},
+.mdens = {0.32037627279379055, 0.5719703189837888, 0.2318783856658509},
+.ydens = {0.12402572420852252, 0.11220266078991072, 0.82348502517513}
 },
 {
+// Ilford Ilfobrom Galerie FB 1
 .rx = (gfloat[]){1, 5},
 .ry = (gfloat[]){0, 0},
 .rn = 2,
@@ -26,14 +28,15 @@ static HDCurve curves[5] = {
 .bx = (gfloat[]){1.493581907, 1.576100244, 1.661369193, 1.754889976, 1.878667482, 1.994193154, 2.159229829, 
2.269254279, 2.503056235, 2.640586797, 2.758863081, 2.849633252, 2.9349022, 3.006418093, 3.099938875, 
3.215464548, 3.319987775, 3.50702934},
 .by = (gfloat[]){0.008241758, 0.041208791, 0.085164835, 0.151098901, 0.263736264, 0.431318681, 0.695054945, 
0.865384615, 1.263736264, 1.519230769, 1.728021978, 1.876373626, 2.010989011, 2.087912088, 2.151098901, 
2.195054945, 2.217032967, 2.21978022},
 .bn = 18,
-.rsens = {0.797668, 0.28804, 0.0},
-.gsens = {0.135193, 0.711884, 0.0},
-.bsens = {0.031342, 9.2e-05, 0.824905},
+.rsens = {0, 0, 0},
+.gsens = {0, 0, 0},
+.bsens = {0, 0, 1},
 .cdens = {0, 0, 0},
 .mdens = {0, 0, 0},
 .ydens = {1, 1, 1}
 },
 {
+// Ilford Ilfobrom Galerie FB 2
 .rx = (gfloat[]){1, 5},
 .ry = (gfloat[]){0, 0},
 .rn = 2,
@@ -43,14 +46,15 @@ static HDCurve curves[5] = {
 .bx = (gfloat[]){1.644865526, 1.686124694, 1.752139364, 1.848410758, 1.958435208, 2.068459658, 2.186735941, 
2.305012225, 2.42603912, 2.519559902, 2.588325183, 2.676344743, 2.723105134, 2.786369193, 2.830378973, 
2.910146699, 3.009168704, 3.143948655, 3.325488998},
 .by = (gfloat[]){0.008241758, 0.021978022, 0.057692308, 0.131868132, 0.269230769, 0.461538462, 0.736263736, 
1.010989011, 1.282967033, 1.497252747, 1.64010989, 1.821428571, 1.906593407, 2.0, 2.052197802, 2.10989011, 
2.151098901, 2.195054945, 2.217032967},
 .bn = 19,
-.rsens = {0.797668, 0.28804, 0.0},
-.gsens = {0.135193, 0.711884, 0.0},
-.bsens = {0.031342, 9.2e-05, 0.824905},
+.rsens = {0, 0, 0},
+.gsens = {0, 0, 0},
+.bsens = {0, 0, 1},
 .cdens = {0, 0, 0},
 .mdens = {0, 0, 0},
 .ydens = {1, 1, 1}
 },
 {
+// Ilford Ilfobrom Galerie FB 3
 .rx = (gfloat[]){1, 5},
 .ry = (gfloat[]){0, 0},
 .rn = 2,
@@ -60,14 +64,15 @@ static HDCurve curves[5] = {
 .bx = (gfloat[]){1.754889976, 1.851161369, 1.936430318, 1.999694377, 2.054706601, 2.197738386, 2.329767726, 
2.439792176, 2.533312958, 2.62408313, 2.670843521, 2.756112469, 2.813875306, 2.890892421, 3.006418093, 
3.075183374, 3.182457213, 3.33099022},
 .by = (gfloat[]){0.008241758, 0.071428571, 0.148351648, 0.233516484, 0.357142857, 0.760989011, 1.142857143, 
1.442307692, 1.678571429, 1.854395604, 1.936813187, 2.027472527, 2.074175824, 2.118131868, 2.156593407, 
2.178571429, 2.200549451, 2.217032967},
 .bn = 18,
-.rsens = {0.797668, 0.28804, 0.0},
-.gsens = {0.135193, 0.711884, 0.0},
-.bsens = {0.031342, 9.2e-05, 0.824905},
+.rsens = {0, 0, 0},
+.gsens = {0, 0, 0},
+.bsens = {0, 0, 1},
 .cdens = {0, 0, 0},
 .mdens = {0, 0, 0},
 .ydens = {1, 1, 1}
 },
 {
+// Ilford Ilfobrom Galerie FB 4
 .rx = (gfloat[]){1, 5},
 .ry = (gfloat[]){0, 0},
 .rn = 2,
@@ -77,11 +82,119 @@ static HDCurve curves[5] = {
 .bx = (gfloat[]){1.807151589, 1.873166259, 1.908924205, 1.952933985, 1.996943765, 2.035452323, 2.090464548, 
2.134474328, 2.18398533, 2.236246944, 2.277506112, 2.307762836, 2.362775061, 2.395782396, 2.42603912, 
2.486552567, 2.527811736, 2.604828851, 2.676344743, 2.734107579, 2.866136919, 3.006418093, 3.165953545},
 .by = (gfloat[]){0.002747253, 0.013736264, 0.043956044, 0.096153846, 0.167582418, 0.244505495, 0.414835165, 
0.546703297, 0.733516484, 0.901098901, 1.071428571, 1.195054945, 1.412087912, 1.546703297, 1.656593407, 
1.818681319, 1.906593407, 2.013736264, 2.085164835, 2.123626374, 2.175824176, 2.208791209, 2.222527473},
 .bn = 23,
-.rsens = {0.797668, 0.28804, 0.0},
-.gsens = {0.135193, 0.711884, 0.0},
-.bsens = {0.031342, 9.2e-05, 0.824905},
+.rsens = {0, 0, 0},
+.gsens = {0, 0, 0},
+.bsens = {0, 0, 1},
 .cdens = {0, 0, 0},
 .mdens = {0, 0, 0},
 .ydens = {1, 1, 1}
+},
+{
+// Ilford Multigrade IV RC Deluxe
+.rx = (gfloat[]){1.4175998847065818, 1.6645998847065817, 1.7905998847065816, 1.8605998847065819, 
1.912599884706582, 1.9455998847065819, 1.9995998847065817, 2.033599884706582, 2.0635998847065817, 
2.090599884706582, 2.1085998847065817, 2.142599884706582, 2.198599884706582, 2.255599884706582, 
2.284599884706582, 2.316599884706582, 2.356599884706582, 2.4065998847065817, 2.477599884706582, 
2.601599884706582, 2.7455998847065817},
+.ry = (gfloat[]){0.010324304382967808, 0.011248199014068795, 0.012257403333089143, 0.01819062738271929, 
0.026078923102844962, 0.04853211805309718, 0.07812503814734445, 0.10921133018526209, 0.1471749703315005, 
0.18443346486701004, 0.22997172105182173, 0.27226289725573105, 0.3341898165415062, 0.38372051942076135, 
0.42042941659598687, 0.4351705729738252, 0.4501109559351687, 0.4642143696466637, 0.4764098662262221, 
0.47918347130497196, 0.4791834713049721},
+.rn = 21,
+.gx = (gfloat[]){1.7592759955350934, 2.006275995535093, 2.132275995535093, 2.2022759955350932, 
2.2542759955350933, 2.287275995535093, 2.341275995535093, 2.3752759955350933, 2.405275995535093, 
2.432275995535093, 2.450275995535093, 2.4842759955350933, 2.5402759955350933, 2.5972759955350933, 
2.626275995535093, 2.658275995535093, 2.6982759955350932, 2.748275995535093, 2.8192759955350932, 
2.9432759955350933, 3.087275995535093},
+.gy = (gfloat[]){0.014813541483019594, 0.01613916604193243, 0.017587194837878586, 0.026100316625748653, 
0.037418618716220056, 0.06963496206334203, 0.11209554179431286, 0.15669884479423668, 0.21116991977343746, 
0.2646292361519006, 0.3299685386400133, 0.39064885857477044, 0.47950297927163954, 0.5505707330464511, 
0.6032414749124313, 0.6243924138435842, 0.6458292075064267, 0.6660650990801078, 0.6835634687315634, 
0.6875430989678973, 0.6875430989678976},
+.gn = 21,
+.bx = (gfloat[]){2.1261790772490836, 2.3731790772490835, 2.4991790772490834, 2.5691790772490837, 
2.6211790772490837, 2.6541790772490836, 2.7081790772490835, 2.7421790772490837, 2.7721790772490835, 
2.7991790772490837, 2.8171790772490835, 2.8511790772490837, 2.9071790772490838, 2.9641790772490837, 
2.9931790772490836, 3.0251790772490836, 3.0651790772490837, 3.1151790772490835, 3.1861790772490837, 
3.310179077249084, 3.4541790772490835},
+.by = (gfloat[]){0.018360273195730175, 0.020003285373777404, 0.02179800841953461, 0.032349384128914034, 
0.04637757034833112, 0.08630731070776017, 0.13893401343130068, 0.19421646087638, 0.2617292713025447, 
0.32798808285619363, 0.40897124582740674, 0.4841799494911138, 0.5943079652954991, 0.682391113826059, 
0.7476725464388939, 0.7738875482713264, 0.8004568455957672, 0.8255377148853861, 0.8472256311509777, 
0.852158084233911, 0.8521580842339112},
+.bn = 21,
+.rsens = {0.0, 0.0, 1.0},
+.gsens = {0.0, 0.5178010948888863, 1},
+.bsens = {0.0, 1.0, 1.0},
+.cdens = {1, 1, 1},
+.mdens = {1, 1, 1},
+.ydens = {1, 1, 1}
+},
+{
+// Foma Fomabrom C
+.rx = (gfloat[]){1, 5},
+.ry = (gfloat[]){0, 0},
+.rn = 2,
+.gx = (gfloat[]){1, 5},
+.gy = (gfloat[]){0, 0},
+.gn = 2,
+.bx = (gfloat[]){-0.07312925170068, 0.017006802721089, 0.090136054421769, 0.187074829931973, 
0.272108843537415, 0.331632653061224, 0.431972789115646, 0.539115646258503, 0.727891156462585, 
0.852040816326531, 0.887755102040816, 0.925170068027211, 0.981292517006803, 1.04761904761905, 
1.13775510204082, 1.24319727891156},
+.by = (gfloat[]){0.060975609756098, 0.065040650406504, 0.09349593495935, 0.16869918699187, 
0.288617886178862, 0.40650406504065, 0.678861788617886, 0.969512195121951, 1.49390243902439, 
1.85569105691057, 1.94105691056911, 2.00609756097561, 2.07317073170732, 2.1239837398374, 2.15447154471545, 
2.16260162601626},
+.bn = 16,
+.rsens = {0, 0, 0},
+.gsens = {0, 0, 0},
+.bsens = {0, 0, 1},
+.cdens = {0, 0, 0},
+.mdens = {0, 0, 0},
+.ydens = {1, 1, 1}
+},
+{
+// Foma Fomabrom N
+.rx = (gfloat[]){1, 5},
+.ry = (gfloat[]){0, 0},
+.rn = 2,
+.gx = (gfloat[]){1, 5},
+.gy = (gfloat[]){0, 0},
+.gn = 2,
+.bx = (gfloat[]){-0.173469387755102, -0.054421768707483, 0.032312925170068, 0.120748299319728, 
0.22108843537415, 0.431972789115646, 0.625850340136054, 0.914965986394558, 1.06292517006803, 
1.21768707482993, 1.2891156462585, 1.34353741496599, 1.4047619047619, 1.48809523809524},
+.by = (gfloat[]){0.060975609756098, 0.07520325203252, 0.123983739837398, 0.211382113821138, 
0.339430894308943, 0.680894308943089, 1.00609756097561, 1.49390243902439, 1.74186991869919, 2.00406504065041, 
2.08943089430894, 2.13211382113821, 2.15650406504065, 2.16260162601626},
+.bn = 14,
+.rsens = {0, 0, 0},
+.gsens = {0, 0, 0},
+.bsens = {0, 0, 1},
+.cdens = {0, 0, 0},
+.mdens = {0, 0, 0},
+.ydens = {1, 1, 1}
+},
+{
+// Foma Fomabrom Sp
+.rx = (gfloat[]){1, 5},
+.ry = (gfloat[]){0, 0},
+.rn = 2,
+.gx = (gfloat[]){1, 5},
+.gy = (gfloat[]){0, 0},
+.gn = 2,
+.bx = (gfloat[]){-0.273809523809524, -0.197278911564626, -0.102040816326531, 0.042517006802721, 
0.193877551020408, 0.433673469387755, 0.664965986394558, 1.07823129251701, 1.47959183673469, 
1.55102040816327, 1.62244897959184, 1.69387755102041, 1.83843537414966},
+.by = (gfloat[]){0.065040650406504, 0.079268292682927, 0.128048780487805, 0.241869918699187, 
0.398373983739837, 0.678861788617886, 0.971544715447154, 1.48983739837398, 2.0020325203252, 2.08943089430894, 
2.14024390243902, 2.15853658536585, 2.16463414634146},
+.bn = 13,
+.rsens = {0, 0, 0},
+.gsens = {0, 0, 0},
+.bsens = {0, 0, 1},
+.cdens = {0, 0, 0},
+.mdens = {0, 0, 0},
+.ydens = {1, 1, 1}
+},
+{
+// Foma Fomabrom S
+.rx = (gfloat[]){1, 5},
+.ry = (gfloat[]){0, 0},
+.rn = 2,
+.gx = (gfloat[]){1, 5},
+.gy = (gfloat[]){0, 0},
+.gn = 2,
+.bx = (gfloat[]){0.37218045112782, 0.428571428571429, 0.49874686716792, 0.605263157894737, 
0.716791979949875, 0.893483709273183, 1.06390977443609, 1.36842105263158, 1.66416040100251, 1.71679197994987, 
1.76942355889724, 1.82205513784461, 1.92857142857143},
+.by = (gfloat[]){0.005357142857143, 0.017857142857143, 0.060714285714286, 0.160714285714286, 
0.298214285714286, 0.544642857142857, 0.801785714285714, 1.25714285714286, 1.70714285714286, 
1.78392857142857, 1.82857142857143, 1.84464285714286, 1.85},
+.bn = 13,
+.rsens = {0, 0, 0},
+.gsens = {0, 0, 0},
+.bsens = {0, 0, 1},
+.cdens = {0, 0, 0},
+.mdens = {0, 0, 0},
+.ydens = {1, 1, 1}
+},
+{
+// Foma Fomabrom Variant III
+.rx = (gfloat[]){-0.15477518799190898, 0.08958571426373108, 0.23369598995295304, 0.325174686694808, 
0.4742974937123521, 0.6296859648902939, 0.835199749351454, 0.896603258123384, 0.988081954865234, 
1.083320050103334, 1.138457894714854, 1.213645864639674},
+.ry = (gfloat[]){0.026687751404829638, 0.035859636141161756, 0.05696854127040171, 0.10672477707954037, 
0.18695111054247987, 0.30305251781200454, 0.40607423350124205, 0.47801358379771275, 0.5180402202518342, 
0.54844497502493, 0.5646113624653601, 0.5680413126990469},
+.rn = 12,
+.gx = (gfloat[]){0.08315254145874457, 0.3275134437143846, 0.4716237194036066, 0.5631024161454615, 
0.7122252231630056, 0.8676136943409475, 1.0731274788021077, 1.1345309875740375, 1.2260096843158874, 
1.3212477795539876, 1.3763856241655077, 1.4515735940903274},
+.gy = (gfloat[]){0.025405116424060247, 0.034136192940023694, 0.05423058696588138, 0.1015954977213603, 
0.1779660885210264, 0.2884875679794168, 0.3865579764446976, 0.45503986321101203, 0.49314278704881664, 
0.5220862646441495, 0.5374756823905344, 0.5407407864337239},
+.gn = 12,
+.bx = (gfloat[]){0.4376465286343034, 0.6820074308899434, 0.8261177065791654, 0.9175964033210203, 
1.0667192103385645, 1.2221076815165064, 1.4276214659776665, 1.4890249747495965, 1.5805036714914464, 
1.6757417667295464, 1.7308796113410665, 1.8060675812658864},
+.by = (gfloat[]){0.041941797737101716, 0.05635610071242231, 0.08953032419615994, 0.16772597083609284, 
0.2938076552856473, 0.47626970189366724, 0.6381760347436221, 0.7512341052308589, 0.8141389586517978, 
0.8619223052363505, 0.8873289924420565, 0.8927194158152141},
+.bn = 12,
+.rsens = {0.0, 0.0, 1.0},
+.gsens = {0.0, 0.5983811484737084, 1},
+.bsens = {0.0, 1.0, 1.0},
+.cdens = {1, 1, 1},
+.mdens = {1, 1, 1},
+.ydens = {1, 1, 1}
 }
 };


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]