GNOME Bugzilla – Bug 721135
Unable to export to .png - libpng error: known incorrect sRGB profile
Last modified: 2014-04-13 01:59:36 UTC
Created attachment 264936 [details] verbose terminal output error I've attached the verbose terminal output
Running OSX 10.8.5 with the latest 2.8.10 build
Thanks for the log, but it only shows that there seems to be a problem with gdk-pixbuf, or with the theme, probably unrelated to png export. It would be more interesting to hear what happens when you try to export to png, any error message or whatever.
Created attachment 265103 [details] Not-very-verbose-png-error
I don't know how to tell you reproduce this because it happened after I updated to 2.8.10 and their was not elaborate sequence: * Boot gimp * open an image * make a change to it (optional step) * export as .png * unable to (Not-very-verbose-png-error screenshot)
From the conversation on IRC: The relevant error message seems to be: libpng error: known incorrect sRGB profile Which is triggered by a specific file Kunda was loading (or a set of files?). Saving a PNG file after doing File->New.. works as expected. If you could attach an example file that fails it would be really helpful.
*** Bug 721948 has been marked as a duplicate of this bug. ***
Bug 721948 has a png file attached.
For legal purposes I can't upload the file. I'm sorry. I also can't recreate the bug anymore.
Created attachment 266630 [details] The sample image from bug 721948
I can reproduce this on linux, with both 2.8 and master.
Let's confirm it then.
Created attachment 269058 [details] exporting this as a png will fail with "libpng error: known incorrect sRGB profile" http://www.playonlinux.com/en/topic-10442-1.html discusses the problem. I extracted the embedded ICC profile with ArgyllCMS "extracticc" and it looks identical to the sRGB profile distributed by Adobe, which doesn't cause any problem.
The relevant libpng code is in the png.c file, in version 1.6.9 png.c downloaded from sourceforge, check line 2278 and surrounding code. No, I don't know anything about libpng, I just asked someone who does.
libpng has code that checks for faulty sRGB profiles using its own hard-coded logic. It refuses to export as a png an image with a profile that libpng thinks is faulty. So if you open a png with Gimp, make some changes, and try to export over the original image, if libpng doesn't like the embedded sRGB profile, then what you get is a destroyed original, zero-length png file. Whether or not libpng should be doing this kind of ICC profile gate-keeping is one question. Whether libpng is correctly identifying faulty sRGB profiles is another question. Currently it seems to not do a very good job: *It identified as faulty a profile that really ought to be considered as good. Least ways I couldn't find anything wrong with it. *It "passed" a known faulty sRGB profile that has unadapted primaries and will turn your whites to cyan when applied to an sRGB image. As libpng does have this code, maybe Gimp could intercept the "export to png" process before the destination png file gets overwritten with a zero-length file and assign the Gimp built-in sRGB profile or ask the user what profile they would like to assign or ask whether the user would like to export a jpeg (lossy) or tiff instead. As I use pngs rather than tiffs whenever possible, I think this libpng profile checking behavior is scary.
Is there a way we can detect this situation, using libpng API?
libpng only rejects two very specific icc profiles in this way. This is their rationale behind it (from png.c around line 2185): /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not * match the D50 PCS illuminant in the header (it is in fact the D65 values, * so the white point is recorded as the un-adapted value.) The profiles * below only differ in one byte - the intent - and are basically the same as * the previous profile except for the mediaWhitePointTag error and a missing * chromaticAdaptationTag. */ PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") It seems impossible to actually save these sRGB profiles with libpng. I'm sure we can detect the error condition (it will probably boil down to setting up a libpng error handler and calling strcmp on the messages, which is ugly, but it works), but the question is, what do we do then? We can try setting a different sRGB profile, or we can just save the image without any profile. Which is better?
We can simply do the same check before calling libpng and replace the profile with a proper sRGB one?
Yes, that's another option. To match the libpng logic, we'd need to do an adler32 checksum on the profile, and check the profile length and adler32 against the two "known incorrect" profiles. (If it's a match, then libpng will sometimes do an additional check based on the crc, depending on whether that was configured in or not, but to be compatible with both configurations we'd probably need to skip this logic). zlib exposes an adler32 implementation, so that wouldn't be too hard.
Created attachment 269217 [details] [review] Detect "known bad" sRGB profiles. This WIP patch can successfully detect that the error will happen, but doesn't do much about it yet, other than prevent the error. Currently, saving a png with GIMP's sRGB built-in space doesn't seem to attach any color space information to the PNG. So, what do we want to do here? Do we want to actually embed the built-in profile (which wouldn't happen otherwise), leave no profile (which we do if you assign sRGB built-in to the image), or do something else like set the PNG sRGB chunk (with or without setting gAMA and cHRM too, which we currently never do for a png)?
There are a couple of Gimp bug reports complaining about the inability to embed the built-in sRGB profile. If the ability to embed the built-in sRGB profile to png files to replace detected "known incorrect" profiles is added to Gimp, could that ability be extended to offer the option of embedding the built-in sRGB profile to any image? Personally I'd prefer to stick with ICC profiles for my entire workflow, which uses pngs quite a lot, rather than having some pngs with ICC profiles and others with the sRGB Png chunk instead of a proper ICC profile.
Michael Natterer, comment #15: >Is there a way we can detect this situation, using libpng API? In fact you *do* detect it; that's why you write a zero length file. On write, inside the png_set_iCCP call, libpng calls png_app_error(...) and that calls longjmp and that gets back to the prior Gimp setjmp. libpng tries very hard to detect all the errors *before* starting to write anything, and it certainly does so in this case. So the error is detected before the first write call. If you delay the file open/create until immediately before you start to write the rows of the image then you are much less likely to destroy data. Even so, I wouldn't ever write directly to a file - I consider it a major app programming bug. You have no guarantee that Gimp won't run out of memory half way through the image. Given the size of the things people put into PNG files these days that's pretty likely. So far as this specific error is concerned you can skip it in two ways: 1) Skip all 'application' errors. Unless you fix your current error handling I would advise you to do this - it's much better to skip the error than it is to destroy an existing PNG. To do this call png_set_benign_errors(png_ptr, true). You will still get the message, but it will be a warning and longjmp won't get called. This solution also causes Gimp to write the profile; in effect it makes the write side work the same way the read side works, you get a warning on both but the profile comes in and goes out all the same. BTW: I'd check this is what happens if you do this, the code inside libpng is a little tricky. 2) In any case you can detect this particular error simply by protecting the call to png_set_iCCP; put it inside a setjmp block, catch the lonjmp there are restore the previous error handler. (How you do this depends on how the current Gimp error handler and the associated setjmp is constructed.) In this case libpng does not write the ICC profile; the error happens, the profile is not set, but you regain control immediately and can then do error handling specific to this issue. I believe that it is possible if you catch this error to write a different profile or to simply call png_set_sRGB, but of course you don't know that it really is the 'known incorrect' profile unless you check it. You could do a strcmp on the error message, but I hope libpng will be i18n'ed some day and, anyway, it's one of those error messages whose wording might change. There are some other obvious approaches, for example you can turn benign errors off then turn them back on after the call, but the 'false' call to that API actually turns on extra errors that were previously turned off. You almost certainly don't want to do that. This arises because of the asymmetry of the error handling in read/write APIs. The profile produces a warning on read, but an error on write. That was quite deliberate. Because the read succeeds you can handle the issue a completely different way - check for the sRGB tag *first* and ignore the ICC profile if it is set. Because the two profiles are recognized as sRGB, along with another five that libpng knows about, the sRGB chunk gets auto-generated on read. You can't have both in a PNG file and most apps don't do ICC, so by generating sRGB on read libpng preserves the sRGB and/or gamma handling in apps that do it. This is why libpng is looking for known sRGB profiles. So if you check for sRGB (png_get_valid(png_ptr, PNG_INFO_sRGB)) you can simply use your favorite sRGB profile in place of whatever is in there. Two of the recognized profiles are the ICC v4 profiles, and two of the others are the latest ICC black scaled/no black scaling profile. If you can't do v4 you want to know about the v4 profiles and, as for the v2 profiles, the right one to choose depends on the CMM, not the PNG; see the discussion on the ICC downloads page. Personally I think this is the best solution because it handles sRGB tagged images with the full CMM based workflow and it allows the user to choose the optimal sRGB profile. That said I strongly recommend that you never write 0 length files. It's pretty standard app programming - write to a temporary and only rename it to the destination if everything succeeds. Some of the Linux guys even want you to sync(2) the whole darned file system before the rename, but I would recommend against that - I think their file system implementation based arguments are flawed.
I couldn't agree more about the atomic file replacing, but let's keep this out of this bug, since it affects *all* our save and export functions, and should probably be solved generically, see bug 139354.
We don't require libz, it's currently an optional dependency. Is this function also available from libpng perhaps? (I have never heard of it). If not, I have absolutely no problem to make libz a hard requirement.
libpng requires libz, so if PNG support is enabled you will be loading libz. libpng doesn't expose any part of zlib, older versions #included <zlib.h> from <png.h> but that doesn't happen any longer either. It's theoretically possible to build a libpng DLL against a static zlib (this happens on Windows), in which case you would end up with an extra DLL dependency, but that would be rare and is, so far as I can see, harmless.
John: I saw the png benign error stuff, but I assumed that this error wasn't one of the benign errors because of the way it's set in libpng. Now that I try it, it actually is a benign error. Thanks. I'll just set benign errors as warnings to fix this bug (we should've probably done this anyway). The atomic file renaming is a good idea. We should look into that more. elle: Is there a big advantage to embedding the icc profile instead of just setting the sRGB chunk? libpng goes to great lengths to try to enforce using the sRGB chunk whenever possible. mitch: We actually do hard-depend on zlib in master. For 2.8, I was planning on making png support depend on zlib as well as libpng (which isn't a big deal because png depends on zlib anyway). At any rate, it looks like it won't be necessary now.
Fixed in master and 2.8. commit 7c493f76f836095adad08205fdfd4522e05e0bd4 Author: Michael Henning Date: Sat Feb 15 22:55:18 2014 -0500 Bug 721135 - Unable to export to .png - error: known incorrect sRGB profile Some libpng errors can safely be marked as nonfatal, which is much better than simply failing in those cases. Thanks to John Bowler for pointing out this solution.
The 'benign_error' control API predates the internal changes I made to separate out different classes of error. We could add more fine-grained control; at present the API can turn off errors (and warnings) that libpng can handle in one way or another and turn on (make hard) all of those cases. It can't do anything inbetween, including restoring the (release) default. It is a reasonable strategy in an application to make any error that can be ignored ignored, but it is not reasonable to do this while testing. libpng pre-RC versions make every class of error a hard error - so if I'm running a pre-RC version on my system every app that encounters any variety of error will get a hard error unless it calls png_set_benign_errors(png_ptr, true). You can do something similar by calling png_set_benign_errors(png_ptr, less-than-rc ? false : true). Of course that will mean you have to handle the problem profile somehow, and that may involve a more sophisticated treatment of sRGB including UI work, but that's probably a good thing. John Bowler
(In reply to comment #25) > elle: Is there a big advantage to embedding the icc profile instead of just > setting the sRGB chunk? libpng goes to great lengths to try to enforce using > the sRGB chunk whenever possible. Embedding sRGB png chunks may be encouraged, but according to the png specs, it looks optional (http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html): "All ancillary chunks [sRGB, cHRM, and gAMA are ancillary] are optional, in the sense that encoders need not write them and decoders can ignore them. However, encoders are encouraged to write the standard ancillary chunks when the information is available, and decoders are encouraged to interpret these chunks when appropriate and feasible." I'm not sure how to quantify "how big" of an advantage there is or might be with using real ICC profiles instead of sRGB png chunks. An automatically embedded sRGB chunk intead of an actual ICC profile seems to imply that in some cases png color management might be handled differently from other file formats, depending on what the image editing software does. Not using sRGB png chunks removes one additional complication from ICC profile color management. What does Gimp actually do when it encounters a sRGB chunk in a png? How does Gimp handle ICC profile conversions "from" the png sRGB chunk to real ICC profiles? I don't know what the actual contents of the sRGB chunk are: does it contain primaries to be used in ICC profile conversions? If libpng didn't flag certain "known to png" sRGB ICC profiles that it has flagged as problematic, this issue wouldn't have come up. Given that libpng does flag certain "known to png" sRGB ICC profiles, I would prefer that Gimp provide the option of allowing the user to substitute an alternative sRGB profile that's acceptable to libpng and to the user (there's a ton of sRGB profile variants out there). I don't use intentionally use any of the profiles that libpng is set up to detect. The problem profile was in a printer test image downloaded from the internet and I don't mind removing the profiles from all such images. But there might be Gimp users who have many images with "known to png" problem profiles. What if libpng expands the current list of "known to png" problem sRGB profiles to include additional sRGB profiles? That might prove to be a real headache to a larger pool of users. Having Gimp ask the user what to do seems like the better option.
I'm having a long off-bug conversation with Elle the brief summary of which is that we disagree on almost everything. The following is slightly different (on the read side) from what I've said before; this addresses one of Elle's concerns, but not most of them. That said there is a pretty straightforward answer to this question: >Is there a big advantage to embedding the icc profile instead of just >setting the sRGB chunk? The answer depends on what the user wants. I think you can deduce this from what the user did: R1) If the user said 'write me an image with *this* profile' then you should write it to the PNG if you can. You have to assume that the user expects the profile to be used in the future. R2) If the user said 'write me an sRGB image' you should write the sRGB tag. The only parameter in the tag is the rendering intent (1 byte). You have to assume that the user wants a 'standard' image, not one with a particular encoding and that the recipient will be able to handle it correctly with just the knowledge that it is sRGB encoded. The condition on (1) is a general one: whenever you record an ICC profile in an image (I think this applies to all images) you need to record the rendering intent too. PNG does not allow this with an iCCP chunk, so if the rendering intent used does not match that in the header you have a problem. At this point if you know the profile is one of the ICC standard ones you should consider writing the sRGB chunk with the rendering intent instead. (Perceptual/absolute colorimetric are interchangeable for ICC v2 sRGB profiles if implemented according to the ICC spec, but I don't know what Gimp does.) The question wasn't asked but there is some corollary on read: R1) [NEW!] If the iCCP chunk is valid, *regardless* of the sRGB setting (which may be set if libpng recognizes the chunk) you should use the embedded chunk when decoding the image and, even though libpng might of told you it is sRGB, you should treat it as *not* sRGB. R2) If the iCCP chunk is not valid but the sRGB chunk is then you should use a standard profile and the rendering intent from the chunk to reverse the encoding. Because you know the rendering intent (from sRGB) you can make an intelligent choice about which of the ICC profiles to use based on the rendering intent and how (or whether) you handle black point corrections. Now by default the output is sRGB and you use the write rules above. The ICC profiles are covered by a license which I believe is no more restrictive than CC BY-ND; the FSF uses this CC license (see the Creative Commons web site). When you encounter one of the two old, broken, profiles that ICC/HP/Microsoft distributed during [R1] I suggest you swap it out for one of the current ICC profiles, probably sRGB_IEC61966-2-1_black_scaled.icc since that is closest to the original. Notice that you load the image with the old, broken, profile and write it with the new one. That way if the user uses 'absolute colorimetric' rendering they get what they apparently expect (a big color shift), which you freeze into the data when it is written out with the new profile (i.e. everyone sees the color shift, not just the author.) Elle will probably disagree strongly on that one ;-) If you don't like this behavior you can certainly produce a new profile which has different adopted and medium white points and otherwise matches the sRGB spec. It's a pretty trivial operation. The result is not sRGB so the profile needs to be embedded, I suggest you consider making it an abstract profile both because that is what it is and because these can be used within PNG files, however these are a little more difficult to produce and tend to be bigger.
You guys should reopen the bug if you keep on discussing :)
(In reply to comment #29) > I'm having a long off-bug conversation with Elle the brief summary of which is > that we disagree on almost everything. This is a true statement :). This comment only covers part of the disagreement. > The ICC profiles are covered by a license which I believe is no more > restrictive than CC BY-ND; the FSF uses this CC license (see the Creative > Commons web site). In the present context by "ICC profiles" John means the sRGB profiles downloadable from the color.org website. The "terms of use" for the two color.org V2 sRGB profiles reads: "To anyone who acknowledges that the files "sRGB_IEC61966-2-1_no_black_scaling.icc" and "sRGB_IEC61966-2-1_black scaled.icc" are provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY, permission to use, copy and distribute these file for any purpose is hereby granted without fee, provided that the files are not changed including the ICC copyright notice tag, and that the name of ICC shall not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. ICC makes no representations about the suitability of this software for any purpose." I agree that this sounds like very much like a CC BY-ND license. But the CC BY-ND license is not compatible with the usual free software licenses (see https://wiki.debian.org/DFSGLicenses, https://en.wikipedia.org/wiki/Comparison_of_free_and_open-source_software_licenses, https://www.gnu.org/licenses/). Also, the Creative Commons license chooser (https://creativecommons.org/choose/) says CC BY-ND is not a free culture license. https://www.gnu.org/licenses/license-list.html Creative Commons Attribution-NoDerivs 3.0 license (a.k.a. CC BY-ND) (#ccbynd) says: "This is the license used throughout the FSF web site. This license provides much the same permissions as our verbatim copying license, but it's much more detailed. We particularly recommend it for audio and/or video works of opinion." So the point of this FSF recommendation for using the BY-ND license is to protect a work of opinion or other work that the author doesn't want modified. The question is whether so protected works can be distributed along with free software. I am not a lawyer and I don't know the answer to this question. > When you encounter one of the two old, broken, profiles that ICC/HP/Microsoft > distributed during [R1] I suggest you swap it out for one of the current ICC > profiles, probably sRGB_IEC61966-2-1_black_scaled.icc since that is closest to > the original. Comparing the "broken" profile and the color.org profile (they are good substitutes for one another): *The sRGB_IEC61966-2-1_black_scaled.icc red, green, and blue colorant values exactly match the "broken" profile colorants. *The original sRGB D65 media white point tag values have been replaced with ICC D50 illuminant values in accord with the V4 way of making V2 ICC profiles, and the sRGB source white point information is contained in the chromatic adaptation ("chad") matrix instead of in the media white point tag. There is one difference between the "broken" profile and the color.org profile: *The "broken" profile has black point tag values of XYZ=(0.0, 0.0, 0.0), which is the correct black point tag for an sRGB ICC profile (normal matrix sRGB profiles, not the new color.org lut sRGB profiles which are a whole other topic). *The color.org sRGB_IEC61966-2-1_black_scaled.icc profile has black point tag values of XYZ=(0.012054, 0.012497, 0.010315). The color.org profile black point disagrees with the profile tone response curves, which start at 0.0 in each channel. This contradiction between the black point tag values and the tone reproduction curves technically makes the color.org profile a faulty, one might even say a "broken" profile. In practice, the color.org profile's contradictory black point tag and tone reproduction curves make no difference at all, as LCMS, ArgyllCMS and probably all CMMs seem to ignore the faulty black point tag. So assigning either profile to an image means the XYZ values that correpond to the image's RGB values don't change one little bit. The two profiles are functionally equivalent. I should point out that assigning the ArgyllCMS sRGB profile OR the new Gimp built-in sRGB profile OR the LCMS built-in sRGB profile in place of the profile that libpng detects as broken WILL change the XYZ values corresponding to the image's RGB values. The XYZ values won't change by much and certainly not enough to be visually obvious, and probably not even measurably in an 8-bit image (depending on the image color gamut). But they will change measurably in a high bit depth image. So if maintaining a high degree of accuracy of the intended XYZ values when writing pngs that contain sRGB profiles that libpng flags as "broken" is a concern, then perhaps a truly free functional equivalent to the color.org V2 sRGB profile should be made. (A problem with the "broken" sRGB *and* the color.org equivalent is that neither one of them is truly neutral.) > Notice that you load the image with the old, broken, profile and > write it with the new one. That way if the user uses 'absolute colorimetric' > rendering they get what they apparently expect (a big color shift), which you > freeze into the data when it is written out with the new profile (i.e. everyone > sees the color shift, not just the author.) Elle will probably disagree > strongly on that one ;-) > This seems to be an argument for why libpng flags some sRGB profiles as broken. It is a reason given by the ICC for prefering V4 CMM and profiles over V2 CMM and profiles. If I understand John correctly, the libpng claim is that these profiles aren't made according to V2 specs and that makes them broken. There are many different versions of V2 specs. It seems to me that a profile should be judged "broken" based only on the version of the spec to which it was written, which informaton is in the header. See http://sourceforge.net/mailarchive/forum.php?thread_name=530152D3.2090502%40argyllcms.com&forum_name=lcms-user for opinions on this topic. See http://justsolve.archiveteam.org/wiki/ICC_profile for download links if you'd like to read the specs and judge for yourself. If the "broken" libpng profiles are broken in part because they don't cohere with some interpretations of how a V2 sRGB profile should be made, then the ArgyllCMS D65 profiles are also broken. As is the AdobeRGB1998 profile and quite a few other V2 profiles. I have a difficult time believing that the people who made and make these profiles didn't read and understand the specs they were/are using. There are V2 and V4 profile specifications, which differ in how absolute colorimetric conversions are done. Then there are V2 and V4 profiles, which differ in how the source white point information is encoded. Then there are CMMs that do things the V2 way, and CMMs that do things the V4 way: If you use an image editing program that uses LittleCMS version 1 as the CMM (Gimp 2.6, early Gimp 2.8?), you must use V2 profiles (unless the program was patched to read V4 profiles) and you will get the V2 profile spec way of doing absolute colorimetric conversions, which if the source profile and destination profile white points differ (eg D65 to D50, D50 to D65), *will* produce a color cast in the converted image. This color cast was intentional, the point being to preserve the white point of the source image. If you don't want the color cast when using a V2 CMM, use relative colorimetric instead. If you use an image editing program that uses LittleCMS version 2 as the CMM (Gimp from git, recent Gimp 2.8), you can use V2 or V4 profiles. Regardless of which type of profile is used for the source and destination profiles, using absolute colorimetric intent will NOT produce a color cast in the destination image. LittleCMS version 2 does things the V4 way, even when the profiles in question are V2 profiles. Converting from the "broken" sRGB profile to the color.org V2 sRGB profile involves a conversion between two profiles with the same D65 source white point (just encoded differently in the two profiles). So even in a V2 workflow using LittleCMS version 1 and using absolute colorimetric intent, the conversion wouldn't have produced a color cast. > If you don't like this behavior you can certainly produce a new profile which > has different adopted and medium white points and otherwise matches the sRGB > spec. It's a pretty trivial operation. The result is not sRGB so the profile > needs to be embedded, I don't understand what John is saying. If the source white point used to make the sRGB profile isn't the sRGB D65 white point, the result is not the sRGB profile. So why do this operation? If the reason is to make a pseudo-sRGB profile for use with a V2 CMM like LMCS version 1, to avoid the color cast from absolute colorimetric conversions between profiles with differing source white points, why not just use relative colorimetric conversion instead? > I suggest you consider making it an abstract profile both > because that is what it is and because these can be used within PNG files, > however these are a little more difficult to produce and tend to be bigger. Here's what the V2 spec linked to on the color.org spec page (http://www.color.org/icc_specs2.xalter) says about abstract profiles: "6.3.4.3 Abstract Profile This profile represents abstract transforms and does not represent any device model. Color transformations using abstract profiles are performed from PCS to PCS. Abstract profiles cannot be embedded in images." The latest V4 ICC spec says the same thing. The required tags show that abstract profiles are LUT profiles. What problem would be solved by making an abstract profile? Why does png allow embedding them? As background information, there is a header field in ICC profiles called "Profile/Device Class". There are only a few allowable values: Input/Display/Output, plus device link, color space conversion, abstract, and named color profiles. Of the three, "color space conversion" sounds like it might be the appropriate type of profile for use as an RGB working space profile. This type of profile can be embedded, but it's also a LUT profile. So it's not appropriate for RGB *matrix* working space profiles like sRGB. Note that the color.org *LUT* sRGB preference profile IS a "color space conversion" profile. But this LUT sRGB profile is not one-for-one functionally equivalent to the "broken" sRGB profile. The standard ICC RGB working space profiles are all *matrix* profiles and they are *all* (whether sRGB, ProPhotoRGB, WideGamutRGB, etc) Display profiles, with "mntr" in the "Profile/Device Class" field. In an ICC profile color-managed workflow sRGB might be a monitor profile (for people who haven't profiled their monitor). But mostly it's an RGB working space profile. Either way, the right Profile/Device Class is "Display" ('mntr'). This Profile/Device Class is *not* limited to actual monitor profiles.
(In reply to comment #16) > libpng only rejects two very specific icc profiles in this way. This is their > rationale behind it (from png.c around line 2185): > > /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does > not > * match the D50 PCS illuminant in the header (it is in fact the D65 values, > * so the white point is recorded as the un-adapted value.) This certainly isn't an argument for rejecting an ICC V2 profile - it's very wide spread and normal practice for V2 ICC profiles to have non-D50 media white points - it's there to record the "media" color so that the meter reading information (absolute colorimetric) information can be recovered in the profile. So libpng has a serious bug if it is using this as the only criteria to reject ICC profiles.
(In reply to comment #31) > If you use an image editing program that uses LittleCMS version 2 as the CMM > (Gimp from git, recent Gimp 2.8), you can use V2 or V4 profiles. Regardless of > which type of profile is used for the source and destination profiles, using > absolute colorimetric intent will NOT produce a color cast in the destination > image. LittleCMS version 2 does things the V4 way, even when the profiles in > question are V2 profiles. Using absolute colorimetric is an unusual thing to do in any normal image transformation. Typically one assumes that the observer is adapted to the white point, which is why the normal intents (relative, perceptual & saturation) are all normalized to the PCS white. Choosing absolute is typically done in a side by side proofing situation, where the observer can't be assumed to be fully adapted, or where one wants to recover the original instrument readings used to create the profile, say for profile verification purposes. ICC V4 display white point handling broke the ability to use absolute colorimetric to recover the instrument readings or do side by side proofing (I regard this as a serious bug in the ICC standard), but that's what the standard says. In my view a useful CMM would compensate for this bug in the ICC V4 spec. by applying the inverse of the chad tag in this situation, so that absolute colorimetric intent behavior for ICC V4 display profiles does something worthwhile. The same argument applies to ICC V2 profiles that adhere to the V4 way of doing things and contain a chad tag.
BTW, above I meant a *colorspace* profile, not an *abstract* one - my error. Colorspace is only in v4 so the comment was pretty irrelevant. lcms-2.5 has a fixup for v2 profiles, cmsiol.c line 70; if the profile version is less than 4 *and* this is a Display profile (i.e. 'mntr') then the mediaWhitePointTag value is returned as D50, i.e. the value from the file is ignored. That's why lcms doesn't show problems with the profile in question. Unfortunately lcms always applies the fix. This is not the libpng approach - it *is* valid for a Display profile to have a mediaWhitePoint value which is not D50, it just means that the display is being viewed by a user who hasn't adapted to the display white. A real world scenario where this may happen is if you are producing output for an electronic photo-frame which is on display in a D50 environment. In that case, curiously, the profile that libpng warns about is actually the right profile so long as absolute colorimetric rendering is used. It is, in fact, this case: > Choosing absolute is typically done in a side > by side proofing situation, where the observer can't be assumed to be fully > adapted, or where one wants to recover the original instrument readings used to > create the profile, say for profile verification purposes. Nevertheless, while it is a valid thing to do with sRGB data on *output* it implicitly assumes that the output *environment* is not sRGB compatible, because it is assuming, as above, that the viewer is not fully adapted. A valid and correct thing to do with the modified image data is to embed the profile. This makes it so that if the data gets reprocessed then absolute colorimetric rendering will restore the original colors. Of course the data has a yellow/red cast to offset the blue cast the viewer observes in the photoframe so it is definitely *not* sRGB data! So the profile in question is certainly valid, I never said it wasn't, the issue is that it does not correspond to the sRGB spec when embedded in an image. It does, in fact, describe something that is *not* sRGB. Unfortunately this is the opposite of the intent of the people who seem to be embedding it, hence the warning. Argyll-cctiff does handle the profile correctly, but it does something weird when a v2 profile contains a 'chad' tag. If I take the chad tag out, or set the mediaWhitePointTag to D50 in a profile without the chromaticAdaptationTag I get what I expect with 'absolute' rendering. I ran the two profiles (two different mediaWhitePointTag values) back-to-back on a single image. With the D65 WP on the input I get a blue cast, on the output I get a yellow one. I still see this with the current sRGB v2 (black scaled) profile but the color cast is reduced - it seems that the 'chad' tag is overriding the contradictory 'wtpt' tag. > > ICC V4 display white point handling broke the ability to use absolute > colorimetric to recover the instrument readings or do side by side proofing I don't see how, it didn't change so far as I can see. The math, using scaling (i.e. the wrong-von-Kries transform) is something like this: Relative colorimetric is generated in the PCS; call these values XYZpcs. To get the absolute values calculate, for each XYZpcs and call the XYZ of the media white point XYZmwp. XYZabsolute = XYZpcs * (XYZmwp/D50) We can see that's right for D50 itself; D50 in the PCS is the media white point and we get XYZmwp when XYZpcs is D50. Equally, when the media white and adopted white are the same XYZmwp will be D50 too and, for that matter, when the adopted white is itself originally D50 (the normal print case) XYZmwp will be equal to the original (unadapted) media white point value. Otherwise XYZmwp: XYZmwp = XYZunadaptedMWP * (D50/XYZadoptedWhite) As I understand it this is what Elle is claiming the ICC changed, but the math for the *output* transform on pages 118 and 119 of the 1998 spec: http://www.color.org/icc-1_1998-09.pdf Seems to me to be the inverse of the input transform I wrote above. The math also produces what is required in the output image - it goes yellow if the MWP is D65 (well, it adapts to D65), and when the profile is used on the input it undoes the yellow by turning the data blue. From above using D65 for XYZmwp: XYZabsolute = XYZpcs * (D65/D50) But that's moot for an sRGB image; the data was never tweaked to make it look right on an otherwise sRGB monitor viewed by a D50 adapted viewer, so the profile shouldn't say it was. John Bowler
(In reply to comment #34) > BTW, above I meant a *colorspace* profile, not an *abstract* one - my error. > Colorspace is only in v4 so the comment was pretty irrelevant. Colorspace profiles are V2 as well - it's been a profile class for a very long time. Both ColorSpaceClass and DisplayClass have been used for standard RGB spaces. > Nevertheless, while it is a valid thing to do with sRGB data on *output* it > implicitly assumes that the output *environment* is not sRGB compatible, > because it is assuming, as above, that the viewer is not fully adapted. Right, but I don't see any relevance - the core purpose of a display color profile is to represent the measured behavior of the display. Everything else including using it to display colors that the user expects under a particular situation is derived from the measurements. > A valid and correct thing to do with the modified image data is to embed the > profile. This makes it so that if the data gets reprocessed then absolute > colorimetric rendering will restore the original colors. Of course the data > has a yellow/red cast to offset the blue cast the viewer observes in the > photoframe so it is definitely *not* sRGB data! I'm not sure what you are saying here. The embedded profile by itself makes no transformation possible except to/from CIE values, and the choice of intent is made when the profile is used, not when it is embedded. So the result of any reprocessing could be to absolute, or it could be white point relative (chromatically adapted), or anything, depending on how the profile gets linked. Properly speaking a colorspace tag should at a minumum describe the XYZ measurement values that correspond to the RGB values. A complication of using ICC profiles is that they store the characterization in a white point normalized form, since this is the default usage mode. Using a profile format that is incapable of representing the XYZ values is in fact a technically poor way of tagging the colorspace, since it is making assumptions about the usage, and absolute->relative can't be undone if the relevant information (the original white point and type of chromatic adaption) has been thrown away. > So the profile in question is certainly valid, I never said it wasn't, the > issue is that it does not correspond to the sRGB spec when embedded in an > image. It does, in fact, describe something that is *not* sRGB. Unfortunately > this is the opposite of the intent of the people who seem to be embedding it, > hence the warning. I can't agree with you there. The profile is a very widely accepted sRGB profile - millions of copies of it exist in the wild - and it is perfectly valid, reasonable and useful sRGB colorspace description. No technical problems exist with it when used with a CMM that knows how to deal with ICC V2 profiles properly, a point that is very easy to demonstrate and illustrate. > Argyll-cctiff does handle the profile correctly, but it does something weird > when a v2 profile contains a 'chad' tag. If I take the chad tag out, or set > the mediaWhitePointTag to D50 in a profile without the chromaticAdaptationTag I > get what I expect with 'absolute' rendering. I ran the two profiles (two > different mediaWhitePointTag values) back-to-back on a single image. With the > D65 WP on the input I get a blue cast, on the output I get a yellow one. I > still see this with the current sRGB v2 (black scaled) profile but the color > cast is reduced - it seems that the 'chad' tag is overriding the contradictory > 'wtpt' tag. Since Argyll icclib doesn't do anything with the chad tag (it doesn't currently claim to support profiles of that version), I'm not sure what you mean by "weird", since the behavior is unchanged. A profile that claims to have a media white of D50 will be treated as if it has a media white of D50. If you do absolute intent links between D65 and D50 white point colorspaces, then yes you will get color casts - that's what you asked for, just like print profiles with different media colors when liked with an absolute intent. [ I can't say I have come across many V2 Display profiles that use the chad tag and set the media to D50, since this was a relatively late addition to the ICC spec., and went against widely established practice. Certainly all the sRGB and AdobeRGB profiles out there don't do this, nor do ArgyllCMS display profiles. Since 99.9% of the time people use a relative link, it is rarely an issue. ] > > ICC V4 display white point handling broke the ability to use absolute > > colorimetric to recover the instrument readings or do side by side proofing > Relative colorimetric is generated in the PCS; call these values XYZpcs. To > get the absolute values calculate, for each XYZpcs and call the XYZ of the > media white point XYZmwp. > > XYZabsolute = XYZpcs * (XYZmwp/D50) Exactly, so if the XYZmwp is D50, we get relative colorimetric values rather than the absolute (ie. measurement) values. We've lost an intent. > But that's moot for an sRGB image; the data was never tweaked to make it look > right on an otherwise sRGB monitor viewed by a D50 adapted viewer, so the > profile shouldn't say it was. I'm not sure what you are talking about. You can't second guess the application or the user intent or the user state of adaptation in the profile. If the application (say) wants to show an absolute XYZ values for (say) side by side proofing to a print illuminated by D55, then it needs to be able to recover the absolute colorimetric values so that it figure out the RGB needed to display white as D55. Setting the media white point tag to D50 makes this impossible using a standard CMM intent like absolute, because you've thrown the needed information away.
This is now very off topic. Bugs in the ICC spec should be upstreamed to the ICC and, anyway, they don't affect *this* bug because it is about the old *ICC* sRGB profile. Back on topic: As I understand gimp, from configure.ac, it uses either lcms1 or lcms2. There doesn't seem to be a provision to use another CMS. I looked at plug-ins/common/lcms.c, it looks like you prefer lcms1 over lcms2 and it looks like the architecture *could* permit another plug-in to be provided without any code change. So I can't be at all sure that LCMS is the only option; for example, maybe someone has implemented an Argyll plug-in, however LCMS is the only option I can see. Nevertheless from an examination of the lcms1 code it seems that it behaves differently in this regard from lcms2. So far as I could see lcms1 preserves the mediaWhitePointTag value on a display profile whereas lcms2 invariably sets it to D50. This also applies to the internally generated sRGB profiles. That means that the lcms plug-in will have radically different behavior with absolute colorimetric rendering depending on which version it uses. If the user uses lcms2 and has a 'display' output profile with a mediaWhitePointTag which is D50 then you should not embed that profile, because it isn't the one that was used! While this is a separate bug if you do fix it, this bug goes away with lcms2. However you probably don't want to do this unless the output is known to be sRGB, because the profile is fine just so long as AbsoluteColorimetric is not used. You could whack on the mediaWhitePointTag before outputting it, but that's a lot of work and raises copyright issues. So what I would suggest is that if you are outputting a *PNG* image using a profile that you know to be ICC-sRGB, because libpng told you it was, you just write the sRGB tag - contrary to what I said above. What is more I suggest you do this for LCMS1 too, because doing a completely absolutely correct solution is going to be a lot of work and is only an issue with LCMS1 and AbsoluteColorimetric rendering! If a user actually gives you the HP/Microsoft profile (which you can detect with MD5 or Adler or CRC32 - lcms already uses MD5), then I suggest you warn them that libpng will issue a warning if it sees the result. "This is a profile published by HP/Microsoft in 1998. It has been superseded by profiles which conform more closely to the intent of the sRGB specification and which are available from the ICC web site www.color.org. If you embed this profile in an sRGB image it can result in unexpected blue color casts if the image is printed."
Please look at git master, lcms1 is just cruft that hangs around in 2.8.
(In reply to comment #36) > So what I would suggest is that if you are outputting a *PNG* image using a > profile that you know to be ICC-sRGB, because libpng told you it was, you just > write the sRGB tag - contrary to what I said above. What is more I suggest you > do this for LCMS1 too, because doing a completely absolutely correct solution > is going to be a lot of work and is only an issue with LCMS1 and > AbsoluteColorimetric rendering! You simply can't assume that sRGB profiles are interchangeable - the colorspace may be well defined, but there are many possible ways of representing it in an ICC profile. You may find that one has a more accurate response for white for instance (ie. R=G=B=1 maps more accurately to D50) than another, and there are lots of ways of making perceptual profiles, etc. etc. If the user gives you a particular profile to tag with, then you had better tag with that profile. > If a user actually gives you the HP/Microsoft profile (which you can detect > with MD5 or Adler or CRC32 - lcms already uses MD5), then I suggest you warn > them that libpng will issue a warning if it sees the result. Why would you do that ? The HP/Microsoft profile is a valid ICC V2 profile. If a profile is badly formed and technically unusable, then yes return an error. But it is not the case here, and a raster format library has no place in making judgements about licensing issues - it simply can't know the legal context. > "This is a profile published by HP/Microsoft in 1998. It has been superseded > by profiles which conform more closely to the intent of the sRGB specification > and which are available from the ICC web site www.color.org. If you embed this > profile in an sRGB image it can result in unexpected blue color casts if the > image is printed." None of libpng or the applications business - they should be staying neutral and doing the best possible work they can. What's more such a statement is simply false - the HP/Microsoft V2 profile has not been superseded - it remains a far more useful profile than most of the attempts to replace it, and therefore has a valuable place in the resources available to the user.
(In reply to comment #37) > Please look at git master, lcms1 is just cruft that hangs around in 2.8. Ok, you now require LCMS 2.2 or later. You only require libpng 1.2.37 or later, which you know about already of course ;-) In fact the write error in question only exists in 1.6 and later, but you should probably disable benign errors where you can (as, indeed, your fix does); there was a policy change in 1.6 whereby recoverable read errors were turned into warnings in release builds. Prior to this recoverable read errors were typically hard-wired as warnings (high ideals gave way to practicality), but some existed. In 1.2, as you know, it was all hard coded - no benign errors to turn on or off. Ok; so when you release that the plug-in will always zap the mediaWhitePoint to D50. You can certainly ignore the error, but you will be passing data down the line to someone else who will see the warning on read. I guess it's up to you what you do about that.
It's better to send these comments to png-mng-implement@sourceforge.net; there are real issues here surrounding the choices I make while writing code, but they will not be resolved here because everything you say convinces me I am right. An open discussion involving many voices is required. I related what libpng does, and what it will do until someone changes the code.
Comment 40 was in reply to Comment 38 (Graeme Gill's). I should probably file a bug against the bugzilla UI, but I can't be asked.
(In reply to comment #34) > XYZmwp = XYZunadaptedMWP * (D50/XYZadoptedWhite) > > As I understand it this is what Elle is claiming the ICC changed Whatever I said, I didn't say it using equations. I'm not fluent enough in matrix math to follow what John's and Graeme's equations actually mean without first spending considerable time pondering the equations. I did say that in V2 profiles the source white point information is in the ICC profile media white point tag, whereas in V4 profiles the source white point information is in the ICC profile chromatic adaptation tag and the media white point tag is the same as the D50 illuminant. I've since learned from a post on the lcms mailing list that my generalization was too broad; not all the older V2 profiles worked this way. However, what I said *does* apply to the Hewlett-Packard V2 sRGB profiles, Adobe's AdobeRGB1998 profile (which uses the same D65 source white point as sRGB), the ArgyllCMS V2 profiles, and to V2 profiles created with lcms version 1. The other alternative was to throw the source white point information away.
(In reply to comment #36) > So what I would suggest is that if you are outputting a *PNG* image using a > profile that you know to be ICC-sRGB, because libpng told you it was, > you just write the sRGB tag - contrary to what I said above. Gimp is a color-managed image editing application which uses lcms2 as the CMM. The CMM, not libpng, is the appropriate software for informing the user when an image has an embedded sRGB ICC profile. If there is no embedded ICC profile in an image, Gimp has user-configurable provisions for assigning an appropriate ICC profile. If the image doesn't have an embedded ICC profile and does have a png sRGB chunk, I presume that there is Gimp code to recognize same, but I don't know for sure because I haven't checked the code. If an image does have a png sRGB chunk (and no ICC profile) and the user wants to edit the image using Gimp, then the logical thing to do is assign the Gimp built-in sRGB profile to the image so the image can be used in an ICC profile color-managed workflow. If the context is exporting an sRGB image to disk for use in a non-ICC-profile-color-managed application that does recognize png sRGB chunks, that's a different matter: presumably at that point ICC profile color-managed image editing is done and the png sRGB chunk could be embedded upon export. It might help to make some careful distinctions in how "sRGB" is used. Case 1: In an ICC profile color-managed workflow, when assigned and/or embedded in an image, the sRGB ICC profile is just another ICC profile, not special and not different in any way from all the other ICC RGB working space matrix profiles that might be used in color-managed image editing. All an sRGB ICC image profile does in a color-managed workflow is tell the CMM how to translate the image RGB values to XYZ. That's all that any ICC RGB matrix profile does. Case 2: In an ICC profile color-managed workflow, if someone is unfortunate enough to still be using an sRGB ICC profile as their LCD monitor profile, then the sRGB ICC profile is being used as a monitor ICC profile. The case where an sRGB ICC profile is used as a monitor ICC profile is completely separate from and independent of the case where the sRGB ICC profile is being used as an *image* ICC profile. Cases 1 and 2 can happen at the same time, but the two sRGB ICC profiles (which might or might not be the exact same sRGB ICC profile) are being used for two conceptually distinct purposes, once as the image ICC profile and once again as the monitor ICC profile. The fact that 'mntr' is used in the header of monitor profiles and also in the header of matrix RGB working space profiles probably has an historical rather than logical rationale: the first RGB working spaces (eg sRGB, ColorMatchRGB, AppleRGB, others?) actually were monitor-based profiles, the assumption being that the monitor had been appropriated calibrated to match the profile. Case 3: Cases 1 and 2 are completely separate from and shouldn't be mixed up with situations where sRGB refers to the D65 sRGB color space as described by the sRGB specs, the context being sending RGB signals to an sRGB display device without using ICC profile color management. The D65 sRGB color space and the D50-adapted sRGB ICC profile are not the same thing.
(In reply to comment #40) > It's better to send these comments to png-mng-implement@sourceforge.net; there > are real issues here surrounding the choices I make while writing code, but > they will not be resolved here because everything you say convinces me I am > right. An open discussion involving many voices is required. > > I related what libpng does, and what it will do until someone changes the code. I would suggest opening two separate libpng bug reports: 1. Whether libpng should be flagging embedded sRGB ICC profiles on the basis that they aren't good sRGB profiles. 2. Whether libpng should be flagging embedded sRGB ICC profiles to see whether a license might have been violated. It seems to me that this responsibility lies with the person using the profile, not with libpng. Is sending an email to png-mng-implement@sourceforge.net the accepted procedure for opening a bug report regarding libpng code, which is a separate sourceforge project? If an email is sent to png-mng-implement@sourceforge.net, where will the bug report(s) appear?
(In reply to comment #44) > I would suggest opening two separate libpng bug reports: It needs to go to the discussion list because you and Graeme are questioning policy decisions. Libpng bug reports can't handle such things. (1) When we encounter the old HP/MS profile that was written on the assumption that the user was adapted to D50 light do we regard it as sRGB, warn about it, refuse to allow it to be written out again by default? (We currently warn on read and error on app (benign) error on write, that's a warning with gimp.) (2) When we encounter a profile that has the MD5 signature of one of the new ICC ones do we validate the profile checksum (which we use for older v2 profiles) and if we do and get a mismatch, do we issue a warning or an error and, if so, what is the wording? The current behavior is to issue a chunk error which can be ignored (and currently is by gimp.) View the libpng home page for more information (www.libpng.org)
(In reply to comment #45) > (In reply to comment #44) > > I would suggest opening two separate libpng bug reports: I opened a thread on the png-mng-implement mailing list: http://sourceforge.net/mailarchive/forum.php?thread_name=530605D7.6010606%40ninedegreesbelow.com&forum_name=png-mng-implement > (2) When we encounter a profile that has the MD5 signature of one of the new > ICC ones do we validate the profile checksum (which we use for older v2 > profiles) and if we do and get a mismatch, do we issue a warning or an error > and, if so, what is the wording? The current behavior is to issue a chunk > error which can be ignored (and currently is by gimp.) The question isn't what libpng should do if it detects a potential violation of an ICC profile's license. The question is whether libpng should include code that tries to detect whether an embedded ICC profile might violate the profile's license. It seems to me that imaging and file format software shouldn't take on the role of "profile police". Responsibility for complying with ICC profile licenses belongs with the user, not the software.
(In reply to comment #45) > (In reply to comment #44) > > I would suggest opening two separate libpng bug reports: I opened a thread on the png-mng-implement mailing list: http://sourceforge.net/mailarchive/forum.php?thread_name=53061378.2040201%40ninedegreesbelow.com&forum_name=png-mng-implement > (1) When we encounter the old HP/MS profile that was written on the assumption > that the user was adapted to D50 light do we regard it as sRGB, warn about it, > refuse to allow it to be written out again by default? (We currently warn on > read and error on app (benign) error on write, that's a warning with gimp.) What options libpng should provide when libpng detects what it thinks is a broken profile is one question. The prior question that needs addressing is whether libpng correctly detects broken sRGB profiles. The libpng code does a checksum to see if certain sRGB profiles are embedded in a png file. The reason given in the libpng code for doing the checksum is that the profile has a D65 media white point. In actual fact all the old HP sRGB profiles that I've ever seen have a D65 media white point tag, as do all D65 V2 profiles made with ArgyllCMS and with LittleCMS version 1. If one of them is broken because it has a D65 media white point tag, they are all broken. The flagged profile isn't broken and flagging it as such causes problems for software that uses libpng and for users who have png files with the flagged profiles embedded.
To be honest, you guy produced too much text here after the bug was already fixed. Is there any outcome of the discussion that would require further changes to *this* bug? If so we can close the bug. If needed, please file new bugs and link to this one, or transfer the relevant information to the new bugs.
(In reply to comment #48) > To be honest, you guy produced too much text here after the bug was > already fixed. Sorry Mitch! Mea culpa. > Is there any outcome of the discussion that would require > further changes to *this* bug? If so we can close the bug. No, as long as GIMP completely ignores the libpng warnings about incorrect embedded ICC profiles, that's all that needs to be done. If libpng ever makes the detection of "wrong" profiles break using libpng, that would be when to open a new bug.
Thanks Elle :)