New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICC profile removed from images when modified by GD #136

Open
imazen-bot opened this Issue Feb 5, 2015 · 14 comments

Comments

Projects
None yet
8 participants
@imazen-bot

imazen-bot commented Feb 5, 2015

It's always ICC profile was removed, especially Adobe RGB (1998) after uploading photos and convert them by GD version 2.1.

Please advise how to avoid it?


@kenoir

This comment has been minimized.

Show comment
Hide comment
@kenoir

kenoir Jul 8, 2015

+1 Would be interested in seeing a solution to this problem.

kenoir commented Jul 8, 2015

+1 Would be interested in seeing a solution to this problem.

@vapier vapier changed the title from ICC profile was removed to ICC profile removed from images when modified by GD Jul 8, 2015

@cmb69

This comment has been minimized.

Show comment
Hide comment
@cmb69

cmb69 Oct 8, 2016

Contributor

FWIW, GD's WebP decoder applies the ICC corrections to the image.

Contributor

cmb69 commented Oct 8, 2016

FWIW, GD's WebP decoder applies the ICC corrections to the image.

@cmb69

This comment has been minimized.

Show comment
Hide comment
@cmb69

cmb69 Jan 22, 2017

Contributor

Respective suspended PHP bugtracker ticket: https://bugs.php.net/bug.php?id=53598.

Contributor

cmb69 commented Jan 22, 2017

Respective suspended PHP bugtracker ticket: https://bugs.php.net/bug.php?id=53598.

@Nicksxs

This comment has been minimized.

Show comment
Hide comment
@Nicksxs

Nicksxs Apr 6, 2017

have any solution to solve this problem now @cmb69

Nicksxs commented Apr 6, 2017

have any solution to solve this problem now @cmb69

@cmb69

This comment has been minimized.

Show comment
Hide comment
@cmb69

cmb69 Apr 14, 2017

Contributor

@Nicksxs Basically, you have to read the profile information from the original image, and write it back to the new image. I suppose that is sufficient for some but not all image manipulations.

If you're working with PHP and JPEG, maybe https://github.com/lsolesen/pel helps to get the job done.

Contributor

cmb69 commented Apr 14, 2017

@Nicksxs Basically, you have to read the profile information from the original image, and write it back to the new image. I suppose that is sufficient for some but not all image manipulations.

If you're working with PHP and JPEG, maybe https://github.com/lsolesen/pel helps to get the job done.

@azavisha

This comment has been minimized.

Show comment
Hide comment
@azavisha

azavisha Jul 30, 2017

GD library is used by NGINX module named "ngx_http_image_filter_module". This module has no configuration parameters to preserve colour profiles. I use this module and all of my images lose information about their embedded colour profile when resized. This is a serious problem because images can look too saturated or too pale depending on the device and browser.

Is it safe to say that this is a bug in the NGINX module (or perhaps PHP-GD library that it uses) and not the GD library itself? I'm asking because PHP suspended the related bug referenced above by @cmb69 and they are pointing the finger at GD. And nobody is working to get this problem fixed...

azavisha commented Jul 30, 2017

GD library is used by NGINX module named "ngx_http_image_filter_module". This module has no configuration parameters to preserve colour profiles. I use this module and all of my images lose information about their embedded colour profile when resized. This is a serious problem because images can look too saturated or too pale depending on the device and browser.

Is it safe to say that this is a bug in the NGINX module (or perhaps PHP-GD library that it uses) and not the GD library itself? I'm asking because PHP suspended the related bug referenced above by @cmb69 and they are pointing the finger at GD. And nobody is working to get this problem fixed...

@azavisha

This comment has been minimized.

Show comment
Hide comment
@azavisha

azavisha commented Jul 30, 2017

I filed a new bug report with NGINX: https://trac.nginx.org/nginx/ticket/1343#no4

@cmb69

This comment has been minimized.

Show comment
Hide comment
@cmb69

cmb69 Jul 30, 2017

Contributor

Actually, the question is how to deal with such color profiles:

  1. Read them, ignore them during processing, write them back when the image is saved.
  2. Read them, apply them before any image processing, but ignore them when the image is saved.

(1) may not be possible for WebP, because the decoder applies the profiles (maybe this can be turned off). However, there's a big issue with (1), if the image is saved is saved in a format that does not support color profiles.

(2) defeats the purpose of color profiles, but somehow seems more appropriate for libgd.

Contributor

cmb69 commented Jul 30, 2017

Actually, the question is how to deal with such color profiles:

  1. Read them, ignore them during processing, write them back when the image is saved.
  2. Read them, apply them before any image processing, but ignore them when the image is saved.

