mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-01 00:11:29 +00:00
Merge branch 'matthiasc/for-main' into 'main'
image-tool: Allow specifying cicp tuples See merge request GNOME/gtk!7511
This commit is contained in:
commit
2ee1f3e8cf
@ -70,6 +70,11 @@ The ``convert`` command converts the image to a different format or color state.
|
||||
Convert to the given color state. The supported color states can be
|
||||
listed with ``--format=list``.
|
||||
|
||||
``--cicp=CICP``
|
||||
|
||||
Convert to a color state that is specified as a cicp tuple. The cicp tuple
|
||||
must be specified as four numbers, separated by /, e.g. 1/13/6/0.
|
||||
|
||||
Relabeling
|
||||
^^^^^^^^^^
|
||||
|
||||
@ -78,5 +83,10 @@ This can be useful to produce wrong color renderings for diagnostics.
|
||||
|
||||
``--color-state=COLORSTATE``
|
||||
|
||||
Convert to the given color state. The supported color states can be
|
||||
Relabel to the given color state. The supported color states can be
|
||||
listed with ``--format=list``.
|
||||
|
||||
``--cicp=CICP``
|
||||
|
||||
Relabel to a color state that is specified as a cicp tuple. The cicp tuple
|
||||
must be specified as four numbers, separated by /, e.g. 1/13/6/0.
|
||||
|
@ -119,76 +119,82 @@ hlg_oetf (float v)
|
||||
* for how to derive the abc_to_xyz matrices from chromaticity coordinates.
|
||||
*/
|
||||
|
||||
static const float srgb_to_xyz[3][3] = {
|
||||
{ 0.4124564, 0.3575761, 0.1804375 },
|
||||
{ 0.2126729, 0.7151522, 0.0721750 },
|
||||
{ 0.0193339, 0.1191920, 0.9503041 }
|
||||
static const float identity[9] = {
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1,
|
||||
};
|
||||
|
||||
static const float xyz_to_srgb[3][3] = {
|
||||
{ 3.2404542, -1.5371385, -0.4985314 },
|
||||
{ -0.9692660, 1.8760108, 0.0415560 },
|
||||
{ 0.0556434, -0.2040259, 1.0572252 },
|
||||
static const float srgb_to_xyz[9] = {
|
||||
0.4124564, 0.3575761, 0.1804375,
|
||||
0.2126729, 0.7151522, 0.0721750,
|
||||
0.0193339, 0.1191920, 0.9503041,
|
||||
};
|
||||
|
||||
static const float rec2020_to_xyz[3][3] = {
|
||||
{ 0.6369580, 0.1446169, 0.1688810 },
|
||||
{ 0.2627002, 0.6779981, 0.0593017 },
|
||||
{ 0.0000000, 0.0280727, 1.0609851 }
|
||||
static const float xyz_to_srgb[9] = {
|
||||
3.2404542, -1.5371385, -0.4985314,
|
||||
-0.9692660, 1.8760108, 0.0415560,
|
||||
0.0556434, -0.2040259, 1.0572252,
|
||||
};
|
||||
|
||||
static const float xyz_to_rec2020[3][3] = {
|
||||
{ 1.7166512, -0.3556708, -0.2533663 },
|
||||
{ -0.6666844, 1.6164812, 0.0157685 },
|
||||
{ 0.0176399, -0.0427706, 0.9421031 },
|
||||
static const float rec2020_to_xyz[9] = {
|
||||
0.6369580, 0.1446169, 0.1688810,
|
||||
0.2627002, 0.6779981, 0.0593017,
|
||||
0.0000000, 0.0280727, 1.0609851,
|
||||
};
|
||||
|
||||
static const float pal_to_xyz[3][3] = {
|
||||
{ 0.4305538, 0.3415498, 0.1783523 },
|
||||
{ 0.2220043, 0.7066548, 0.0713409 },
|
||||
{ 0.0201822, 0.1295534, 0.9393222 },
|
||||
static const float xyz_to_rec2020[9] = {
|
||||
1.7166512, -0.3556708, -0.2533663,
|
||||
-0.6666844, 1.6164812, 0.0157685,
|
||||
0.0176399, -0.0427706, 0.9421031,
|
||||
};
|
||||
|
||||
static const float xyz_to_pal[3][3] = {
|
||||
{ 3.0633611, -1.3933902, -0.4758237 },
|
||||
{ -0.9692436, 1.8759675, 0.0415551 },
|
||||
{ 0.0678610, -0.2287993, 1.0690896 },
|
||||
static const float pal_to_xyz[9] = {
|
||||
0.4305538, 0.3415498, 0.1783523,
|
||||
0.2220043, 0.7066548, 0.0713409,
|
||||
0.0201822, 0.1295534, 0.9393222,
|
||||
};
|
||||
|
||||
static const float ntsc_to_xyz[3][3] = {
|
||||
{ 0.3935209, 0.3652581, 0.1916769 },
|
||||
{ 0.2123764, 0.7010599, 0.0865638 },
|
||||
{ 0.0187391, 0.1119339, 0.9583847 },
|
||||
static const float xyz_to_pal[9] = {
|
||||
3.0633611, -1.3933902, -0.4758237,
|
||||
-0.9692436, 1.8759675, 0.0415551,
|
||||
0.0678610, -0.2287993, 1.0690896,
|
||||
};
|
||||
|
||||
static const float xyz_to_ntsc[3][3] = {
|
||||
{ 3.5060033, -1.7397907, -0.5440583 },
|
||||
{ -1.0690476, 1.9777789, 0.0351714 },
|
||||
{ 0.0563066, -0.1969757, 1.0499523 },
|
||||
static const float ntsc_to_xyz[9] = {
|
||||
0.3935209, 0.3652581, 0.1916769,
|
||||
0.2123764, 0.7010599, 0.0865638,
|
||||
0.0187391, 0.1119339, 0.9583847,
|
||||
};
|
||||
|
||||
static const float p3_to_xyz[3][3] = {
|
||||
{ 0.4865709, 0.2656677, 0.1982173 },
|
||||
{ 0.2289746, 0.6917385, 0.0792869 },
|
||||
{ 0.0000000, 0.0451134, 1.0439444 },
|
||||
static const float xyz_to_ntsc[9] = {
|
||||
3.5060033, -1.7397907, -0.5440583,
|
||||
-1.0690476, 1.9777789, 0.0351714,
|
||||
0.0563066, -0.1969757, 1.0499523,
|
||||
};
|
||||
|
||||
static const float xyz_to_p3[3][3] = {
|
||||
{ 2.4934969, -0.9313836, -0.4027108 },
|
||||
{ -0.8294890, 1.7626641, 0.0236247 },
|
||||
{ 0.0358458, -0.0761724, 0.9568845 },
|
||||
static const float p3_to_xyz[9] = {
|
||||
0.4865709, 0.2656677, 0.1982173,
|
||||
0.2289746, 0.6917385, 0.0792869,
|
||||
0.0000000, 0.0451134, 1.0439444,
|
||||
};
|
||||
|
||||
static const float xyz_to_p3[9] = {
|
||||
2.4934969, -0.9313836, -0.4027108,
|
||||
-0.8294890, 1.7626641, 0.0236247,
|
||||
0.0358458, -0.0761724, 0.9568845,
|
||||
};
|
||||
|
||||
/* premultiplied matrices for default conversions */
|
||||
|
||||
static const float rec2020_to_srgb[3][3] = {
|
||||
{ 1.660227, -0.587548, -0.072838 },
|
||||
{ -0.124553, 1.132926, -0.008350 },
|
||||
{ -0.018155, -0.100603, 1.118998 },
|
||||
static const float rec2020_to_srgb[9] = {
|
||||
1.660227, -0.587548, -0.072838,
|
||||
-0.124553, 1.132926, -0.008350,
|
||||
-0.018155, -0.100603, 1.118998,
|
||||
};
|
||||
|
||||
static const float srgb_to_rec2020[3][3] = {
|
||||
{ 0.627504, 0.329275, 0.043303 },
|
||||
{ 0.069108, 0.919519, 0.011360 },
|
||||
{ 0.016394, 0.088011, 0.895380 },
|
||||
static const float srgb_to_rec2020[9] = {
|
||||
0.627504, 0.329275, 0.043303,
|
||||
0.069108, 0.919519, 0.011360,
|
||||
0.016394, 0.088011, 0.895380,
|
||||
};
|
||||
|
@ -223,9 +223,9 @@ gdk_color_state_create_cicp_params (GdkColorState *self)
|
||||
/* {{{ Conversion functions */
|
||||
|
||||
typedef float (* GdkTransferFunc) (float v);
|
||||
typedef const float GdkColorMatrix[3][3];
|
||||
typedef const float GdkColorMatrix[9];
|
||||
|
||||
#define IDENTITY ((float**)0)
|
||||
#define IDENTITY ((float*)0)
|
||||
#define NONE ((GdkTransferFunc)0)
|
||||
|
||||
#define TRANSFORM(name, eotf, matrix, oetf) \
|
||||
@ -242,12 +242,12 @@ name (GdkColorState *self, \
|
||||
values[i][1] = eotf (values[i][1]); \
|
||||
values[i][2] = eotf (values[i][2]); \
|
||||
} \
|
||||
if ((float **)matrix != IDENTITY) \
|
||||
if (matrix != IDENTITY) \
|
||||
{ \
|
||||
float res[3]; \
|
||||
res[0] = matrix[0][0] * values[i][0] + matrix[0][1] * values[i][1] + matrix[0][2] * values[i][2]; \
|
||||
res[1] = matrix[1][0] * values[i][0] + matrix[1][1] * values[i][1] + matrix[1][2] * values[i][2]; \
|
||||
res[2] = matrix[2][0] * values[i][0] + matrix[2][1] * values[i][1] + matrix[2][2] * values[i][2]; \
|
||||
res[0] = matrix[0] * values[i][0] + matrix[1] * values[i][1] + matrix[2] * values[i][2]; \
|
||||
res[1] = matrix[3] * values[i][0] + matrix[4] * values[i][1] + matrix[5] * values[i][2]; \
|
||||
res[2] = matrix[6] * values[i][0] + matrix[7] * values[i][1] + matrix[8] * values[i][2]; \
|
||||
values[i][0] = res[0]; \
|
||||
values[i][1] = res[1]; \
|
||||
values[i][2] = res[2]; \
|
||||
@ -426,10 +426,10 @@ struct _GdkCicpColorState
|
||||
GdkTransferFunc eotf;
|
||||
GdkTransferFunc oetf;
|
||||
|
||||
float to_srgb[3][3];
|
||||
float to_rec2020[3][3];
|
||||
float from_srgb[3][3];
|
||||
float from_rec2020[3][3];
|
||||
float *to_srgb;
|
||||
float *to_rec2020;
|
||||
float *from_srgb;
|
||||
float *from_rec2020;
|
||||
|
||||
GdkCicp cicp;
|
||||
};
|
||||
@ -449,7 +449,8 @@ TRANSFORM(gdk_cicp_from_rec2100_linear, NONE, cicp->from_rec2020, cicp->o
|
||||
|
||||
#undef cicp
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
/* {{{ Vfuncs */
|
||||
|
||||
static void
|
||||
@ -460,6 +461,11 @@ gdk_cicp_color_state_free (GdkColorState *cs)
|
||||
if (self->no_srgb)
|
||||
gdk_color_state_unref (self->no_srgb);
|
||||
|
||||
g_free (self->to_srgb);
|
||||
g_free (self->to_rec2020);
|
||||
g_free (self->from_srgb);
|
||||
g_free (self->from_rec2020);
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
@ -549,7 +555,7 @@ gdk_cicp_color_state_get_cicp (GdkColorState *color_state)
|
||||
return &self->cicp;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
static const
|
||||
GdkColorStateClass GDK_CICP_COLOR_STATE_CLASS = {
|
||||
@ -562,19 +568,19 @@ GdkColorStateClass GDK_CICP_COLOR_STATE_CLASS = {
|
||||
.get_cicp = gdk_cicp_color_state_get_cicp,
|
||||
};
|
||||
|
||||
static inline void
|
||||
multiply (float res[3][3],
|
||||
const float m1[3][3],
|
||||
const float m2[3][3])
|
||||
static inline float *
|
||||
multiply (float res[9],
|
||||
const float m1[9],
|
||||
const float m2[9])
|
||||
{
|
||||
if ((float **) m1 == IDENTITY)
|
||||
memcpy (res, m2, sizeof (float) * 3 * 3);
|
||||
else if ((float **) m2 == IDENTITY)
|
||||
memcpy (res, m1, sizeof (float) * 3 * 3);
|
||||
else
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
res[i][j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] + m1[i][2] * m2[2][j];
|
||||
#define IDX(i,j) 3*i+j
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
res[IDX(i,j)] = m1[IDX(i,0)] * m2[IDX(0,j)]
|
||||
+ m1[IDX(i,1)] * m2[IDX(1,j)]
|
||||
+ m1[IDX(i,2)] * m2[IDX(2,j)];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
@ -663,8 +669,8 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
from_xyz = xyz_to_rec2020;
|
||||
break;
|
||||
case 10:
|
||||
to_xyz = IDENTITY;
|
||||
from_xyz = IDENTITY;
|
||||
to_xyz = identity;
|
||||
from_xyz = identity;
|
||||
break;
|
||||
case 12:
|
||||
to_xyz = p3_to_xyz;
|
||||
@ -693,10 +699,10 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
self->eotf = eotf;
|
||||
self->oetf = oetf;
|
||||
|
||||
multiply (self->to_srgb, xyz_to_srgb, to_xyz);
|
||||
multiply (self->to_rec2020, xyz_to_rec2020, to_xyz);
|
||||
multiply (self->from_srgb, from_xyz, srgb_to_xyz);
|
||||
multiply (self->from_rec2020, from_xyz, rec2020_to_xyz);
|
||||
self->to_srgb = multiply (g_new (float, 9), xyz_to_srgb, to_xyz);
|
||||
self->to_rec2020 = multiply (g_new (float, 9), xyz_to_rec2020, to_xyz);
|
||||
self->from_srgb = multiply (g_new (float, 9), from_xyz, srgb_to_xyz);
|
||||
self->from_rec2020 = multiply (g_new (float, 9), from_xyz, rec2020_to_xyz);
|
||||
|
||||
self->name = g_strdup_printf ("cicp-%u/%u/%u/%u",
|
||||
cicp->color_primaries,
|
||||
|
@ -78,31 +78,6 @@ output_message_handler (j_common_ptr cinfo)
|
||||
/* }}} */
|
||||
/* {{{ Format conversion */
|
||||
|
||||
static void
|
||||
convert_grayscale_to_rgb (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
guchar *dest, *src;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = data + width;
|
||||
dest = data + 3 * width;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
dest -= 3;
|
||||
src -= 1;
|
||||
dest[0] = *src;
|
||||
dest[1] = *src;
|
||||
dest[2] = *src;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_cmyk_to_rgba (guchar *data,
|
||||
int width,
|
||||
@ -184,6 +159,10 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
stride = width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_G8;
|
||||
break;
|
||||
case JCS_RGB:
|
||||
stride = 3 * width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
@ -217,20 +196,8 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
jpeg_read_scanlines (&info, row, 1);
|
||||
}
|
||||
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
convert_grayscale_to_rgb (data, width, height, stride);
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
break;
|
||||
case JCS_RGB:
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
convert_cmyk_to_rgba (data, width, height, stride);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
if (info.out_color_space == JCS_CMYK)
|
||||
convert_cmyk_to_rgba (data, width, height, stride);
|
||||
|
||||
jpeg_finish_decompress (&info);
|
||||
jpeg_destroy_decompress (&info);
|
||||
@ -307,6 +274,7 @@ gdk_save_jpeg (GdkTexture *texture)
|
||||
|
||||
gdk_texture_downloader_init (&downloader, texture);
|
||||
gdk_texture_downloader_set_format (&downloader, GDK_MEMORY_R8G8B8);
|
||||
gdk_texture_downloader_set_color_state (&downloader, GDK_COLOR_STATE_SRGB);
|
||||
texbytes = gdk_texture_downloader_download_bytes (&downloader, &texstride);
|
||||
gdk_texture_downloader_finish (&downloader);
|
||||
texdata = g_bytes_get_data (texbytes, NULL);
|
||||
|
@ -33,7 +33,7 @@ test_transfer (gconstpointer data)
|
||||
}
|
||||
}
|
||||
|
||||
typedef const float Matrix[3][3];
|
||||
typedef const float Matrix[9];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -50,59 +50,54 @@ static MatrixTest matrices[] = {
|
||||
{ "srgb<>rec2020", &rec2020_to_srgb, &srgb_to_rec2020 },
|
||||
};
|
||||
|
||||
#define IDX(i,j) 3*i+j
|
||||
static inline void
|
||||
multiply (float res[3][3],
|
||||
const float m1[3][3],
|
||||
const float m2[3][3])
|
||||
multiply (float res[9],
|
||||
const float m1[9],
|
||||
const float m2[9])
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
res[i][j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] + m1[i][2] * m2[2][j];
|
||||
res[IDX(i,j)] = m1[IDX(i,0)] * m2[IDX(0,j)]
|
||||
+ m1[IDX(i,1)] * m2[IDX(1,j)]
|
||||
+ m1[IDX(i,2)] * m2[IDX(2,j)];
|
||||
}
|
||||
|
||||
static inline void
|
||||
difference (float res[3][3],
|
||||
const float m1[3][3],
|
||||
const float m2[3][3])
|
||||
difference (float res[9],
|
||||
const float m1[9],
|
||||
const float m2[9])
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
res[i][j] = m1[i][j] - m2[i][j];
|
||||
for (int i = 0; i < 9; i++)
|
||||
res[i] = m1[i] - m2[i];
|
||||
}
|
||||
|
||||
static float
|
||||
norm (const float m[3][3])
|
||||
norm (const float m[9])
|
||||
{
|
||||
float sum = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
sum += m[i][j] * m[i][j];
|
||||
for (int i = 0; i < 9; i++)
|
||||
sum += m[i] * m[i];
|
||||
|
||||
return sqrtf (sum);
|
||||
}
|
||||
|
||||
static const float identity[3][3] = {
|
||||
{ 1, 0, 0 },
|
||||
{ 0, 1, 0 },
|
||||
{ 0, 0, 1 },
|
||||
};
|
||||
|
||||
static void
|
||||
print_matrix (const float m[3][3])
|
||||
print_matrix (const float m[9])
|
||||
{
|
||||
g_print ("%f %f %f\n%f %f %f\n%f %f %f\n",
|
||||
m[0][0], m[0][1], m[0][2],
|
||||
m[1][0], m[1][1], m[1][2],
|
||||
m[2][0], m[2][1], m[2][2]);
|
||||
m[0], m[1], m[2],
|
||||
m[3], m[4], m[5],
|
||||
m[6], m[7], m[8]);
|
||||
}
|
||||
|
||||
static void
|
||||
test_matrix (gconstpointer data)
|
||||
{
|
||||
MatrixTest *matrix = (MatrixTest *) data;
|
||||
float res[3][3];
|
||||
float res2[3][3];
|
||||
float res[9];
|
||||
float res2[9];
|
||||
|
||||
multiply (res, *matrix->to_xyz, *matrix->from_xyz);
|
||||
|
||||
@ -120,7 +115,7 @@ test_matrix (gconstpointer data)
|
||||
static void
|
||||
test_srgb_to_rec2020 (void)
|
||||
{
|
||||
float m[3][3], res[3][3];
|
||||
float m[9], res[9];
|
||||
|
||||
multiply (m, xyz_to_rec2020, srgb_to_xyz);
|
||||
difference (res, m, srgb_to_rec2020);
|
||||
@ -131,7 +126,7 @@ test_srgb_to_rec2020 (void)
|
||||
static void
|
||||
test_rec2020_to_srgb (void)
|
||||
{
|
||||
float m[3][3], res[3][3];
|
||||
float m[9], res[9];
|
||||
|
||||
multiply (m, xyz_to_srgb, rec2020_to_xyz);
|
||||
difference (res, m, rec2020_to_srgb);
|
||||
|
@ -81,15 +81,17 @@ do_convert (int *argc,
|
||||
char **filenames = NULL;
|
||||
char *format_name = NULL;
|
||||
char *colorstate_name = NULL;
|
||||
char *cicp_tuple = NULL;
|
||||
const GOptionEntry entries[] = {
|
||||
{ "format", 0, 0, G_OPTION_ARG_STRING, &format_name, N_("Format to use"), N_("FORMAT") },
|
||||
{ "color-state", 0, 0, G_OPTION_ARG_STRING, &colorstate_name, N_("Color state to use"), N_("COLORSTATE") },
|
||||
{ "cicp", 0, 0, G_OPTION_ARG_STRING, &cicp_tuple, N_("Color state to use, as cicp tuple"), N_("CICP") },
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, N_("FILE…") },
|
||||
{ NULL, }
|
||||
};
|
||||
GError *error = NULL;
|
||||
GdkMemoryFormat format = GDK_MEMORY_DEFAULT;
|
||||
GdkColorState *color_state = gdk_color_state_get_srgb ();
|
||||
GdkColorState *color_state = NULL;
|
||||
|
||||
g_set_prgname ("gtk4-image-tool convert");
|
||||
context = g_option_context_new (NULL);
|
||||
@ -151,6 +153,26 @@ do_convert (int *argc,
|
||||
}
|
||||
}
|
||||
|
||||
if (cicp_tuple)
|
||||
{
|
||||
if (color_state)
|
||||
{
|
||||
g_printerr (_("Can't specify both --color-state and --cicp\n"));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
color_state = parse_cicp_tuple (cicp_tuple, &error);
|
||||
|
||||
if (!color_state)
|
||||
{
|
||||
g_printerr (_("Not a supported cicp tuple: %s\n"), error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!color_state)
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
save_image (filenames[0], filenames[1], format, color_state);
|
||||
|
||||
g_strfreev (filenames);
|
||||
|
@ -79,13 +79,15 @@ do_relabel (int *argc,
|
||||
GOptionContext *context;
|
||||
char **filenames = NULL;
|
||||
char *colorstate_name = NULL;
|
||||
char *cicp_tuple = NULL;
|
||||
const GOptionEntry entries[] = {
|
||||
{ "color-state", 0, 0, G_OPTION_ARG_STRING, &colorstate_name, N_("Color state to use"), N_("COLORSTATE") },
|
||||
{ "cicp", 0, 0, G_OPTION_ARG_STRING, &cicp_tuple, N_("Color state to use, as cicp tuple"), N_("CICP") },
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, N_("FILE…") },
|
||||
{ NULL, }
|
||||
};
|
||||
GError *error = NULL;
|
||||
GdkColorState *color_state = gdk_color_state_get_srgb ();
|
||||
GdkColorState *color_state = NULL;
|
||||
|
||||
g_set_prgname ("gtk4-image-tool relabel");
|
||||
context = g_option_context_new (NULL);
|
||||
@ -131,6 +133,26 @@ do_relabel (int *argc,
|
||||
}
|
||||
}
|
||||
|
||||
if (cicp_tuple)
|
||||
{
|
||||
if (color_state)
|
||||
{
|
||||
g_printerr (_("Can't specify both --color-state and --cicp\n"));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
color_state = parse_cicp_tuple (cicp_tuple, &error);
|
||||
|
||||
if (!color_state)
|
||||
{
|
||||
g_printerr (_("Not a supported cicp tuple: %s\n"), error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!color_state)
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
relabel_image (filenames[0], filenames[1], color_state);
|
||||
|
||||
g_strfreev (filenames);
|
||||
|
@ -221,3 +221,42 @@ get_color_state_name (GdkColorState *color_state)
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
parse_cicp_tuple (const char *cicp_tuple,
|
||||
GError **error)
|
||||
{
|
||||
char **tokens;
|
||||
guint64 num[4];
|
||||
GdkCicpParams *params;
|
||||
GdkColorState *color_state;
|
||||
|
||||
tokens = g_strsplit (cicp_tuple, "/", 0);
|
||||
|
||||
if (g_strv_length (tokens) != 4 ||
|
||||
!g_ascii_string_to_unsigned (tokens[0], 10, 0, 255, &num[0], NULL) ||
|
||||
!g_ascii_string_to_unsigned (tokens[1], 10, 0, 255, &num[1], NULL) ||
|
||||
!g_ascii_string_to_unsigned (tokens[2], 10, 0, 255, &num[2], NULL) ||
|
||||
!g_ascii_string_to_unsigned (tokens[3], 10, 0, 255, &num[3], NULL))
|
||||
{
|
||||
g_strfreev (tokens);
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("cicp must be 4 numbers, separated by /\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_strfreev (tokens);
|
||||
|
||||
params = gdk_cicp_params_new ();
|
||||
|
||||
gdk_cicp_params_set_color_primaries (params, (guint) num[0]);
|
||||
gdk_cicp_params_set_transfer_function (params, (guint) num[1]);
|
||||
gdk_cicp_params_set_matrix_coefficients (params, (guint) num[2]);
|
||||
gdk_cicp_params_set_range (params, num[3] == 0 ? GDK_CICP_RANGE_NARROW : GDK_CICP_RANGE_FULL);
|
||||
color_state = gdk_cicp_params_build_color_state (params, error);
|
||||
|
||||
g_object_unref (params);
|
||||
|
||||
return color_state;
|
||||
}
|
||||
|
@ -17,3 +17,6 @@ GdkColorState * find_color_state_by_name (const char *name);
|
||||
|
||||
char ** get_color_state_names (void);
|
||||
char * get_color_state_name (GdkColorState *color_state);
|
||||
|
||||
GdkColorState *parse_cicp_tuple (const char *cicp_tuple,
|
||||
GError **error);
|
||||
|
Loading…
Reference in New Issue
Block a user