2014-02-06 22:53:37 +08:00
|
|
|
|
/* LIBGIMP - The GIMP Library
|
|
|
|
|
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
|
|
|
|
*
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimpcolorprofile.c
|
2014-02-06 22:53:37 +08:00
|
|
|
|
* Copyright (C) 2014 Michael Natterer <mitch@gimp.org>
|
|
|
|
|
* Elle Stone <ellestone@ninedegreesbelow.com>
|
|
|
|
|
*
|
|
|
|
|
* This library 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
|
|
|
|
|
* version 3 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Library General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library. If not, see
|
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
2014-03-29 17:40:47 +08:00
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2014-02-06 22:53:37 +08:00
|
|
|
|
#include <lcms2.h>
|
|
|
|
|
|
2014-03-14 08:44:27 +08:00
|
|
|
|
#include <gio/gio.h>
|
2014-02-06 22:53:37 +08:00
|
|
|
|
#include <gegl.h>
|
|
|
|
|
|
2014-03-14 08:44:27 +08:00
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
|
|
|
|
2014-02-06 22:53:37 +08:00
|
|
|
|
#include "gimpcolortypes.h"
|
|
|
|
|
|
2015-06-03 15:41:23 +08:00
|
|
|
|
#include "gimpcolorprofile.h"
|
2014-02-06 22:53:37 +08:00
|
|
|
|
|
2014-03-16 07:06:31 +08:00
|
|
|
|
#include "libgimp/libgimp-intl.h"
|
|
|
|
|
|
2014-02-06 22:53:37 +08:00
|
|
|
|
|
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* SECTION: gimpcolorprofile
|
|
|
|
|
* @title: GimpColorProfile
|
2014-02-06 22:53:37 +08:00
|
|
|
|
* @short_description: Definitions and Functions relating to LCMS.
|
|
|
|
|
*
|
|
|
|
|
* Definitions and Functions relating to LCMS.
|
|
|
|
|
**/
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
|
|
|
|
* GimpColorProfile:
|
|
|
|
|
*
|
|
|
|
|
* Simply a typedef to #gpointer, but actually is a cmsHPROFILE. It's
|
|
|
|
|
* used in public GIMP APIs in order to avoid having to include LCMS
|
|
|
|
|
* headers.
|
|
|
|
|
**/
|
|
|
|
|
|
2014-04-11 02:41:32 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
struct _GimpColorProfilePrivate
|
|
|
|
|
{
|
|
|
|
|
cmsHPROFILE lcms_profile;
|
|
|
|
|
guint8 *data;
|
|
|
|
|
gsize length;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void gimp_color_profile_finalize (GObject *object);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (GimpColorProfile, gimp_color_profile,
|
|
|
|
|
G_TYPE_OBJECT);
|
|
|
|
|
|
|
|
|
|
#define parent_class gimp_color_profile_parent_class
|
|
|
|
|
|
|
|
|
|
|
2014-03-16 07:06:31 +08:00
|
|
|
|
static GQuark
|
2015-06-03 15:41:23 +08:00
|
|
|
|
gimp_color_profile_error_quark (void)
|
2014-03-16 07:06:31 +08:00
|
|
|
|
{
|
|
|
|
|
static GQuark quark = 0;
|
|
|
|
|
|
|
|
|
|
if (G_UNLIKELY (quark == 0))
|
2015-06-03 15:41:23 +08:00
|
|
|
|
quark = g_quark_from_static_string ("gimp-color-profile-error-quark");
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
|
|
|
|
return quark;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
static void
|
|
|
|
|
gimp_color_profile_class_init (GimpColorProfileClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
object_class->finalize = gimp_color_profile_finalize;
|
|
|
|
|
|
|
|
|
|
g_type_class_add_private (klass, sizeof (GimpColorProfilePrivate));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_color_profile_init (GimpColorProfile *profile)
|
|
|
|
|
{
|
|
|
|
|
profile->priv = G_TYPE_INSTANCE_GET_PRIVATE (profile,
|
|
|
|
|
GIMP_TYPE_COLOR_PROFILE,
|
|
|
|
|
GimpColorProfilePrivate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_color_profile_finalize (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
GimpColorProfile *profile = GIMP_COLOR_PROFILE (object);
|
|
|
|
|
|
|
|
|
|
if (profile->priv->lcms_profile)
|
|
|
|
|
{
|
|
|
|
|
cmsCloseProfile (profile->priv->lcms_profile);
|
|
|
|
|
profile->priv->lcms_profile = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (profile->priv->data)
|
|
|
|
|
{
|
|
|
|
|
g_free (profile->priv->data);
|
|
|
|
|
profile->priv->data = NULL;
|
|
|
|
|
profile->priv->length = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* gimp_color_profile_new_from_file:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @file: a #GFile
|
|
|
|
|
* @error: return location for #GError
|
|
|
|
|
*
|
|
|
|
|
* This function opens an ICC color profile from @file.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the #GimpColorProfile, or %NULL. On error, %NULL is
|
|
|
|
|
* returned and @error is set.
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2015-07-11 04:43:53 +08:00
|
|
|
|
GimpColorProfile *
|
|
|
|
|
gimp_color_profile_new_from_file (GFile *file,
|
|
|
|
|
GError **error)
|
2014-03-16 07:06:31 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
GimpColorProfile *profile = NULL;
|
|
|
|
|
cmsHPROFILE lcms_profile = NULL;
|
|
|
|
|
guint8 *data = NULL;
|
|
|
|
|
gsize length = 0;
|
2014-07-05 05:57:27 +08:00
|
|
|
|
gchar *path;
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
2014-07-05 05:57:27 +08:00
|
|
|
|
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
2014-03-16 07:06:31 +08:00
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
|
|
|
|
2014-07-05 05:57:27 +08:00
|
|
|
|
path = g_file_get_path (file);
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
2014-07-05 05:57:27 +08:00
|
|
|
|
if (path)
|
|
|
|
|
{
|
|
|
|
|
GMappedFile *mapped;
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
2014-07-05 05:57:27 +08:00
|
|
|
|
mapped = g_mapped_file_new (path, FALSE, error);
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
2014-07-05 05:57:27 +08:00
|
|
|
|
if (! mapped)
|
|
|
|
|
return NULL;
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
2014-07-05 05:57:27 +08:00
|
|
|
|
length = g_mapped_file_get_length (mapped);
|
2015-07-11 04:43:53 +08:00
|
|
|
|
data = g_memdup (g_mapped_file_get_contents (mapped), length);
|
2014-07-05 05:57:27 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
lcms_profile = cmsOpenProfileFromMem (data, length);
|
2014-07-05 05:57:27 +08:00
|
|
|
|
|
|
|
|
|
g_mapped_file_unref (mapped);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GFileInfo *info;
|
|
|
|
|
|
|
|
|
|
info = g_file_query_info (file,
|
|
|
|
|
G_FILE_ATTRIBUTE_STANDARD_SIZE,
|
|
|
|
|
G_FILE_QUERY_INFO_NONE,
|
|
|
|
|
NULL, error);
|
|
|
|
|
if (info)
|
|
|
|
|
{
|
|
|
|
|
GInputStream *input;
|
2015-07-11 04:43:53 +08:00
|
|
|
|
|
|
|
|
|
length = g_file_info_get_size (info);
|
|
|
|
|
data = g_malloc (length);
|
2014-07-05 05:57:27 +08:00
|
|
|
|
|
|
|
|
|
g_object_unref (info);
|
|
|
|
|
|
|
|
|
|
input = G_INPUT_STREAM (g_file_read (file, NULL, error));
|
|
|
|
|
|
|
|
|
|
if (input)
|
|
|
|
|
{
|
|
|
|
|
gsize bytes_read;
|
|
|
|
|
|
|
|
|
|
if (g_input_stream_read_all (input, data, length,
|
|
|
|
|
&bytes_read, NULL, error) &&
|
|
|
|
|
bytes_read == length)
|
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
lcms_profile = cmsOpenProfileFromMem (data, length);
|
2014-07-05 05:57:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_object_unref (input);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
if (lcms_profile)
|
|
|
|
|
{
|
|
|
|
|
profile = g_object_new (GIMP_TYPE_COLOR_PROFILE, NULL);
|
|
|
|
|
|
|
|
|
|
profile->priv->lcms_profile = lcms_profile;
|
|
|
|
|
profile->priv->data = data;
|
|
|
|
|
profile->priv->length = length;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (data)
|
|
|
|
|
g_free (data);
|
|
|
|
|
|
|
|
|
|
if (error && *error == NULL)
|
|
|
|
|
{
|
|
|
|
|
g_set_error (error, gimp_color_profile_error_quark (), 0,
|
|
|
|
|
_("'%s' does not appear to be an ICC color profile"),
|
|
|
|
|
gimp_file_get_utf8_name (file));
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
|
|
|
|
return profile;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* gimp_color_profile_new_from_icc_profile:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @data: pointer to memory containing an ICC profile
|
|
|
|
|
* @length: lenght of the profile in memory, in bytes
|
|
|
|
|
* @error: return location for #GError
|
|
|
|
|
*
|
|
|
|
|
* This function opens an ICC color profile from memory. On error,
|
|
|
|
|
* %NULL is returned and @error is set.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the #GimpColorProfile, or %NULL.
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2015-07-11 04:43:53 +08:00
|
|
|
|
GimpColorProfile *
|
|
|
|
|
gimp_color_profile_new_from_icc_profile (const guint8 *data,
|
|
|
|
|
gsize length,
|
|
|
|
|
GError **error)
|
2014-03-16 07:06:31 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
cmsHPROFILE lcms_profile;
|
|
|
|
|
GimpColorProfile *profile = NULL;
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (data != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (length > 0, NULL);
|
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
lcms_profile = cmsOpenProfileFromMem (data, length);
|
|
|
|
|
|
|
|
|
|
if (lcms_profile)
|
|
|
|
|
{
|
|
|
|
|
profile = g_object_new (GIMP_TYPE_COLOR_PROFILE, NULL);
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
profile->priv->lcms_profile = lcms_profile;
|
|
|
|
|
profile->priv->data = g_memdup (data, length);
|
|
|
|
|
profile->priv->length = length;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g_set_error_literal (error, gimp_color_profile_error_quark (), 0,
|
|
|
|
|
_("Data does not appear to be an ICC color profile"));
|
|
|
|
|
}
|
2014-03-16 07:06:31 +08:00
|
|
|
|
|
|
|
|
|
return profile;
|
|
|
|
|
}
|
2014-02-06 22:53:37 +08:00
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* gimp_color_profile_new_from_lcms_profile:
|
|
|
|
|
* @lcms_profile: an LCMS cmsHPROFILE pointer
|
|
|
|
|
* @error: return location for #GError
|
2015-05-07 08:00:33 +08:00
|
|
|
|
*
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* This function creates a GimpColorProfile from a cmsHPROFILE. On
|
|
|
|
|
* error, %NULL is returned and @error is set. The passed
|
|
|
|
|
* @lcms_profile pointer is not retained by the created
|
|
|
|
|
* #GimpColorProfile.
|
2015-05-07 08:00:33 +08:00
|
|
|
|
*
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* Return value: the #GimpColorProfile, or %NULL.
|
2015-05-07 08:00:33 +08:00
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2015-07-11 04:43:53 +08:00
|
|
|
|
GimpColorProfile *
|
|
|
|
|
gimp_color_profile_new_from_lcms_profile (gpointer lcms_profile,
|
|
|
|
|
GError **error)
|
2014-04-10 22:30:04 +08:00
|
|
|
|
{
|
|
|
|
|
cmsUInt32Number size;
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_return_val_if_fail (lcms_profile != NULL, NULL);
|
2014-04-10 22:30:04 +08:00
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
if (cmsSaveProfileToMem (lcms_profile, NULL, &size))
|
2014-04-10 22:30:04 +08:00
|
|
|
|
{
|
|
|
|
|
guint8 *data = g_malloc (size);
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
if (cmsSaveProfileToMem (lcms_profile, data, &size))
|
2014-04-10 22:30:04 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gsize length = size;
|
|
|
|
|
|
|
|
|
|
lcms_profile = cmsOpenProfileFromMem (data, length);
|
|
|
|
|
|
|
|
|
|
if (lcms_profile)
|
|
|
|
|
{
|
|
|
|
|
GimpColorProfile *profile;
|
|
|
|
|
|
|
|
|
|
profile = g_object_new (GIMP_TYPE_COLOR_PROFILE, NULL);
|
2014-04-10 22:30:04 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
profile->priv->lcms_profile = lcms_profile;
|
|
|
|
|
profile->priv->data = data;
|
|
|
|
|
profile->priv->length = length;
|
|
|
|
|
|
|
|
|
|
return profile;
|
|
|
|
|
}
|
2014-04-10 22:30:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-03 15:41:23 +08:00
|
|
|
|
g_set_error_literal (error, gimp_color_profile_error_quark (), 0,
|
2014-04-10 22:30:04 +08:00
|
|
|
|
_("Could not save color profile to memory"));
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* gimp_color_profile_get_icc_profile:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* @length: return location for the number of bytes
|
|
|
|
|
* @error: return location for #GError
|
2015-05-07 08:00:33 +08:00
|
|
|
|
*
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* This function returns @profile as ICC profile data. The returned
|
|
|
|
|
* memory belongs to @profile and must not be modified or freed.
|
|
|
|
|
*
|
|
|
|
|
* Return value: a pointer to the IIC profile data.
|
2015-05-07 08:00:33 +08:00
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2015-07-11 04:43:53 +08:00
|
|
|
|
const guint8 *
|
|
|
|
|
gimp_color_profile_get_icc_profile (GimpColorProfile *profile,
|
|
|
|
|
gsize *length)
|
2015-05-06 22:28:45 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), NULL);
|
|
|
|
|
g_return_val_if_fail (length != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
*length = profile->priv->length;
|
2015-05-06 22:28:45 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
return profile->priv->data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gimp_color_profile_get_lcms_profile:
|
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* This function returns @profile's cmsHPROFILE. The returned
|
|
|
|
|
* value belongs to @profile and must not be modified or freed.
|
|
|
|
|
*
|
|
|
|
|
* Return value: a pointer to the cmsHPROFILE.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.10
|
|
|
|
|
**/
|
|
|
|
|
gpointer
|
|
|
|
|
gimp_color_profile_get_lcms_profile (GimpColorProfile *profile)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), NULL);
|
|
|
|
|
|
|
|
|
|
return profile->priv->lcms_profile;
|
2015-05-06 22:28:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-15 01:37:07 +08:00
|
|
|
|
static gchar *
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_get_info (GimpColorProfile *profile,
|
|
|
|
|
cmsInfoType info)
|
2014-03-14 08:44:27 +08:00
|
|
|
|
{
|
|
|
|
|
cmsUInt32Number size;
|
2014-03-15 01:37:07 +08:00
|
|
|
|
gchar *text = NULL;
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), NULL);
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
size = cmsGetProfileInfoASCII (profile->priv->lcms_profile, info,
|
2014-03-14 08:44:27 +08:00
|
|
|
|
"en", "US", NULL, 0);
|
|
|
|
|
if (size > 0)
|
|
|
|
|
{
|
|
|
|
|
gchar *data = g_new (gchar, size + 1);
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
size = cmsGetProfileInfoASCII (profile->priv->lcms_profile, info,
|
2014-03-14 08:44:27 +08:00
|
|
|
|
"en", "US", data, size);
|
|
|
|
|
if (size > 0)
|
2014-03-15 01:37:07 +08:00
|
|
|
|
text = gimp_any_to_utf8 (data, -1, NULL);
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-15 01:37:07 +08:00
|
|
|
|
return text;
|
2014-03-14 08:44:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_get_description:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* Return value: a newly allocated string containing @profile's
|
|
|
|
|
* description. Free with g_free().
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-14 08:44:27 +08:00
|
|
|
|
gchar *
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_get_description (GimpColorProfile *profile)
|
2014-03-14 08:44:27 +08:00
|
|
|
|
{
|
2015-06-03 15:41:23 +08:00
|
|
|
|
return gimp_color_profile_get_info (profile, cmsInfoDescription);
|
2014-03-15 01:37:07 +08:00
|
|
|
|
}
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_get_manufacturer:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* Return value: a newly allocated string containing @profile's
|
|
|
|
|
* manufacturer. Free with g_free().
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-15 01:37:07 +08:00
|
|
|
|
gchar *
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_get_manufacturer (GimpColorProfile *profile)
|
2014-03-15 01:37:07 +08:00
|
|
|
|
{
|
2015-06-03 15:41:23 +08:00
|
|
|
|
return gimp_color_profile_get_info (profile, cmsInfoManufacturer);
|
2014-03-15 01:37:07 +08:00
|
|
|
|
}
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_get_model:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* Return value: a newly allocated string containing @profile's
|
|
|
|
|
* model. Free with g_free().
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-15 01:37:07 +08:00
|
|
|
|
gchar *
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_get_model (GimpColorProfile *profile)
|
2014-03-15 01:37:07 +08:00
|
|
|
|
{
|
2015-06-03 15:41:23 +08:00
|
|
|
|
return gimp_color_profile_get_info (profile, cmsInfoModel);
|
2014-03-15 01:37:07 +08:00
|
|
|
|
}
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_get_copyright:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* Return value: a newly allocated string containing @profile's
|
|
|
|
|
* copyright. Free with g_free().
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-15 01:37:07 +08:00
|
|
|
|
gchar *
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_get_copyright (GimpColorProfile *profile)
|
2014-03-15 01:37:07 +08:00
|
|
|
|
{
|
2015-06-03 15:41:23 +08:00
|
|
|
|
return gimp_color_profile_get_info (profile, cmsInfoCopyright);
|
2014-03-14 08:44:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_get_label:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* This function returns a newly allocated string containing
|
|
|
|
|
* @profile's "title", a string that can be used to label the profile
|
|
|
|
|
* in a user interface.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the @profile's label. Free with g_free().
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-30 09:12:42 +08:00
|
|
|
|
gchar *
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_get_label (GimpColorProfile *profile)
|
2014-03-30 09:12:42 +08:00
|
|
|
|
{
|
|
|
|
|
gchar *label;
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), NULL);
|
2014-03-30 09:12:42 +08:00
|
|
|
|
|
2015-06-03 15:41:23 +08:00
|
|
|
|
label = gimp_color_profile_get_description (profile);
|
2014-03-30 09:12:42 +08:00
|
|
|
|
|
|
|
|
|
if (label && ! strlen (label))
|
|
|
|
|
{
|
|
|
|
|
g_free (label);
|
|
|
|
|
label = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! label)
|
2015-06-03 15:41:23 +08:00
|
|
|
|
label = gimp_color_profile_get_model (profile);
|
2014-03-30 09:12:42 +08:00
|
|
|
|
|
|
|
|
|
if (label && ! strlen (label))
|
|
|
|
|
{
|
|
|
|
|
g_free (label);
|
|
|
|
|
label = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! label)
|
|
|
|
|
label = g_strdup (_("(unnamed profile)"));
|
|
|
|
|
|
|
|
|
|
return label;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_get_summary:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* This function return a newly allocated string containing a
|
|
|
|
|
* multi-line summary of @profile's description, model, manufacturer
|
|
|
|
|
* and copyright, to be used as detailled information about the
|
|
|
|
|
* prpfile in a user interface.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the @profile's summary. Free with g_free().
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-14 08:44:27 +08:00
|
|
|
|
gchar *
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_get_summary (GimpColorProfile *profile)
|
2014-03-14 08:44:27 +08:00
|
|
|
|
{
|
2014-03-15 01:37:07 +08:00
|
|
|
|
GString *string;
|
|
|
|
|
gchar *text;
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), NULL);
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2014-03-15 01:37:07 +08:00
|
|
|
|
string = g_string_new (NULL);
|
|
|
|
|
|
2015-06-03 15:41:23 +08:00
|
|
|
|
text = gimp_color_profile_get_description (profile);
|
2014-03-15 01:37:07 +08:00
|
|
|
|
if (text)
|
2014-03-14 08:44:27 +08:00
|
|
|
|
{
|
2014-03-15 01:37:07 +08:00
|
|
|
|
g_string_append (string, text);
|
|
|
|
|
g_free (text);
|
|
|
|
|
}
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2015-06-03 15:41:23 +08:00
|
|
|
|
text = gimp_color_profile_get_model (profile);
|
2014-03-15 01:37:07 +08:00
|
|
|
|
if (text)
|
|
|
|
|
{
|
|
|
|
|
if (string->len > 0)
|
|
|
|
|
g_string_append (string, "\n");
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2014-03-15 01:37:07 +08:00
|
|
|
|
g_string_append (string, text);
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_free (text);
|
2014-03-14 08:44:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-03 15:41:23 +08:00
|
|
|
|
text = gimp_color_profile_get_manufacturer (profile);
|
2014-03-15 01:37:07 +08:00
|
|
|
|
if (text)
|
|
|
|
|
{
|
|
|
|
|
if (string->len > 0)
|
|
|
|
|
g_string_append (string, "\n");
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2014-03-15 01:37:07 +08:00
|
|
|
|
g_string_append (string, text);
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_free (text);
|
2014-03-15 01:37:07 +08:00
|
|
|
|
}
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2015-06-03 15:41:23 +08:00
|
|
|
|
text = gimp_color_profile_get_copyright (profile);
|
2014-03-15 01:37:07 +08:00
|
|
|
|
if (text)
|
2014-03-14 08:44:27 +08:00
|
|
|
|
{
|
2014-03-15 01:37:07 +08:00
|
|
|
|
if (string->len > 0)
|
|
|
|
|
g_string_append (string, "\n");
|
2014-03-14 08:44:27 +08:00
|
|
|
|
|
2014-03-15 01:37:07 +08:00
|
|
|
|
g_string_append (string, text);
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_free (text);
|
2014-03-14 08:44:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-15 01:37:07 +08:00
|
|
|
|
return g_string_free (string, FALSE);
|
2014-03-14 08:44:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_is_equal:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile1: a #GimpColorProfile
|
|
|
|
|
* @profile2: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* Compares two profiles.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the profiles are equal, %FALSE otherwise.
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-29 17:40:47 +08:00
|
|
|
|
gboolean
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_is_equal (GimpColorProfile *profile1,
|
|
|
|
|
GimpColorProfile *profile2)
|
2014-03-29 17:40:47 +08:00
|
|
|
|
{
|
2015-07-11 05:06:53 +08:00
|
|
|
|
const gsize header_len = sizeof (cmsICCHeader);
|
2014-03-29 17:40:47 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile1), FALSE);
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile1), FALSE);
|
2014-03-29 17:40:47 +08:00
|
|
|
|
|
2015-07-11 05:06:53 +08:00
|
|
|
|
return (profile1->priv->length == profile2->priv->length &&
|
|
|
|
|
memcmp (profile1->priv->data + header_len,
|
|
|
|
|
profile2->priv->data + header_len,
|
|
|
|
|
profile1->priv->length - header_len) == 0);
|
2014-03-29 17:40:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_is_rgb:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the profile's color space is RGB, %FALSE
|
|
|
|
|
* otherwise.
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-16 04:46:02 +08:00
|
|
|
|
gboolean
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_is_rgb (GimpColorProfile *profile)
|
2014-03-16 04:46:02 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), FALSE);
|
2014-03-16 04:46:02 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
return (cmsGetColorSpace (profile->priv->lcms_profile) == cmsSigRgbData);
|
2014-03-16 04:46:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 08:00:33 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_is_cmyk:
|
2015-05-07 08:00:33 +08:00
|
|
|
|
* @profile: a #GimpColorProfile
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE if the profile's color space is CMYK, %FALSE
|
|
|
|
|
* otherwise.
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-07 08:00:33 +08:00
|
|
|
|
**/
|
2014-03-16 04:46:02 +08:00
|
|
|
|
gboolean
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_is_cmyk (GimpColorProfile *profile)
|
2014-03-16 04:46:02 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), FALSE);
|
2014-03-16 04:46:02 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
return (cmsGetColorSpace (profile->priv->lcms_profile) == cmsSigCmykData);
|
2014-03-16 04:46:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-15 07:06:47 +08:00
|
|
|
|
static void
|
2015-06-03 15:41:23 +08:00
|
|
|
|
gimp_color_profile_set_tag (cmsHPROFILE profile,
|
|
|
|
|
cmsTagSignature sig,
|
|
|
|
|
const gchar *tag)
|
2014-03-15 07:06:47 +08:00
|
|
|
|
{
|
|
|
|
|
cmsMLU *mlu;
|
|
|
|
|
|
|
|
|
|
mlu = cmsMLUalloc (NULL, 1);
|
|
|
|
|
cmsMLUsetASCII (mlu, "en", "US", tag);
|
|
|
|
|
cmsWriteTag (profile, sig, mlu);
|
|
|
|
|
cmsMLUfree (mlu);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
static cmsHPROFILE *
|
2015-06-03 15:41:23 +08:00
|
|
|
|
gimp_color_profile_new_srgb_internal (void)
|
2014-02-06 22:53:37 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
cmsHPROFILE profile;
|
2014-03-15 07:06:47 +08:00
|
|
|
|
cmsCIExyY d65_srgb_specs = { 0.3127, 0.3290, 1.0 };
|
2014-02-10 22:42:39 +08:00
|
|
|
|
|
2014-03-15 07:06:47 +08:00
|
|
|
|
cmsCIExyYTRIPLE srgb_primaries_pre_quantized =
|
2014-02-06 22:53:37 +08:00
|
|
|
|
{
|
|
|
|
|
{ 0.639998686, 0.330010138, 1.0 },
|
|
|
|
|
{ 0.300003784, 0.600003357, 1.0 },
|
|
|
|
|
{ 0.150002046, 0.059997204, 1.0 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
cmsFloat64Number srgb_parameters[5] =
|
|
|
|
|
{ 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
|
|
|
|
|
|
|
|
|
|
cmsToneCurve *srgb_parametric_curve =
|
|
|
|
|
cmsBuildParametricToneCurve (NULL, 4, srgb_parameters);
|
|
|
|
|
|
|
|
|
|
cmsToneCurve *tone_curve[3];
|
|
|
|
|
|
|
|
|
|
tone_curve[0] = tone_curve[1] = tone_curve[2] = srgb_parametric_curve;
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
profile = cmsCreateRGBProfile (&d65_srgb_specs,
|
|
|
|
|
&srgb_primaries_pre_quantized,
|
|
|
|
|
tone_curve);
|
2014-02-06 22:53:37 +08:00
|
|
|
|
|
|
|
|
|
cmsFreeToneCurve (srgb_parametric_curve);
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_set_tag (profile, cmsSigProfileDescriptionTag,
|
2015-06-03 15:41:23 +08:00
|
|
|
|
"GIMP built-in sRGB");
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_set_tag (profile, cmsSigDeviceMfgDescTag,
|
2015-06-03 15:41:23 +08:00
|
|
|
|
"GIMP");
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_set_tag (profile, cmsSigDeviceModelDescTag,
|
2015-06-03 15:41:23 +08:00
|
|
|
|
"sRGB");
|
2015-07-11 04:43:53 +08:00
|
|
|
|
gimp_color_profile_set_tag (profile, cmsSigCopyrightTag,
|
2015-06-03 15:41:23 +08:00
|
|
|
|
"Public Domain");
|
2014-02-06 22:53:37 +08:00
|
|
|
|
|
2015-05-31 08:47:24 +08:00
|
|
|
|
/* The following line produces a V2 profile with a point curve TRC.
|
2014-02-10 22:42:39 +08:00
|
|
|
|
* Profiles with point curve TRCs can't be used in LCMS2 unbounded
|
|
|
|
|
* mode ICC profile conversions. A V2 profile might be appropriate
|
|
|
|
|
* for embedding in sRGB images saved to disk, if the image is to be
|
|
|
|
|
* opened by an image editing application that doesn't understand V4
|
|
|
|
|
* profiles.
|
|
|
|
|
*
|
|
|
|
|
* cmsSetProfileVersion (srgb_profile, 2.1);
|
2015-05-31 08:47:24 +08:00
|
|
|
|
*/
|
2014-02-06 22:53:37 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
return profile;
|
2014-02-06 22:53:37 +08:00
|
|
|
|
}
|
2014-04-10 22:30:04 +08:00
|
|
|
|
|
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_new_srgb:
|
2014-04-10 22:30:04 +08:00
|
|
|
|
*
|
|
|
|
|
* This function is a replacement for cmsCreate_sRGBProfile() and
|
|
|
|
|
* returns an sRGB profile that is functionally the same as the
|
|
|
|
|
* ArgyllCMS sRGB.icm profile. "Functionally the same" means it has
|
|
|
|
|
* the same red, green, and blue colorants and the V4 "chad"
|
|
|
|
|
* equivalent of the ArgyllCMS V2 white point. The profile TRC is also
|
|
|
|
|
* functionally equivalent to the ArgyllCMS sRGB.icm TRC and is the
|
|
|
|
|
* same as the LCMS sRGB built-in profile TRC.
|
|
|
|
|
*
|
|
|
|
|
* The actual primaries in the sRGB specification are
|
|
|
|
|
* red xy: {0.6400, 0.3300, 1.0}
|
|
|
|
|
* green xy: {0.3000, 0.6000, 1.0}
|
|
|
|
|
* blue xy: {0.1500, 0.0600, 1.0}
|
|
|
|
|
*
|
|
|
|
|
* The sRGB primaries given below are "pre-quantized" to compensate
|
|
|
|
|
* for hexadecimal quantization during the profile-making process.
|
|
|
|
|
* Unless the profile-making code compensates for this quantization,
|
|
|
|
|
* the resulting profile's red, green, and blue colorants will deviate
|
|
|
|
|
* slightly from the correct XYZ values.
|
|
|
|
|
*
|
|
|
|
|
* LCMS2 doesn't compensate for hexadecimal quantization. The
|
|
|
|
|
* "pre-quantized" primaries below were back-calculated from the
|
|
|
|
|
* ArgyllCMS sRGB.icm profile. The resulting sRGB profile's colorants
|
|
|
|
|
* exactly matches the ArgyllCMS sRGB.icm profile colorants.
|
|
|
|
|
*
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* Return value: the sRGB #GimpColorProfile.
|
2014-04-10 22:30:04 +08:00
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2014-04-10 22:30:04 +08:00
|
|
|
|
**/
|
2015-07-11 04:43:53 +08:00
|
|
|
|
GimpColorProfile *
|
2015-06-03 15:41:23 +08:00
|
|
|
|
gimp_color_profile_new_srgb (void)
|
2014-04-10 22:30:04 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
static GimpColorProfile *profile = NULL;
|
2014-04-10 22:30:04 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
const guint8 *data;
|
|
|
|
|
gsize length;
|
2014-04-10 22:30:04 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
if (G_UNLIKELY (profile == NULL))
|
|
|
|
|
{
|
|
|
|
|
cmsHPROFILE lcms_profile = gimp_color_profile_new_srgb_internal ();
|
2014-04-10 22:30:04 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
profile = gimp_color_profile_new_from_lcms_profile (lcms_profile, NULL);
|
2014-04-10 22:30:04 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
cmsCloseProfile (lcms_profile);
|
2014-04-10 22:30:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
data = gimp_color_profile_get_icc_profile (profile, &length);
|
|
|
|
|
|
|
|
|
|
return gimp_color_profile_new_from_icc_profile (data, length, NULL);
|
2014-04-10 22:30:04 +08:00
|
|
|
|
}
|
2015-05-08 18:44:44 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
static cmsHPROFILE
|
2015-06-03 15:41:23 +08:00
|
|
|
|
gimp_color_profile_new_linear_rgb_internal (void)
|
2015-05-13 04:47:12 +08:00
|
|
|
|
{
|
|
|
|
|
cmsHPROFILE profile;
|
|
|
|
|
|
|
|
|
|
/* white point is D65 from the sRGB specs */
|
|
|
|
|
cmsCIExyY whitepoint = { 0.3127, 0.3290, 1.0 };
|
|
|
|
|
|
|
|
|
|
/* primaries are ITU‐R BT.709‐5 (xYY), which are also the primaries
|
|
|
|
|
* from the sRGB specs, modified to properly account for hexadecimal
|
|
|
|
|
* quantization during the profile making process.
|
|
|
|
|
*/
|
|
|
|
|
cmsCIExyYTRIPLE primaries =
|
|
|
|
|
{
|
|
|
|
|
/* R { 0.6400, 0.3300, 1.0 }, */
|
|
|
|
|
/* G { 0.3000, 0.6000, 1.0 }, */
|
|
|
|
|
/* B { 0.1500, 0.0600, 1.0 } */
|
|
|
|
|
/* R */ { 0.639998686, 0.330010138, 1.0 },
|
|
|
|
|
/* G */ { 0.300003784, 0.600003357, 1.0 },
|
|
|
|
|
/* B */ { 0.150002046, 0.059997204, 1.0 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* linear light */
|
|
|
|
|
cmsToneCurve *linear[3];
|
|
|
|
|
|
|
|
|
|
linear[0] = linear[1] = linear[2] = cmsBuildGamma (NULL, 1.0);
|
|
|
|
|
|
|
|
|
|
/* create the profile, cleanup, and return */
|
|
|
|
|
profile = cmsCreateRGBProfile (&whitepoint, &primaries, linear);
|
|
|
|
|
cmsFreeToneCurve (linear[0]);
|
|
|
|
|
|
2015-06-03 15:41:23 +08:00
|
|
|
|
gimp_color_profile_set_tag (profile, cmsSigProfileDescriptionTag,
|
|
|
|
|
"GIMP built-in Linear RGB");
|
|
|
|
|
gimp_color_profile_set_tag (profile, cmsSigDeviceMfgDescTag,
|
|
|
|
|
"GIMP");
|
|
|
|
|
gimp_color_profile_set_tag (profile, cmsSigDeviceModelDescTag,
|
|
|
|
|
"Linear RGB");
|
|
|
|
|
gimp_color_profile_set_tag (profile, cmsSigCopyrightTag,
|
|
|
|
|
"Public Domain");
|
2015-05-13 04:47:12 +08:00
|
|
|
|
|
|
|
|
|
return profile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_new_linear_rgb:
|
2015-05-13 04:47:12 +08:00
|
|
|
|
*
|
|
|
|
|
* This function creates a profile for babl_model("RGB"). Please
|
|
|
|
|
* somebody write someting smarter here.
|
|
|
|
|
*
|
2015-07-11 04:43:53 +08:00
|
|
|
|
* Return value: the linear RGB #GimpColorProfile.
|
2015-05-13 04:47:12 +08:00
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-13 04:47:12 +08:00
|
|
|
|
**/
|
2015-07-11 04:43:53 +08:00
|
|
|
|
GimpColorProfile *
|
2015-06-03 15:41:23 +08:00
|
|
|
|
gimp_color_profile_new_linear_rgb (void)
|
2015-05-13 04:47:12 +08:00
|
|
|
|
{
|
2015-07-11 04:43:53 +08:00
|
|
|
|
static GimpColorProfile *profile = NULL;
|
2015-05-13 04:47:12 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
const guint8 *data;
|
|
|
|
|
gsize length;
|
2015-05-13 04:47:12 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
if (G_UNLIKELY (profile == NULL))
|
|
|
|
|
{
|
|
|
|
|
cmsHPROFILE lcms_profile = gimp_color_profile_new_linear_rgb_internal ();
|
2015-05-13 04:47:12 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
profile = gimp_color_profile_new_from_lcms_profile (lcms_profile, NULL);
|
2015-05-13 04:47:12 +08:00
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
cmsCloseProfile (lcms_profile);
|
2015-05-13 04:47:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-11 04:43:53 +08:00
|
|
|
|
data = gimp_color_profile_get_icc_profile (profile, &length);
|
|
|
|
|
|
|
|
|
|
return gimp_color_profile_new_from_icc_profile (data, length, NULL);
|
2015-05-13 04:47:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-08 18:44:44 +08:00
|
|
|
|
/**
|
2015-06-03 15:41:23 +08:00
|
|
|
|
* gimp_color_profile_get_format:
|
2015-05-08 18:44:44 +08:00
|
|
|
|
* @format: a #Babl format
|
|
|
|
|
* @lcms_format: return location for an lcms format
|
|
|
|
|
*
|
|
|
|
|
* This function takes a #Babl format and returns the lcms format to
|
|
|
|
|
* be used with that @format. It also returns a #Babl format to be
|
|
|
|
|
* used instead of the passed @format, which usually is the same as
|
|
|
|
|
* @format, unless lcms doesn't support @format.
|
|
|
|
|
*
|
|
|
|
|
* Note that this function currently only supports RGB, RGBA, R'G'B' and
|
|
|
|
|
* R'G'B'A formats.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the #Babl format to be used instead of @format, or %NULL
|
|
|
|
|
* is the passed @format is not supported at all.
|
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
|
* Since: 2.10
|
2015-05-08 18:44:44 +08:00
|
|
|
|
**/
|
|
|
|
|
const Babl *
|
2015-06-03 15:41:23 +08:00
|
|
|
|
gimp_color_profile_get_format (const Babl *format,
|
|
|
|
|
guint32 *lcms_format)
|
2015-05-08 18:44:44 +08:00
|
|
|
|
{
|
|
|
|
|
const Babl *output_format = NULL;
|
|
|
|
|
const Babl *type;
|
|
|
|
|
const Babl *model;
|
|
|
|
|
gboolean has_alpha;
|
|
|
|
|
gboolean linear;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (format != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (lcms_format != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
has_alpha = babl_format_has_alpha (format);
|
|
|
|
|
type = babl_format_get_type (format, 0);
|
|
|
|
|
model = babl_format_get_model (format);
|
|
|
|
|
|
|
|
|
|
if (model == babl_model ("RGB") ||
|
|
|
|
|
model == babl_model ("RGBA"))
|
|
|
|
|
{
|
|
|
|
|
linear = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (model == babl_model ("R'G'B'") ||
|
|
|
|
|
model == babl_model ("R'G'B'A"))
|
|
|
|
|
{
|
|
|
|
|
linear = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_reached (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*lcms_format = 0;
|
|
|
|
|
|
|
|
|
|
if (type == babl_type ("u8"))
|
|
|
|
|
{
|
|
|
|
|
if (has_alpha)
|
|
|
|
|
*lcms_format = TYPE_RGBA_8;
|
|
|
|
|
else
|
|
|
|
|
*lcms_format = TYPE_RGB_8;
|
|
|
|
|
|
|
|
|
|
output_format = format;
|
|
|
|
|
}
|
|
|
|
|
else if (type == babl_type ("u16"))
|
|
|
|
|
{
|
|
|
|
|
if (has_alpha)
|
|
|
|
|
*lcms_format = TYPE_RGBA_16;
|
|
|
|
|
else
|
|
|
|
|
*lcms_format = TYPE_RGB_16;
|
|
|
|
|
|
|
|
|
|
output_format = format;
|
|
|
|
|
}
|
|
|
|
|
else if (type == babl_type ("half")) /* 16-bit floating point (half) */
|
|
|
|
|
{
|
|
|
|
|
if (has_alpha)
|
|
|
|
|
*lcms_format = TYPE_RGBA_HALF_FLT;
|
|
|
|
|
else
|
|
|
|
|
*lcms_format = TYPE_RGB_HALF_FLT;
|
|
|
|
|
|
|
|
|
|
output_format = format;
|
|
|
|
|
}
|
|
|
|
|
else if (type == babl_type ("float"))
|
|
|
|
|
{
|
|
|
|
|
if (has_alpha)
|
|
|
|
|
*lcms_format = TYPE_RGBA_FLT;
|
|
|
|
|
else
|
|
|
|
|
*lcms_format = TYPE_RGB_FLT;
|
|
|
|
|
|
|
|
|
|
output_format = format;
|
|
|
|
|
}
|
|
|
|
|
else if (type == babl_type ("double"))
|
|
|
|
|
{
|
|
|
|
|
if (has_alpha)
|
|
|
|
|
{
|
|
|
|
|
#ifdef TYPE_RGBA_DBL
|
|
|
|
|
/* RGBA double not implemented in lcms */
|
|
|
|
|
*lcms_format = TYPE_RGBA_DBL;
|
|
|
|
|
output_format = format;
|
|
|
|
|
#endif /* TYPE_RGBA_DBL */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*lcms_format = TYPE_RGB_DBL;
|
|
|
|
|
output_format = format;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*lcms_format == 0)
|
|
|
|
|
{
|
2015-06-13 02:43:17 +08:00
|
|
|
|
g_printerr ("%s: layer format %s not supported, "
|
2015-05-08 18:44:44 +08:00
|
|
|
|
"falling back to float\n",
|
2015-06-13 02:43:17 +08:00
|
|
|
|
G_STRFUNC, babl_get_name (format));
|
2015-05-08 18:44:44 +08:00
|
|
|
|
|
|
|
|
|
if (has_alpha)
|
|
|
|
|
{
|
|
|
|
|
*lcms_format = TYPE_RGBA_FLT;
|
|
|
|
|
|
|
|
|
|
if (linear)
|
|
|
|
|
output_format = babl_format ("RGBA float");
|
|
|
|
|
else
|
|
|
|
|
output_format = babl_format ("R'G'B'A float");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*lcms_format = TYPE_RGB_FLT;
|
|
|
|
|
|
|
|
|
|
if (linear)
|
|
|
|
|
output_format = babl_format ("RGB float");
|
|
|
|
|
else
|
|
|
|
|
output_format = babl_format ("R'G'B' float");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return output_format;
|
|
|
|
|
}
|