Ensure embedded profile, if any, is always used

Perform sRGB conversion at end of pipe only

withMetadata exports profile, should not convert

Convert one fixture to sRGB to help test

Discovered while investigating #125
This commit is contained in:
Lovell Fuller
2014-11-25 18:31:20 +00:00
parent 02b6016390
commit f57a0e3b00
7 changed files with 53 additions and 39 deletions

View File

@@ -117,6 +117,13 @@ namespace sharp {
return image;
}
/*
Does this image have an embedded profile?
*/
bool HasProfile(VipsImage *image) {
return (vips_image_get_typeof(image, VIPS_META_ICC_NAME) > 0) ? TRUE : FALSE;
}
/*
Does this image have an alpha channel?
Uses colour space interpretation with number of channels to guess this.

View File

@@ -44,6 +44,11 @@ namespace sharp {
*/
VipsImage* InitImage(ImageType imageType, char const *file, VipsAccess const access);
/*
Does this image have an embedded profile?
*/
bool HasProfile(VipsImage *image);
/*
Does this image have an alpha channel?
Uses colour space interpretation with number of channels to guess this.

View File

@@ -74,7 +74,7 @@ class MetadataWorker : public NanAsyncWorker {
baton->height = image->Ysize;
baton->space = vips_enum_nick(VIPS_TYPE_INTERPRETATION, image->Type);
baton->channels = image->Bands;
baton->hasProfile = (vips_image_get_typeof(image, VIPS_META_ICC_NAME) > 0) ? TRUE : FALSE;
baton->hasProfile = HasProfile(image);
// Derived attributes
baton->hasAlpha = HasAlpha(image);
baton->orientation = ExifOrientation(image);

View File

@@ -269,33 +269,23 @@ class ResizeWorker : public NanAsyncWorker {
image = shrunkOnLoad;
}
// Handle colour profile, if any, for non sRGB images
if (image->Type != VIPS_INTERPRETATION_sRGB) {
// Get the input colour profile
if (vips_image_get_typeof(image, VIPS_META_ICC_NAME)) {
VipsImage *profile;
// Use embedded profile
if (vips_icc_import(image, &profile, "pcs", VIPS_PCS_XYZ, "embedded", TRUE, NULL)) {
return Error(baton, hook);
}
vips_object_local(hook, profile);
image = profile;
} else if (image->Type == VIPS_INTERPRETATION_CMYK) {
VipsImage *profile;
// CMYK with no embedded profile
if (vips_icc_import(image, &profile, "pcs", VIPS_PCS_XYZ, "input_profile", (baton->iccProfileCmyk).c_str(), NULL)) {
return Error(baton, hook);
}
vips_object_local(hook, profile);
image = profile;
}
// Attempt to convert to sRGB colour space
VipsImage *colourspaced;
if (vips_colourspace(image, &colourspaced, VIPS_INTERPRETATION_sRGB, NULL)) {
// Ensure we're using a device-independent colour space
if (HasProfile(image)) {
// Convert to CIELAB using embedded profile
VipsImage *profile;
if (vips_icc_import(image, &profile, "pcs", VIPS_PCS_XYZ, "embedded", TRUE, NULL)) {
return Error(baton, hook);
}
vips_object_local(hook, colourspaced);
image = colourspaced;
vips_object_local(hook, profile);
image = profile;
} else if (image->Type == VIPS_INTERPRETATION_CMYK) {
// Convert to CIELAB using default "USWebCoatedSWOP" CMYK profile
VipsImage *profile;
if (vips_icc_import(image, &profile, "pcs", VIPS_PCS_XYZ, "input_profile", (baton->iccProfileCmyk).c_str(), NULL)) {
return Error(baton, hook);
}
vips_object_local(hook, profile);
image = profile;
}
// Flatten image to remove alpha channel
@@ -578,14 +568,22 @@ class ResizeWorker : public NanAsyncWorker {
image = gammaDecoded;
}
// Convert to sRGB colour space, if not already
// Convert colour space to either sRGB or RGB-with-profile, if not already
if (image->Type != VIPS_INTERPRETATION_sRGB) {
VipsImage *colourspaced;
if (vips_colourspace(image, &colourspaced, VIPS_INTERPRETATION_sRGB, NULL)) {
return Error(baton, hook);
VipsImage *rgb;
if (baton->withMetadata && HasProfile(image)) {
// Convert to device-dependent RGB using embedded profile of input
if (vips_icc_export(image, &rgb, NULL)) {
return Error(baton, hook);
}
} else {
// Convert to device-independent sRGB
if (vips_colourspace(image, &rgb, VIPS_INTERPRETATION_sRGB, NULL)) {
return Error(baton, hook);
}
}
vips_object_local(hook, colourspaced);
image = colourspaced;
vips_object_local(hook, rgb);
image = rgb;
}
#if !(VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 40 && VIPS_MINOR_VERSION >= 5)