plug-ins: support color managed EXR loading

This generates an ICC profile from the embedded white point and
chromaticities on the fly, assuming linear gamma images.
This commit is contained in:
Tobias Ellinghaus 2015-09-20 23:42:24 +02:00
parent 9550fbff3c
commit d73cfa4a24
4 changed files with 104 additions and 0 deletions

View File

@ -26,6 +26,7 @@ AM_CPPFLAGS = \
$(GTK_CFLAGS) \
$(GEGL_CFLAGS) \
$(OPENEXR_CFLAGS) \
$(LCMS_CFLAGS) \
-I$(includedir)
libexec_PROGRAMS = file-exr
@ -48,4 +49,5 @@ file_exr_LDADD = \
$(GEGL_LIBS) \
$(RT_LIBS) \
$(INTLLIBS) \
$(LCMS_LIBS) \
$(file_exr_RC)

View File

@ -280,6 +280,27 @@ load_image (const gchar *filename,
gimp_progress_update ((gdouble) begin / (gdouble) height);
}
// try to load an icc profile.
// this will be generated on the fly if chromaticities are given
if (image_type == GIMP_RGB)
{
cmsHPROFILE lcms_profile = NULL;
GimpColorProfile *profile = NULL;
lcms_profile = exr_loader_icc_read_profile (loader);
if (lcms_profile)
{
profile = gimp_color_profile_new_from_lcms_profile (lcms_profile,
NULL);
if (profile)
{
gimp_image_set_color_profile (image, profile);
g_object_unref (profile);
}
cmsCloseProfile (lcms_profile);
}
}
gimp_progress_update (1.0);
status = image;

View File

@ -170,6 +170,76 @@ struct _EXRLoader
return has_alpha_ ? 1 : 0;
}
cmsHPROFILE readICCProfile() const {
Chromaticities chromaticities;
float whiteLuminance = 1.0;
cmsHPROFILE profile = NULL;
if (hasChromaticities (file_.header ()))
chromaticities = Imf::chromaticities (file_.header ());
else
return NULL;
if (Imf::hasWhiteLuminance (file_.header ()))
whiteLuminance = Imf::whiteLuminance (file_.header ());
else
return NULL;
#if 0
std::cout << "hasChromaticities: "
<< hasChromaticities (file_.header ())
<< std::endl;
std::cout << "hasWhiteLuminance: "
<< hasWhiteLuminance (file_.header ())
<< std::endl;
std::cout << chromaticities.red << std::endl;
std::cout << chromaticities.green << std::endl;
std::cout << chromaticities.blue << std::endl;
std::cout << chromaticities.white << std::endl;
std::cout << std::endl;
#endif
// TODO: maybe factor this out into libgimpcolor/gimpcolorprofile.h ?
cmsCIExyY whitePoint = { chromaticities.white.x,
chromaticities.white.y,
whiteLuminance };
cmsCIExyYTRIPLE CameraPrimaries = { { chromaticities.red.x,
chromaticities.red.y,
whiteLuminance },
{ chromaticities.green.x,
chromaticities.green.y,
whiteLuminance },
{ chromaticities.blue.x,
chromaticities.blue.y,
whiteLuminance } };
double Parameters[2] = { 1.0, 0.0 };
cmsToneCurve *Gamma[3];
Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildParametricToneCurve(0,
1,
Parameters);
profile = cmsCreateRGBProfile (&whitePoint, &CameraPrimaries, Gamma);
cmsFreeToneCurve (Gamma[0]);
if (profile == NULL) return NULL;
cmsSetProfileVersion (profile, 2.1);
cmsMLU *mlu0 = cmsMLUalloc (NULL, 1);
cmsMLUsetASCII (mlu0, "en", "US", "(GIMP internal)");
cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII (mlu1, "en", "US", "color profile from EXR chromaticities");
cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII (mlu2, "en", "US", "color profile from EXR chromaticities");
cmsWriteTag (profile, cmsSigDeviceMfgDescTag, mlu0);
cmsWriteTag (profile, cmsSigDeviceModelDescTag, mlu1);
cmsWriteTag (profile, cmsSigProfileDescriptionTag, mlu2);
cmsMLUfree (mlu0);
cmsMLUfree (mlu1);
cmsMLUfree (mlu2);
return profile;
}
size_t refcount_;
InputFile file_;
const Box2i data_window_;
@ -289,3 +359,9 @@ exr_loader_read_pixel_row (EXRLoader *loader,
return retval;
}
cmsHPROFILE
exr_loader_icc_read_profile (EXRLoader *loader)
{
return loader->readICCProfile ();
}

View File

@ -8,6 +8,8 @@
extern "C" {
#endif
#include <lcms2.h>
/* This is fully opaque on purpose, as the calling C code must not be
* exposed to more than this.
*/
@ -54,6 +56,9 @@ exr_loader_read_pixel_row (EXRLoader *loader,
int bpp,
int row);
cmsHPROFILE
exr_loader_icc_read_profile (EXRLoader *loader);
#ifdef __cplusplus
}
#endif