Commit 2c47261e authored by Paolo Bacchilega's avatar Paolo Bacchilega

color profile: use an object to store the transformation

parent 6693627d
......@@ -209,7 +209,7 @@ _cairo_image_surface_create_from_jpeg (GInputStream *istream,
orientation = GTH_TRANSFORM_NONE;
#if HAVE_LCMS2
if (jpeg_info.valid & _JPEG_INFO_ICC_PROFILE) {
GthICCData *profile = gth_icc_data_new (NULL, cmsOpenProfileFromMem (jpeg_info.icc_data, jpeg_info.icc_data_size));
GthICCProfile *profile = gth_icc_profile_new (GTH_ICC_PROFILE_ID_UNKNOWN, cmsOpenProfileFromMem (jpeg_info.icc_data, jpeg_info.icc_data_size));
gth_image_set_icc_profile (image, profile);
g_object_unref (profile);
}
......
......@@ -257,7 +257,7 @@ profile_ready_cb (GObject *source_object,
{
ProfileData *profile_data = user_data;
GthImageViewerPage *self = profile_data->self;
GthICCData *profile;
GthICCProfile *profile;
profile = gth_color_manager_get_profile_finish (GTH_COLOR_MANAGER (source_object), res, NULL);
if (profile == NULL)
......
......@@ -180,7 +180,7 @@ struct _GthBrowserPrivate {
gboolean file_properties_on_the_right;
GthSidebarState viewer_sidebar;
BrowserState state;
GthICCProfile screen_profile;
GthICCProfile *screen_profile;
GtkTreePath *folder_tree_last_dest_row; /* used to open a folder during D&D */
guint folder_tree_open_folder_id;
GtkWidget *apply_editor_changes_button;
......@@ -6951,7 +6951,7 @@ gth_browser_apply_editor_changes (GthBrowser *browser)
}
GthICCData *
GthICCProfile *
gth_browser_get_monitor_profile (GthBrowser *browser)
{
#if HAVE_LCMS2
......@@ -6976,13 +6976,13 @@ gth_browser_get_monitor_profile (GthBrowser *browser)
0, 64 * 1024 * 1024, FALSE,
&type, &format, &nitems, &data) && nitems > 0)
{
GthICCProfile profile;
GthCMSProfile cms_profile;
profile = cmsOpenProfileFromMem (data, nitems);
if (profile != NULL) {
char *filename = g_strdup_printf ("icc-profile://%d", monitor_num);
browser->priv->screen_profile = gth_icc_data_new (filename, profile);
g_free (filename);
cms_profile = (GthCMSProfile) cmsOpenProfileFromMem (data, nitems);
if (cms_profile != NULL) {
char *id = g_strdup_printf ("%s%d", GTH_ICC_PROFILE_FROM_PROPERTY, monitor_num);
browser->priv->screen_profile = gth_icc_profile_new (id, cms_profile);
g_free (id);
}
g_free (data);
......
......@@ -272,7 +272,7 @@ void gth_browser_ask_whether_to_save (GthBrowser *browser,
void gth_browser_save_state (GthBrowser *browser);
gboolean gth_browser_restore_state (GthBrowser *browser);
void gth_browser_apply_editor_changes (GthBrowser *browser);
GthICCData * gth_browser_get_monitor_profile (GthBrowser *browser);
GthICCProfile * gth_browser_get_monitor_profile (GthBrowser *browser);
GtkWidget * gth_browser_get_fullscreen_headerbar
(GthBrowser *browser);
void gth_browser_keep_mouse_visible (GthBrowser *browser,
......
......@@ -33,9 +33,9 @@
typedef struct {
GthICCData *in_profile;
GthICCData *out_profile;
GthICCTransform transform;
GthICCProfile *in_profile;
GthICCProfile *out_profile;
GthICCTransform *transform;
} TransformData;
......@@ -58,7 +58,7 @@ transform_data_free (TransformData *data)
{
_g_object_unref (data->in_profile);
_g_object_unref (data->out_profile);
gth_icc_transform_free (data->transform);
_g_object_unref (data->transform);
g_free (data);
}
......@@ -143,6 +143,19 @@ gth_color_manager_new (void)
}
static void
_gth_color_manager_add_profile (GthColorManager *self,
const char *id,
GthICCProfile *profile)
{
g_return_if_fail (self != NULL);
g_return_if_fail (id != NULL);
g_return_if_fail (profile != NULL);
g_hash_table_insert (self->priv->profile_cache, g_strdup (id), g_object_ref (profile));
}
#if HAVE_LCMS2 && HAVE_COLORD
......@@ -177,17 +190,17 @@ profile_buffer_ready_cb (void **buffer,
g_task_return_error (task, g_error_copy (error));
}
else {
ProfilesData *data = g_task_get_task_data (task);
char *filename;
GthICCData *icc_data;
ProfilesData *data = g_task_get_task_data (task);
char *uri;
GthICCProfile *profile;
filename = g_file_get_path (data->icc_file);
icc_data = gth_icc_data_new (filename, (GthICCProfile) cmsOpenProfileFromMem (*buffer, count));
gth_color_manager_add_profile (data->color_manager, data->cache_id, icc_data);
g_task_return_pointer (task, g_object_ref (icc_data), g_object_unref);
uri = g_file_get_uri (data->icc_file);
profile = gth_icc_profile_new (uri, (GthCMSProfile) cmsOpenProfileFromMem (*buffer, count));
_gth_color_manager_add_profile (data->color_manager, data->cache_id, profile);
g_task_return_pointer (task, g_object_ref (profile), g_object_unref);
g_object_unref (icc_data);
g_free (filename);
g_object_unref (profile);
g_free (uri);
}
g_object_unref (task);
......@@ -308,6 +321,20 @@ cd_client_connected_cb (GObject *source_object,
#endif /* HAVE_LCMS2 && HAVE_COLORD */
static GthICCProfile *
_gth_color_manager_get_profile (GthColorManager *self,
const char *id)
{
GthICCProfile *profile;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (id != NULL, NULL);
profile = g_hash_table_lookup (self->priv->profile_cache, id);
return _g_object_ref (profile);
}
void
gth_color_manager_get_profile_async (GthColorManager *self,
char *monitor_name,
......@@ -322,12 +349,12 @@ gth_color_manager_get_profile_async (GthColorManager *self,
#if HAVE_LCMS2
{
char *id;
GthICCData *profile;
ProfilesData *data;
char *id;
GthICCProfile *profile;
ProfilesData *data;
id = g_strdup_printf ("monitor://%s", monitor_name);
profile = gth_color_manager_get_profile (self, id);
profile = _gth_color_manager_get_profile (self, id);
if (profile != NULL) {
g_task_return_pointer (task, g_object_ref (profile), g_object_unref);
g_object_unref (task);
......@@ -373,7 +400,7 @@ gth_color_manager_get_profile_async (GthColorManager *self,
}
GthICCData *
GthICCProfile *
gth_color_manager_get_profile_finish (GthColorManager *self,
GAsyncResult *result,
GError **error)
......@@ -383,99 +410,43 @@ gth_color_manager_get_profile_finish (GthColorManager *self,
}
void
gth_color_manager_add_profile (GthColorManager *self,
const char *id,
GthICCData *profile)
{
g_return_if_fail (self != NULL);
g_return_if_fail (id != NULL);
g_return_if_fail (profile != NULL);
g_hash_table_insert (self->priv->profile_cache, g_strdup (id), g_object_ref (profile));
}
GthICCData *
gth_color_manager_get_profile (GthColorManager *self,
const char *id)
{
GthICCData *profile;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (id != NULL, NULL);
profile = g_hash_table_lookup (self->priv->profile_cache, id);
return _g_object_ref (profile);
}
#if HAVE_LCMS2
#if G_BYTE_ORDER == G_LITTLE_ENDIAN /* BGRA */
#define _LCMS2_CAIRO_FORMAT TYPE_BGRA_8
#elif G_BYTE_ORDER == G_BIG_ENDIAN /* ARGB */
#define _LCMS2_CAIRO_FORMAT TYPE_ARGB_8
#else
#define _LCMS2_CAIRO_FORMAT TYPE_ABGR_8
#endif
#endif
static char *
create_transform_id (GthICCData *from_profile,
GthICCData *to_profile)
create_transform_id_for_cache (GthICCProfile *from_profile,
GthICCProfile *to_profile)
{
const char *from_filename = gth_icc_data_get_filename (from_profile);
const char *to_filename = gth_icc_data_get_filename (to_profile);
const char *from_id = gth_icc_profile_get_id (from_profile);
const char *to_id = gth_icc_profile_get_id (to_profile);
if ((g_strcmp0 (from_filename, "") != 0) && (g_strcmp0 (to_filename, "") != 0))
return g_strdup_printf ("%s -> %s", from_filename, to_filename);
else
return NULL;
}
g_print (" -> gth_color_manager_get_transform: %s -> %s\n", from_id, to_id);
if (gth_icc_profile_id_is_unknown (from_id) || gth_icc_profile_id_is_unknown (to_id))
return NULL;
GthICCTransform
gth_color_manager_create_transform (GthColorManager *self,
GthICCData *from_profile,
GthICCData *to_profile)
{
#if HAVE_LCMS2
g_print ("gth_color_manager_create_transform (%p, %p)\n", gth_icc_data_get_profile (from_profile), gth_icc_data_get_profile (to_profile));
return (GthICCTransform) cmsCreateTransform ((cmsHPROFILE) gth_icc_data_get_profile (from_profile),
_LCMS2_CAIRO_FORMAT,
(cmsHPROFILE) gth_icc_data_get_profile (to_profile),
_LCMS2_CAIRO_FORMAT,
INTENT_PERCEPTUAL,
0);
#else
return NULL;
#endif
return g_strdup_printf ("%s -> %s", from_id, to_id);
}
GthICCTransform
GthICCTransform *
gth_color_manager_get_transform (GthColorManager *self,
GthICCData *from_profile,
GthICCData *to_profile)
GthICCProfile *in_profile,
GthICCProfile *out_profile)
{
#if HAVE_LCMS2
GthICCTransform transform = NULL;
GthICCTransform *transform = NULL;
char *transform_id;
g_return_val_if_fail (self != NULL, NULL);
transform_id = create_transform_id (from_profile, to_profile);
transform_id = create_transform_id_for_cache (in_profile, out_profile);
if (transform_id != NULL) {
TransformData *transform_data = g_hash_table_lookup (self->priv->transform_cache, transform_id);
if (transform_data == NULL) {
transform_data = transform_data_new ();
transform_data->in_profile = g_object_ref (from_profile);
transform_data->out_profile = g_object_ref (to_profile);
transform_data->transform = gth_color_manager_create_transform (self, transform_data->in_profile, transform_data->out_profile);
transform_data->in_profile = g_object_ref (in_profile);
transform_data->out_profile = g_object_ref (out_profile);
transform_data->transform = gth_icc_transform_new_from_profiles (transform_data->in_profile, transform_data->out_profile);
if (transform_data->transform != NULL) {
g_hash_table_insert (self->priv->transform_cache, g_strdup (transform_id), transform_data);
......@@ -487,14 +458,18 @@ gth_color_manager_get_transform (GthColorManager *self,
}
if (transform_data != NULL)
transform = transform_data->transform;
transform = g_object_ref (transform_data->transform);
g_free (transform_id);
}
else
transform = gth_icc_transform_new_from_profiles (in_profile, out_profile);
return transform;
#endif
#else
return NULL;
#endif
}
......@@ -59,20 +59,12 @@ void gth_color_manager_get_profile_async (GthColorManager *color_manager,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GthICCData * gth_color_manager_get_profile_finish (GthColorManager *color_manager,
GthICCProfile * gth_color_manager_get_profile_finish (GthColorManager *color_manager,
GAsyncResult *result,
GError **error);
void gth_color_manager_add_profile (GthColorManager *color_manager,
const char *id,
GthICCData *profile);
GthICCData * gth_color_manager_get_profile (GthColorManager *color_manager,
const char *id);
GthICCTransform gth_color_manager_create_transform (GthColorManager *self,
GthICCData *from_profile,
GthICCData *to_profile);
GthICCTransform gth_color_manager_get_transform (GthColorManager *color_manager,
GthICCData *from_profile,
GthICCData *to_profile);
GthICCTransform * gth_color_manager_get_transform (GthColorManager *color_manager,
GthICCProfile *from_profile,
GthICCProfile *to_profile);
G_END_DECLS
......
......@@ -28,67 +28,87 @@
#include "gth-icc-profile.h"
struct _GthICCDataPrivate {
GthICCProfile icc_profile;
char *filename;
struct _GthICCProfilePrivate {
GthCMSProfile cms_profile;
char *id;
};
G_DEFINE_TYPE (GthICCData, gth_icc_data, G_TYPE_OBJECT)
struct _GthICCTransformPrivate {
GthCMSTransform cms_transform;
};
G_DEFINE_TYPE (GthICCProfile, gth_icc_profile, G_TYPE_OBJECT)
G_DEFINE_TYPE (GthICCTransform, gth_icc_transform, G_TYPE_OBJECT)
void
gth_cms_profile_free (GthCMSProfile profile)
{
#ifdef HAVE_LCMS2
if (profile != NULL)
cmsCloseProfile ((cmsHPROFILE) profile);
#endif
}
void
gth_cms_transform_free (GthCMSTransform transform)
{
#ifdef HAVE_LCMS2
if (transform != NULL)
cmsDeleteTransform ((cmsHTRANSFORM) transform);
#endif
}
/* -- GthICCProfile -- */
static void
gth_icc_data_finalize (GObject *object)
gth_icc_profile_finalize (GObject *object)
{
GthICCData *icc_data;
GthICCProfile *icc_profile;
g_return_if_fail (object != NULL);
g_return_if_fail (GTH_IS_ICC_DATA (object));
g_return_if_fail (GTH_IS_ICC_PROFILE (object));
icc_data = GTH_ICC_DATA (object);
gth_icc_profile_free (icc_data->priv->icc_profile);
g_free (icc_data->priv->filename);
icc_profile = GTH_ICC_PROFILE (object);
gth_cms_profile_free (icc_profile->priv->cms_profile);
g_free (icc_profile->priv->id);
/* Chain up */
G_OBJECT_CLASS (gth_icc_data_parent_class)->finalize (object);
G_OBJECT_CLASS (gth_icc_profile_parent_class)->finalize (object);
}
static void
gth_icc_data_class_init (GthICCDataClass *klass)
gth_icc_profile_class_init (GthICCProfileClass *klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GthICCDataPrivate));
g_type_class_add_private (klass, sizeof (GthICCProfilePrivate));
gobject_class = (GObjectClass*) klass;
gobject_class->finalize = gth_icc_data_finalize;
gobject_class->finalize = gth_icc_profile_finalize;
}
static void
gth_icc_data_init (GthICCData *self)
gth_icc_profile_init (GthICCProfile *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_ICC_DATA, GthICCDataPrivate);
self->priv->icc_profile = NULL;
self->priv->filename = NULL;
}
void
gth_icc_profile_free (GthICCProfile icc_profile)
{
#ifdef HAVE_LCMS2
if (icc_profile != NULL)
cmsCloseProfile ((cmsHPROFILE) icc_profile);
#endif
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_ICC_PROFILE, GthICCProfilePrivate);
self->priv->cms_profile = NULL;
self->priv->id = NULL;
}
static char *
gth_icc_profile_get_id (GthICCProfile icc_profile)
_gth_cms_profile_create_id (GthCMSProfile cms_profile)
{
GString *str;
GString *str;
gboolean id_set = FALSE;
str = g_string_new ("");
......@@ -103,7 +123,7 @@ gth_icc_profile_get_id (GthICCProfile icc_profile)
gchar *md5 = NULL;
guint i;
cmsGetHeaderProfileID ((cmsHPROFILE) icc_profile, icc_id);
cmsGetHeaderProfileID ((cmsHPROFILE) cms_profile, icc_id);
for (i = 0; i < 16; i++) {
if (icc_id[i] != 0) {
md5_precooked = TRUE;
......@@ -118,62 +138,162 @@ gth_icc_profile_get_id (GthICCProfile icc_profile)
}
if (md5 != NULL) {
g_string_append (str, "md5://");
g_string_append (str, GTH_ICC_PROFILE_WITH_MD5);
g_string_append (str, md5);
id_set = TRUE;
}
}
#endif
return g_string_free (str, FALSE);
}
if (! id_set)
g_string_append (str, GTH_ICC_PROFILE_ID_UNKNOWN);
void
gth_icc_transform_free (GthICCTransform transform)
{
#ifdef HAVE_LCMS2
if (transform != NULL)
cmsDeleteTransform ((cmsHTRANSFORM) transform);
#endif
return g_string_free (str, FALSE);
}
GthICCData *
gth_icc_data_new (const char *filename,
GthICCProfile profile)
GthICCProfile *
gth_icc_profile_new (const char *id,
GthCMSProfile profile)
{
GthICCData *icc_data;
GthICCProfile *icc_profile;
icc_data = g_object_new (GTH_TYPE_ICC_DATA, NULL);
if (filename != NULL)
icc_data->priv->filename = g_strdup (filename);
icc_profile = g_object_new (GTH_TYPE_ICC_PROFILE, NULL);
if (! gth_icc_profile_id_is_unknown (id))
icc_profile->priv->id = g_strdup (id);
else
icc_data->priv->filename = gth_icc_profile_get_id (profile);
icc_data->priv->icc_profile = profile;
icc_profile->priv->id = _gth_cms_profile_create_id (profile);
icc_profile->priv->cms_profile = profile;
return icc_data;
return icc_profile;
}
const char *
gth_icc_data_get_filename (GthICCData *self)
gth_icc_profile_get_id (GthICCProfile *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->priv->filename;
return self->priv->id;
}
GthICCProfile
gth_icc_data_get_profile (GthICCData *self)
gboolean
gth_icc_profile_id_is_unknown (const char *id)
{
return (id == NULL) || (g_strcmp0 (id, GTH_ICC_PROFILE_ID_UNKNOWN) == 0);
}
GthCMSProfile
gth_icc_profile_get_profile (GthICCProfile *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->priv->icc_profile;
return self->priv->cms_profile;
}
gboolean
gth_icc_data_equal (GthICCData *a,
GthICCData *b)
gth_icc_profile_equal (GthICCProfile *a,
GthICCProfile *b)
{
g_return_val_if_fail ((a == NULL) || (b == NULL), NULL);
return g_strcmp0 (a->priv->filename, b->priv->filename) == 0;
if (gth_icc_profile_id_is_unknown (a->priv->id) || gth_icc_profile_id_is_unknown (b->priv->id))
return FALSE;
else
return g_strcmp0 (a->priv->id, b->priv->id) == 0;
}
/* -- GthICCTransform -- */
static void
gth_icc_transform_finalize (GObject *object)
{
GthICCTransform *icc_transform;
g_return_if_fail (object != NULL);
g_return_if_fail (GTH_IS_ICC_TRANSFORM (object));
icc_transform = GTH_ICC_TRANSFORM (object);
gth_cms_transform_free (icc_transform->priv->cms_transform);
/* Chain up */
G_OBJECT_CLASS (gth_icc_transform_parent_class)->finalize (object);
}
static void
gth_icc_transform_class_init (GthICCTransformClass *klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (GthICCTransformPrivate));
gobject_class = (GObjectClass*) klass;
gobject_class->finalize = gth_icc_transform_finalize;
}
static void
gth_icc_transform_init (GthICCTransform *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_ICC_TRANSFORM, GthICCTransformPrivate);
self->priv->cms_transform = NULL;
}
GthICCTransform *
gth_icc_transform_new (GthCMSTransform transform)
{
GthICCTransform *icc_transform;
icc_transform = g_object_new (GTH_TYPE_ICC_TRANSFORM, NULL);
icc_transform->priv->cms_transform = transform;