(1) may not be possible for WebP, because the decoder applies the profiles (maybe this can be turned off). However, there's a big issue with (1), if the image is saved is saved in a format that does not support color profiles.

(2) defeats the purpose of color profiles, but somehow seems more appropriate for libgd.

@azavisha

This comment has been minimized.

Show comment
Hide comment
@azavisha

azavisha Jul 30, 2017

Thank you @cmb69. The only solution that makes sense to me is to preserve colour profiles. If the information is present, then write it back when the new image is saved. If there is no information, then don't add anything.

I am not sure about GD, but ngx_http_image_filter_module doesn't change the format of images during processing. It outputs images in the same format as it receives. Even if GD can do that and the original image contains a colour profile while the output format doesn't support it, it seems there is no other choice but to leave it out.

When I create an image, I add colour profile information to it, and I expect any image processing software to respect and preserve this information. What happens now when NGINX's image filter module resizes my images, this information simply gets removed and any browser reading that resized image has no idea about its colour profile. My images look normal on regular desktops, but wide gamut displays show oversaturated colours, and some laptops show very pale colours.

I don't know much about WebP, but I see that it supports colour profiles (https://developers.google.com/speed/webp/docs/riff_container#color_profile).

If this doesn't make sense for GD library to preserve colour profile information, then I would encourage NGINX to do this in their module.

azavisha commented Jul 30, 2017

Thank you @cmb69. The only solution that makes sense to me is to preserve colour profiles. If the information is present, then write it back when the new image is saved. If there is no information, then don't add anything.

I am not sure about GD, but ngx_http_image_filter_module doesn't change the format of images during processing. It outputs images in the same format as it receives. Even if GD can do that and the original image contains a colour profile while the output format doesn't support it, it seems there is no other choice but to leave it out.

When I create an image, I add colour profile information to it, and I expect any image processing software to respect and preserve this information. What happens now when NGINX's image filter module resizes my images, this information simply gets removed and any browser reading that resized image has no idea about its colour profile. My images look normal on regular desktops, but wide gamut displays show oversaturated colours, and some laptops show very pale colours.

I don't know much about WebP, but I see that it supports colour profiles (https://developers.google.com/speed/webp/docs/riff_container#color_profile).

If this doesn't make sense for GD library to preserve colour profile information, then I would encourage NGINX to do this in their module.

@paperboyo

This comment has been minimized.

Show comment
Hide comment
@paperboyo

paperboyo Jul 30, 2017

I'm just a user and know absolutely nothing at all about the workings of libgd. The product I use displays widely wrong colour in the scenario exactly like in an NGINX issue opened above by @azavisha.

I think (may be wrong, though) that there are two possible scenarios (both assume libgd is completely colour-blind, i.e. never takes note of any colour profile information, never tries to read it, keep it, write it, never does any colour space transformations using e.g. littleCMS, doesn't perform processing in a ICC-neutral profile connection space etc.).

I'm also not sure what is meant above by applying a profile and writing it back. I assume applying means performing a profile-to-profile colour space transformation and writing it back means embedding a colour profile information in a file.

  1. Primo non nocere (basically scenario 1 above):
    libgd should try its best to read emebedded colour profile info from the source image. Please note that different file formats can store this info differently, even the same formats can have different ways of storing it.
    Processing should happen as it happens now (assuming it only takes note of the pixel values and not of their meaning, this will lead to all sorts of problems, but won't be any worse than now).
    libgd should attempt to embedd the same colour profile back to the resulting image. If the output image format does not support ICC, well, tough luck: most popular formats do and GIF (?) won't ever be displaying proper colours anyway (also, it won't be any different to current situation). For these image formats, the best would be to convert the image values to some safe colour space (sRGB), but that would require libgd to perform correct colour transfromations, by when why not to just go fully

  2. Become fully colour-aware
    Attempt to always read all colour profile info, assume (or even give users control over what to assume) safe colour profiles for untagged images. Convert all images from their embedded (or assumed) profiles to the high-bit (probably linear) profile connection space and always perform all image processing and compositioning within this space. On output, convert all imagery into a user-specified ICC profile and by default embed it into the images. Users can be given control over what the output profile should be (or whether it should be the same as the input profile), they could also be given control over whether the output profiles should actually be embedded, although because it's very unsafe to produce images without profiles - it should never be the default behaviour.

Again: I have next to no idea. But from my layman's POV, my scenario 1 is much easier to implement and while not entirely correct (.e.g performing image operations in an unknown colour space is prone to all sorts of unpredictable errors and can't be consistent), at least won't remove important info from images. As is - all output is prone to entirely incorrect colour, widely depending on viewing environment. Basically, it's unpredictable to feed libgd with anything else than sRGB and even then the resulting images should be independently tagged with an sRGB profile or they will display wrong colour at times.

