[babl/wip/icc-cluts: 3/5] babl: implement icc mft2 b2a0 parsing/handling
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [babl/wip/icc-cluts: 3/5] babl: implement icc mft2 b2a0 parsing/handling
- Date: Mon, 11 Sep 2017 15:15:41 +0000 (UTC)
commit e3d93424a8276d134ae5c23b04ef111f1fd21ade
Author: Øyvind Kolås <pippin gimp org>
Date: Tue Sep 5 03:37:53 2017 +0200
babl: implement icc mft2 b2a0 parsing/handling
babl/babl-fish-reference.c | 45 ++++++++++----
babl/babl-icc.c | 43 +++++++-----
babl/babl-space.c | 80 ++++++++++++++++++++++-
babl/babl-space.h | 151 +++++++++++++++++++++++++++++++++++++++++---
4 files changed, 277 insertions(+), 42 deletions(-)
---
diff --git a/babl/babl-fish-reference.c b/babl/babl-fish-reference.c
index d97cca3..3e3b24e 100644
--- a/babl/babl-fish-reference.c
+++ b/babl/babl-fish-reference.c
@@ -434,11 +434,12 @@ babl_fish_reference_process (const Babl *babl,
Babl *source_image;
Babl *rgba_image;
Babl *destination_image;
+ BablSpace *destination_space = (void*)&((babl->fish.destination)->format.space->space);
+ BablSpace *source_space = (void*)&((babl->fish.source)->format.space->space);
if ((BABL (babl->fish.source)->format.model ==
BABL (babl->fish.destination)->format.model) &&
- (BABL (babl->fish.source)->format.space ==
- BABL (babl->fish.destination)->format.space)
+ (source_space == destination_space)
)
return process_same_model (babl, source, destination, n);
@@ -492,17 +493,37 @@ babl_fish_reference_process (const Babl *babl,
else babl_fatal ("oops");
}
- if (((babl->fish.source)->format.space !=
- ((babl->fish.destination)->format.space)))
+ if (source_space != destination_space || 1)
{
- double matrix[9];
- double *rgba = rgba_double_buf;
- babl_matrix_mul_matrix (
- (babl->fish.destination)->format.space->space.XYZtoRGB,
- (babl->fish.source)->format.space->space.RGBtoXYZ,
- matrix);
-
- babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
+ // if neither space has luts we use the matrix
+ if (destination_space->b2a0 || source_space->a2b0)
+ {
+ int i;
+
+ double *rgba = rgba_double_buf;
+ for (i = 0; i < n; i++)
+ {
+ double xyz[4];
+ static int counter = 0;
+ if (counter ++ % 100000 == 0)
+ fprintf (stderr, "!");
+
+ babl_space_to_xyz ((void*)source_space, rgba, xyz);
+ babl_space_from_xyz ((void*)destination_space, xyz, rgba);
+ rgba += 4;
+ }
+ }
+ else
+ {
+ double matrix[9];
+ double *rgba = rgba_double_buf;
+ babl_matrix_mul_matrix (
+ (babl->fish.destination)->format.space->space.XYZtoRGB,
+ (babl->fish.source)->format.space->space.RGBtoXYZ,
+ matrix);
+
+ babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
+ }
}
{
diff --git a/babl/babl-icc.c b/babl/babl-icc.c
index 32f1066..ae4b50b 100644
--- a/babl/babl-icc.c
+++ b/babl/babl-icc.c
@@ -668,27 +668,27 @@ static char *decode_string (ICC *state, const char *tag, const char *lang, const
return NULL;
}
-static ICCv2CLUT *load_mft2 (ICC *state, int offset)
+static ICCv2CLUT *load_mft2 (ICC *state, int offset, int size)
{
int i, c;
int o;
ICCv2CLUT *clut = babl_calloc (sizeof (ICCv2CLUT), 1);
- clut->clut_size = icc_read (u8, offset + 10);
+ clut->clut_size[0] = icc_read (u8, offset + 10);
+ clut->clut_size[1] = icc_read (u8, offset + 10);
+ clut->clut_size[2] = icc_read (u8, offset + 10);
clut->in_table_size = icc_read (u16, offset + 48);
clut->out_table_size = icc_read (u16, offset + 50);
+
for (i = 0; i < 9; i++)
clut->matrix[i] = icc_read (s15f16, offset + 12 + i * 4);
- clut->clut = babl_calloc (sizeof (float), 3 * clut->clut_size * clut->clut_size * clut->clut_size);
+ clut->clut = babl_calloc (sizeof (float), 3 * clut->clut_size[0] * clut->clut_size[1] *
(clut->clut_size[2]+1));
for (c = 0; c < 3; c++)
clut->in_table[c] = babl_calloc (sizeof (float), clut->in_table_size);
for (c = 0; c < 3; c++)
clut->out_table[c] = babl_calloc (sizeof (float), clut->out_table_size);
- for (i = 0; i < 9; i++)
- clut->matrix[i] = icc_read (s15f16, offset + 12 + i * 4);
-
o = 52;
for (c = 0; c < 3; c++)
for (i = 0; i < clut->in_table_size; i++)
@@ -696,7 +696,7 @@ static ICCv2CLUT *load_mft2 (ICC *state, int offset)
clut->in_table[c][i] = icc_read (u16, offset + o) / 65535.0;
o+=2;
}
- for (i = 0; i < 3 * clut->clut_size * clut->clut_size * clut->clut_size; i++)
+ for (i = 0; i < 3 * clut->clut_size[0] * clut->clut_size[1] * clut->clut_size[2]; i++)
{
clut->clut[i] = icc_read (u16, offset + o) / 65535.0;
o+=2;
@@ -715,22 +715,29 @@ static ICCv2CLUT *load_mft1 (ICC *state, int offset)
int i, c;
int o;
ICCv2CLUT *clut = babl_calloc (sizeof (ICCv2CLUT), 1);
- clut->clut_size = icc_read (u8, offset + 10);
+
+ clut->clut_size[0] = icc_read (u8, offset + 10);
+ clut->clut_size[1] = icc_read (u8, offset + 10);
+ clut->clut_size[2] = icc_read (u8, offset + 10);
clut->in_table_size = 256;
clut->out_table_size = 256;
- for (i = 0; i < 9; i++)
- clut->matrix[i] = icc_read (s15f16, offset + 12 + i * 4);
-
- clut->clut = babl_calloc (sizeof (float), 3 * clut->clut_size * clut->clut_size * clut->clut_size);
+ clut->matrix[0] = icc_read (s15f16, offset + 12 + 0 * 4);
+ clut->matrix[1] = icc_read (s15f16, offset + 12 + 3 * 4);
+ clut->matrix[2] = icc_read (s15f16, offset + 12 + 6 * 4);
+ clut->matrix[3] = icc_read (s15f16, offset + 12 + 1 * 4);
+ clut->matrix[4] = icc_read (s15f16, offset + 12 + 4 * 4);
+ clut->matrix[5] = icc_read (s15f16, offset + 12 + 7 * 4);
+ clut->matrix[6] = icc_read (s15f16, offset + 12 + 2 * 4);
+ clut->matrix[7] = icc_read (s15f16, offset + 12 + 5 * 4);
+ clut->matrix[8] = icc_read (s15f16, offset + 12 + 8 * 4);
+
+ clut->clut = babl_calloc (sizeof (float), 3 * clut->clut_size[0] * clut->clut_size[1] *
(clut->clut_size[2]+1));
for (c = 0; c < 3; c++)
clut->in_table[c] = babl_calloc (sizeof (float), clut->in_table_size);
for (c = 0; c < 3; c++)
clut->out_table[c] = babl_calloc (sizeof (float), clut->out_table_size);
- for (i = 0; i < 9; i++)
- clut->matrix[i] = icc_read (s15f16, offset + 12 + i * 4);
-
o = 52;
for (c = 0; c < 3; c++)
for (i = 0; i < clut->in_table_size; i++)
@@ -738,7 +745,7 @@ static ICCv2CLUT *load_mft1 (ICC *state, int offset)
clut->in_table[c][i] = icc_read (u8, offset + o) / 255.0;
o++;
}
- for (i = 0; i < 3 * clut->clut_size * clut->clut_size * clut->clut_size; i++)
+ for (i = 0; i < 3 * clut->clut_size[0] * clut->clut_size[1] * clut->clut_size[2]; i++)
{
clut->clut[i] = icc_read (u8, offset + o) / 255.0;
o++;
@@ -827,7 +834,7 @@ babl_space_from_icc (const char *icc_data,
if (icc_tag (state, "A2B0", &offset, &element_size))
{
if (!strcmp (state->data + offset, "mft2"))
- a2b0 = load_mft2 (state, offset);
+ a2b0 = load_mft2 (state, offset, element_size);
else if (!strcmp (state->data + offset, "mft1"))
a2b0 = load_mft1 (state, offset);
}
@@ -838,7 +845,7 @@ babl_space_from_icc (const char *icc_data,
if (icc_tag (state, "B2A0", &offset, &element_size))
{
if (!strcmp (state->data + offset, "mft2"))
- b2a0 = load_mft2 (state, offset);
+ b2a0 = load_mft2 (state, offset, element_size);
else if (!strcmp (state->data + offset, "mft1"))
b2a0 = load_mft1 (state, offset);
}
diff --git a/babl/babl-space.c b/babl/babl-space.c
index 6966aba..9d4324e 100644
--- a/babl/babl-space.c
+++ b/babl/babl-space.c
@@ -474,8 +474,6 @@ static void prep_conversion (const Babl *babl)
} while(0)
-
-
static inline void
universal_nonlinear_rgb_converter (const Babl *conversion,unsigned char *src_char, unsigned char *dst_char,
long samples)
{
@@ -742,11 +740,86 @@ universal_nonlinear_rgb_linear_converter_sse2 (const Babl *conversion,unsigned c
}
#endif
+static inline long
+universal_generic_rgba_converter (const Babl *conversion,unsigned char *src_char, unsigned char *dst_char,
long samples)
+{
+ const Babl *source_space = babl_conversion_get_source_space (conversion);
+ const Babl *destination_space = babl_conversion_get_destination_space (conversion);
+ float *rgba_in = (void*)src_char;
+ float *rgba_out = (void*)dst_char;
+
+ int i;
+ for (i = 0; i < samples; i++)
+ {
+ double rgba[4] = {rgba_in[0], rgba_in[1], rgba_in[2]};
+ babl_space_to_xyz (source_space,
+ rgba, rgba);
+ babl_space_from_xyz (destination_space,
+ rgba, rgba);
+ rgba_out[0] = rgba[0];
+ rgba_out[1] = rgba[1];
+ rgba_out[2] = rgba[2];
+ rgba_out[3] = rgba_in[3];
+ rgba_in += 4;
+ rgba_out += 4;
+ {
+ static int counter = 0;
+ if (counter ++ % 100000 == 0)
+ fprintf (stderr, "%%");
+ }
+ }
+ return samples;
+}
+
+static inline long
+universal_generic_rgb_converter (const Babl *conversion,unsigned char *src_char, unsigned char *dst_char,
long samples)
+{
+ const Babl *source_space = babl_conversion_get_source_space (conversion);
+ const Babl *destination_space = babl_conversion_get_destination_space (conversion);
+ float *rgba_in = (void*)src_char;
+ float *rgba_out = (void*)dst_char;
+
+ int i;
+ for (i = 0; i < samples; i++)
+ {
+ double rgba[4] = {rgba_in[0], rgba_in[1], rgba_in[2]};
+ babl_space_to_xyz (source_space, rgba, rgba);
+ babl_space_from_xyz (destination_space, rgba, rgba);
+ rgba_out[0] = rgba[0];
+ rgba_out[1] = rgba[1];
+ rgba_out[2] = rgba[2];
+ rgba_in += 3;
+ rgba_out += 3;
+
+
+ {
+ static int counter = 0;
+ if (counter ++ % 100000 == 0)
+ fprintf (stderr, ":");
+ }
+ }
+ return samples;
+}
static int
add_rgb_adapter (Babl *babl,
- void *space)
+ void *data)
{
+ Babl *space = data;
+
+ if (space->space.a2b0 || babl->space.a2b0)
+ {
+ prep_conversion(babl_conversion_new(babl_format_with_space("RGBA float", (void*)space),
+ babl_format_with_space("RGBA float", babl),
+ "linear", universal_generic_rgba_converter,
+ NULL));
+ prep_conversion(babl_conversion_new(babl_format_with_space("RGB float", (void*)space),
+ babl_format_with_space("RGB float", babl),
+ "linear", universal_generic_rgb_converter,
+ NULL));
+ return 0;
+ }
+
if (babl != space)
{
@@ -879,3 +952,4 @@ const Babl *babl_space_match_trc_matrix (const Babl *trc_red,
}
return NULL;
}
+
diff --git a/babl/babl-space.h b/babl/babl-space.h
index a5c2e08..4b4ae38 100644
--- a/babl/babl-space.h
+++ b/babl/babl-space.h
@@ -29,7 +29,7 @@ BABL_CLASS_DECLARE (space);
typedef struct
{
float *clut;
- int clut_size;
+ int clut_size[3];
int in_table_size;
int out_table_size;
float matrix[9];
@@ -37,6 +37,7 @@ typedef struct
float *out_table[3];
} ICCv2CLUT;
+
typedef struct
{
BablInstance instance;
@@ -78,28 +79,160 @@ typedef struct
} BablSpace;
+
+static inline float do_lut (float *lut, int lut_size, float value)
+{
+ int entry;
+ float diff;
+ entry = value * (lut_size-1);
+ diff = ( (value * (lut_size-1)) - entry);
+ if (entry >= lut_size) entry = lut_size - 1;
+ else if (entry < 0) entry = 0;
+
+ if (diff > 0.0 && entry < lut_size - 1)
+ {
+ return lut[entry] * (1.0 - diff) + lut[entry+1] * diff;
+ }
+ else
+ {
+ return lut[entry];
+ }
+}
+
+static inline void clut_interpol (ICCv2CLUT *clut, const double *ind, double *outd)
+{
+ float val[3] = {ind[0], ind[1], ind[2]};
+ int entry[3];
+ float diff[3];
+ int *dim = clut->clut_size;
+ int c;
+
+ babl_matrix_mul_vectorff (clut->matrix, val, val);
+
+ for (c = 0; c < 3; c ++)
+ {
+ val[c] = do_lut (clut->in_table[c], clut->in_table_size, val[c]);
+ }
+
+ for (c = 0; c < 3; c++)
+ {
+ entry[c] = val[c] * (dim[c]-1);
+ diff[c] = ((val[c] * (dim[c]-1)) - entry[c]);
+
+ if (entry[c] >= dim[c] - 1)
+ {
+ entry[c] = dim[c] - 1;
+ diff[c] = 0.0;
+ }
+ else if (entry[c] <= 0.0001)
+ {
+ entry[c] = 0;
+ diff[c] = 0.0;
+ }
+ }
+
+ // needs rework for non-same sized acceses
+#define IDX(a,b,c,comp) (((a) * dim[0] * dim[1] + (b) * dim[0] + (c)) * 3 + comp)
+
+ for (c = 0; c < 3; c ++)
+ {
+#if 1
+ val[c] =
+ ((clut->clut[IDX(entry[0], entry[1], entry[2],c )] * (1.0 - diff[0]) +
+ clut->clut[IDX(entry[0]+1, entry[1], entry[2],c )] * (diff[0])) * (1.0 - diff[1]) +
+
+ (clut->clut[IDX(entry[0], entry[1]+1, entry[2],c )] * (1.0 - diff[0]) +
+ clut->clut[IDX(entry[0]+1, entry[1]+1, entry[2],c )] * (diff[0])) * diff[1]) *
+ (1.0-diff[2]) +
+
+ ((clut->clut[IDX(entry[0], entry[1], entry[2]+1,c)] * (1.0 - diff[0]) +
+ clut->clut[IDX(entry[0]+1, entry[1], entry[2]+1,c)] * (diff[0])) * (1.0 - diff[1]) +
+
+ (clut->clut[IDX(entry[0], entry[1]+1, entry[2]+1,c)] * (1.0 - diff[0]) +
+ clut->clut[IDX(entry[0]+1, entry[1]+1, entry[2]+1,c)] * (diff[0])) * diff[1]) * diff[2];
+#else
+ val[c] = clut->clut[IDX(entry[0], entry[1], entry[2],c)];
+#endif
+ }
+ for (c = 0; c < 3; c ++)
+ val[c] = do_lut (clut->out_table[c], clut->out_table_size, val[c]);
+ for (c = 0; c < 3; c ++)
+ outd[c] = val[c];
+}
+
+
static inline void babl_space_to_xyzf (const Babl *space, const float *rgb, float *xyz)
{
BablSpace *space_ = (void*)space;
- babl_matrix_mul_vectorff (space_->RGBtoXYZf, rgb, xyz);
+ double rgbmat[3] = {rgb[0], rgb[1], rgb[2]};
+ double xyzmat[3];
+ if (space_->a2b0)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ rgbmat[c] = babl_trc_from_linear (space_->trc[c], rgbmat[c]);
+ clut_interpol (space_->a2b0, rgbmat, xyzmat);
+ }
+ else
+ {
+ babl_matrix_mul_vector (space_->RGBtoXYZ, rgbmat, xyzmat);
+ }
+ xyz[0] = xyzmat[0];
+ xyz[1] = xyzmat[1];
+ xyz[2] = xyzmat[2];
}
+
static inline void babl_space_from_xyzf (const Babl *space, const float *xyz, float *rgb)
{
BablSpace *space_ = (void*)space;
- babl_matrix_mul_vectorff (space_->XYZtoRGBf, xyz, rgb);
+ double xyzmat[3] = {xyz[0], xyz[1], xyz[2]};
+ double rgbmat[3];
+ if (space_->b2a0)
+ {
+ int c;
+ clut_interpol (space_->b2a0, xyzmat, rgbmat);
+ for (c = 0; c < 3; c++)
+ rgbmat[c] = babl_trc_to_linear (space_->trc[c], rgbmat[c]);
+ }
+ else
+ {
+ babl_matrix_mul_vector (space_->XYZtoRGB, xyzmat, rgbmat);
+ }
+ rgb[0] = rgbmat[0];
+ rgb[1] = rgbmat[1];
+ rgb[2] = rgbmat[2];
}
-static inline void _babl_space_to_xyz (const Babl *space, const double *rgb, double *xyz)
+
+static inline void _babl_space_to_xyz (const Babl *space_, const double *rgb, double *xyz)
{
- BablSpace *space_ = (void*)space;
- babl_matrix_mul_vector (space_->RGBtoXYZ, rgb, xyz);
+ BablSpace *space = (void*)space_;
+ if (space->a2b0)
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ xyz[c] = babl_trc_from_linear (space->trc[c], rgb[c]);
+ clut_interpol (space->a2b0, xyz, xyz);
+ }
+ else
+ babl_matrix_mul_vector (space->RGBtoXYZ, rgb, xyz);
}
-static inline void _babl_space_from_xyz (const Babl *space, const double *xyz, double *rgb)
+static inline void _babl_space_from_xyz (const Babl *space_, const double *xyz, double *rgb)
{
- BablSpace *space_ = (void*)space;
- babl_matrix_mul_vector (space_->XYZtoRGB, xyz, rgb);
+ BablSpace *space = (void*)space_;
+ if (space->b2a0)
+ {
+ clut_interpol (space->b2a0, xyz, rgb);
+ {
+ int c;
+ for (c = 0; c < 3; c++)
+ rgb[c] = babl_trc_to_linear (space->trc[c], rgb[c]);
+ }
+ }
+ else
+ babl_matrix_mul_vector (space->XYZtoRGB, xyz, rgb);
}
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]