Sorry for the length and thanks for responding, @cmb69!

paperboyo commented Jul 30, 2017

I'm just a user and know absolutely nothing at all about the workings of libgd. The product I use displays widely wrong colour in the scenario exactly like in an NGINX issue opened above by @azavisha.

I think (may be wrong, though) that there are two possible scenarios (both assume libgd is completely colour-blind, i.e. never takes note of any colour profile information, never tries to read it, keep it, write it, never does any colour space transformations using e.g. littleCMS, doesn't perform processing in a ICC-neutral profile connection space etc.).

I'm also not sure what is meant above by applying a profile and writing it back. I assume applying means performing a profile-to-profile colour space transformation and writing it back means embedding a colour profile information in a file.

  1. Primo non nocere (basically scenario 1 above):
    libgd should try its best to read emebedded colour profile info from the source image. Please note that different file formats can store this info differently, even the same formats can have different ways of storing it.
    Processing should happen as it happens now (assuming it only takes note of the pixel values and not of their meaning, this will lead to all sorts of problems, but won't be any worse than now).
    libgd should attempt to embedd the same colour profile back to the resulting image. If the output image format does not support ICC, well, tough luck: most popular formats do and GIF (?) won't ever be displaying proper colours anyway (also, it won't be any different to current situation). For these image formats, the best would be to convert the image values to some safe colour space (sRGB), but that would require libgd to perform correct colour transfromations, by when why not to just go fully

  2. Become fully colour-aware
    Attempt to always read all colour profile info, assume (or even give users control over what to assume) safe colour profiles for untagged images. Convert all images from their embedded (or assumed) profiles to the high-bit (probably linear) profile connection space and always perform all image processing and compositioning within this space. On output, convert all imagery into a user-specified ICC profile and by default embed it into the images. Users can be given control over what the output profile should be (or whether it should be the same as the input profile), they could also be given control over whether the output profiles should actually be embedded, although because it's very unsafe to produce images without profiles - it should never be the default behaviour.

Again: I have next to no idea. But from my layman's POV, my scenario 1 is much easier to implement and while not entirely correct (.e.g performing image operations in an unknown colour space is prone to all sorts of unpredictable errors and can't be consistent), at least won't remove important info from images. As is - all output is prone to entirely incorrect colour, widely depending on viewing environment. Basically, it's unpredictable to feed libgd with anything else than sRGB and even then the resulting images should be independently tagged with an sRGB profile or they will display wrong colour at times.

Sorry for the length and thanks for responding, @cmb69!

@cmb69

This comment has been minimized.

Show comment
Hide comment
@cmb69
Contributor

cmb69 commented Aug 15, 2017

@azavisha

This comment has been minimized.

Show comment
Hide comment
@azavisha

azavisha Sep 25, 2017

@cmb69, are you planning to implement the first solution? It seems that it should be relatively easy to do and it will fix the problem at least for the most common scenarios.

azavisha commented Sep 25, 2017

@cmb69, are you planning to implement the first solution? It seems that it should be relatively easy to do and it will fix the problem at least for the most common scenarios.

@cmb69

This comment has been minimized.

Show comment
Hide comment
@cmb69

cmb69 Sep 25, 2017

Contributor

@azavisha While storing the color profile during read, ignoring it during processing, but writing it back on save, would be easier to implement it seems to me there are two issues:

  • it would require to extend the gdImage structure, which would be an ABI break, and as such could not be done in GD 2.2.x (2.3 might be okay)
  • treating colors of arbitrary profiles as RGB might produce wrong results
Contributor

cmb69 commented Sep 25, 2017

@azavisha While storing the color profile during read, ignoring it during processing, but writing it back on save, would be easier to implement it seems to me there are two issues:

  • it would require to extend the gdImage structure, which would be an ABI break, and as such could not be done in GD 2.2.x (2.3 might be okay)
  • treating colors of arbitrary profiles as RGB might produce wrong results
@Schweinepriester

This comment has been minimized.

Show comment
Hide comment
@Schweinepriester

Schweinepriester Nov 7, 2017

+1000

(Arrived here via https://bugs.php.net/bug.php?id=53598)
This would probably benefit the web a lot, as e.g. many (most?) WordPress installs only have GD available and thus strip color profiles for at least the smaller images, leading to false colors.

Schweinepriester commented Nov 7, 2017

+1000

(Arrived here via https://bugs.php.net/bug.php?id=53598)
This would probably benefit the web a lot, as e.g. many (most?) WordPress installs only have GD available and thus strip color profiles for at least the smaller images, leading to false colors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment