GNOME Bugzilla – Bug 753163
Add blend mode "RGB Luminance"
Last modified: 2017-02-22 07:08:55 UTC
Created attachment 308643 [details] matlab/octave code to confirm theory above As I pointed out in Bug https://bugzilla.gnome.org/show_bug.cgi?id=325564 (already fixed) the newly added layer blend mode raises some issues: In LCH color model - increasing lightness desaturates colors - decreasing lightness oversaturates colors This the desired behaviour of this color model, that preserves "chromaticity". For a natural lightness scaling, one has to add "cromaticity" when increasing lightness. This can easily be understood looking at the specific formulas of the LCH / XYZ Color model. The desired behaviour might be another one, when considering what physically happens, when taking a photo. The lightness is definded by the amount of light hitting the film (longer exposure duration). So doubling exposure time doubles the amount of light (R, G and B) hitting the film or the sensor, what increases lightness. This leads to the idea to just scale the old lightness (or luminosity) of an image to the new desired one. The ratio of original and new lightness is used to scale all image compontents (RGB). This does of course only work in linear light (RGB). The proposed method - doesnt require transformation to Cie LCH (less computational effort) - doesn't cause color-shifts (hue locked by nature) - is similar to the "gegl:exposure" idea - maybe has potential for improving a lot of related functions (curves tool, ... Cheers, Immanuel
Created attachment 308647 [details] example - original image
Created attachment 308648 [details] example - desired lightness
Created attachment 308649 [details] example - result "luminosity LCH" blending
Comment on attachment 308649 [details] example - result "luminosity LCH" blending former dark areas with strongly increased lightness are heavily desaturated... (left side)
Created attachment 308650 [details] example - result with proposed method "exposure scaling" gives the most "natural" results.
Comment on attachment 308643 [details] matlab/octave code to confirm theory above for octave compatibility the cieLAB-stuff (lines 60...85, 87, 89, 96, 97) must be commented out.
Created attachment 309200 [details] octave file This is the adapted octave file. Previous matlab version uses CIELAB-functions not supported by octave. Also reordered inline subfunctions for octave compatibility.
Created attachment 309838 [details] [review] patch
This all seems very well researched, but I have no clue if it's right :) Opinions anyone?
Created attachment 309866 [details] Adjust the global tonality, then apply the tone-mapping using LCH Lightness As Immanuel demonstrated, applying his desired tonality (https://bug753163.bugzilla-attachments.gnome.org/attachment.cgi?id=308648), in the Lightness blend mode, over the original image (https://bug753163.bugzilla-attachments.gnome.org/attachment.cgi?id=308647) leads to severely desaturated shadows, as shown in (https://bug753163.bugzilla-attachments.gnome.org/attachment.cgi?id=308649). In the real world, and in the CIELAB color space, colors with a very low Luminance also have a very low Lightness, and all colors with a low Lightness also have a low Chroma. So raising the Lightness of a "low Lightness/low Chroma" color gets you a "high Lightness/low Chroma" color. As Immanuel says, exposure compensation does simultaneously raise the Lightness/Luminance and also the LCH Chroma of the color. So using the tools currently available in GIMP 2.9, the way to get Immanuel's desired tonality and color is to: First raise the tonality of the shadows by about 3-4 stops, until the shadow area's overall Luminance matches the desired final Luminance. But you can't use the Lightness blend mode to do this. You have to use some combination of Levels or Curves (moving all three channels together), GEGL's exposure compensation, even Mantuik/etc tone-mapping, combined with masks and layers to only affect the shadows. Then apply the desired final tonality (the example image was created by tone-mapping a black and white rendition of the original image?) using the LCH Lightness blend mode. But you have to do the exposure compensation first. For example, in the attched image: Image 1, upper left corner, is Immanuel's original image. Image 2, lower left corner, was produced using GIMP to raise the shadows on a second layer by about 4 stops, and then blending the two layers together. Actually it took several layers to produce Image 2, which is normal when trying to raise severely underexposed shadows. Image 3 is Immanuel's desired final tonality. Image 4 is Image 3 blended over Image 2 using LCH Lightness blend mode. I think the request is to add a new layer blend mode to GIMP that will accomplish increasing the exposure compensation of the shadows automatically in the background if a suitable second layer is placed over the first layer using "blend mode X" (not sure what to call the proposed blend mode). This new blend mode would allow the user to achieve the desired final tonality and color, by blending a black and white layer with the desired final tonality, over the original color image with the underexposed shadows.
(In reply to Michael Natterer from comment #9) > This all seems very well researched, but I have no clue if it's right :) > Opinions anyone? I just compiled the suggested changes in the LCH Lightness blend mode. It does a very nice job, at least with Immanuel's "desired tonality" over "original image". But imho it shouldn't be used to replace the current LCH Lightness blend mode, because, well, it isn't the actual LCH Lightness blend mode, and the proposed code changes would make it impossible to do real LCH Lightness blending. It seems like it would make a very useful new blend mode. If someone tells me what the new blend mode should be called, I can try to code up a patch, if you like (I may code one up anyway, so I can use try using it for actual image editing). But I'm not sure if you are ready to add new blend modes to GIMP at this point.
Created attachment 309916 [details] CIELCH and relatives (LSH): Lightness mapping has inaccurate saturation compensation See attachment IMG_7912sml_blend_LSH.jpg In CIE LCH colorspace and also in all its derivatives like CIE LAB and CIE LSH (the latter does some Saturation Compensation) it is impossible to perform an accurate Saturation compensation, when changing the L-channel. This is because of the linear approximation of L, A and B Channel for low lightnesses and also for low Chromaticities used by CIE LAB color model. This behaviour (saturation shift) can also be seen in the when using Chroma-Scaling in Darktables luminance-control curve. (as I described here: https://bugzilla.gnome.org/show_bug.cgi?id=325564#c107) So IMHO the saturation-aware change of lightness is bound to RGB color model or the color model of the recording device.
Just a few remarks: - of course, the main purpose of the suggested blend mode is not just for brightening underexposed images, maybe "lightness mapping" is a more "general". It is suitable for operations, that exclusively are done in L-Channel, but shouldn't affect saturation like true lightness (LCH) blending. - for instance, I created the desired tonality/lightness with the gegl:c2g operation on L-Channel (or Y-Channel). But one could also use Y-Channel of gegl:Reinhard 05 etc... - the gimp tools "levels" and "curves" do not maintain color / saturation, despite they do control all 3 channels simultaneously. Gegl:exposure (and the proposed blend mode) does protect color/saturation. Impressive Demonstration: A) inverting the slope of "curves" inverts lightness and colors. B) Extract the L-Channel into new layer and set the new blend mode. Then invert the L-Channel-Layer with "curves" or play around with "curves" --> Color/Saturation remains, while L is inverted or whatever changed. - "Curves" works completely different from controlling lightness channel (x-axis of "curves" is completely independent from lightness). --> see also bug https://bugzilla.gnome.org/show_bug.cgi?id=109161 ISSUES: - most jpegs from cameras do have a certain degree of oversaturation especially in mid-tones and shadows. (desired behaviour --> vendor-specific "base-curves") The new blend mode works better with linear "base-curve" (nothing new, see darktable documentation) - clipping: does turning luminance to maximum cut off color-information? This should be handled by color-management!?
(In reply to immanuel from comment #12) > In CIE LCH colorspace and also in all its derivatives like CIE LAB and CIE > LSH (the latter does some Saturation Compensation) it is impossible to > perform an accurate Saturation compensation, when changing the L-channel. > > This is because of the linear approximation of L, A and B Channel for low > lightnesses and also for low Chromaticities used by CIE LAB color model. Changing LCH Lightness always leaves LCH Chroma alone, regardless of whether the color in question has a low or high LCH Lightness. So the linear portion of the transform from XYZ to LAB doesn't seem relevant to this bug report. > So IMHO the saturation-aware change of lightness is bound to RGB color model > or the color model of the recording device. Is it possible that we are dealing with multiple definitions of Lightness? In any event, unlike modifying chroma in the LCH color space, if you modify "saturation/colorfulness" using various RGB editing operations, then yes, you will get different results in different color spaces. These types of operations involve multiplication, which is a chromaticity-dependent editing operation. I'm not sure what any of the above has to do with the proposed new blend mode, except to reiterate that the LCH L blend mode doesn't accomplish the same goal. But that's already been established.
(In reply to immanuel from comment #13) > - the gimp tools "levels" and "curves" do not maintain color / saturation, > despite they do control all 3 channels simultaneously. Gegl:exposure (and > the proposed blend mode) does protect color/saturation. Actually, Color/Levels/Value channel adjustments (which adjust all three channels together at once) and Color/Exposure, making the equivalent adjustments for each operation, do give exactly the same results. If they don't, there's something wrong with one or the other algorithm. But I just checked and they do give the same results. The same is true for Curves, except for clipping issues if the original or final image has any out of gamut RGB values.This is because unlike Exposure and Levels, Curves clips out of gamut channel values. As an example: 1. Open an image (use a tiff, jpeg, or png, because openexr files are handled differently). 2. Convert the image to 32-bit floating point *gamma* precision. 3. Convert to the GIMP built-in sRGB profile. 4. Convert the image to 32-bit floating point *linear* precision. 5. To add 2 stops of exposure: a. With Colors/Exposure, move the Exposure slider to 2.0. Don't use the gamma hack. b. With Levels, move the upper right slider from 100.00 to 25.00. *Do* check the gamma hack. Or stay in gamma precision, don't use the gamma hack, and move the upper right slider to around 54, but it doesn't produce quite the same results, as you can see if you use the Difference blend mode. I don't know why there is a difference here. c. With Curves, move the upper right end of the Curve from 100 to 25.00. *Do* check the gamma hack. Or stay in gamma precision, don't use the gamma hack, and move the upper right end of the curve to 54, with same considerations as for using Levels in gamma precision. > Impressive Demonstration: Unless you were operating exclusively on linearized RGB, your examples probably mostly show that you weren't operating exclusively on linearized RGB. The GIMP UI in this regard is beyond confusing. For example, assuming the image is in GIMP's built-in sRGB color space: * Colors/Invert always works on perceptually uniform RGB, so don't use it for inverting an image, or at least don't expect the results to match what you'd get if the operation were done on linearized RGB. The workaround is to stay at gamma precision and convert the image to a true linear gamma color space, do the inversion, and then convert back to the GIMP built-in sRGB color space. * Using Curves to invert on linearized RGB, use linear precision and *do* use the gamma hack, but out of gamut colors will be clipped. * Using Levels bottom slider to invert on linearized RGB, use linear precision and *do* use the gamma hack. Out of gamut colors won't be clipped. See here for how to patch GIMP to avoid all these issues: http://ninedegreesbelow.com/photography/patch-gimp-in-prefix-for-artists.html. Then convert to a true linear gamma color space (profiles can be downloaded from http://ninedegreesbelow.com/photography/lcms-make-icc-profiles.html), so you know for sure that you are operating on linear RGB. It would be much less confusing if the linear vs. gamma precisions were eliminated from GIMP, and the user had the option to specifically choose whether to operate on linearized or perceptually uniform RGB, for every RGB operation, with good defaults. > ISSUES: > - most jpegs from cameras do have a certain degree of oversaturation > especially in mid-tones and shadows. (desired behaviour --> vendor-specific > "base-curves") The new blend mode works better with linear "base-curve" > (nothing new, see darktable documentation) > - clipping: does turning luminance to maximum cut off color-information? > This should be handled by color-management!? I don't understand what you are asking.
I just wanted to make clear, that even LSH color model, which introduces a chromaticity-lightness-dependency in LCH colorspace is mathematically not able to keep saturation constant over lightness. Maybe this comment doesn't save the world :-) (you described it here: https://bugzilla.gnome.org/show_bug.cgi?id=325564#c106 (http://www.handprint.com/HP/WCL/color3.html#satvsval)
(In reply to Elle Stone from comment #15) > (In reply to immanuel from comment #13) > > - the gimp tools "levels" and "curves" do not maintain color / saturation, > > despite they do control all 3 channels simultaneously. Gegl:exposure (and > > the proposed blend mode) does protect color/saturation. > > Actually, Color/Levels/Value channel adjustments (which adjust all three > channels together at once) and Color/Exposure, making the equivalent > adjustments for each operation, do give exactly the same results. If they > don't, there's something wrong with one or the other algorithm. But I just > checked and they do give the same results. The same is true for Curves, > except for clipping issues if the original or final image has any out of > gamut RGB values.This is because unlike Exposure and Levels, Curves clips > out of gamut channel values. > > As an example: > 1. Open an image (use a tiff, jpeg, or png, because openexr files are > handled differently). > 2. Convert the image to 32-bit floating point *gamma* precision. > 3. Convert to the GIMP built-in sRGB profile. > 4. Convert the image to 32-bit floating point *linear* precision. > 5. To add 2 stops of exposure: > > a. With Colors/Exposure, move the Exposure slider to 2.0. Don't use the > gamma hack. > > b. With Levels, move the upper right slider from 100.00 to 25.00. *Do* > check the gamma hack. Or stay in gamma precision, don't use the gamma hack, > and move the upper right slider to around 54, but it doesn't produce quite > the same results, as you can see if you use the Difference blend mode. I > don't know why there is a difference here. > > c. With Curves, move the upper right end of the Curve from 100 to > 25.00. *Do* check the gamma hack. Or stay in gamma precision, don't use the > gamma hack, and move the upper right end of the curve to 54, with same > considerations as for using Levels in gamma precision. > > > Impressive Demonstration: > > Unless you were operating exclusively on linearized RGB, your examples > probably mostly show that you weren't operating exclusively on linearized > RGB. The GIMP UI in this regard is beyond confusing. For example, assuming > the image is in GIMP's built-in sRGB color space: > > * Colors/Invert always works on perceptually uniform RGB, so don't use it > for inverting an image, or at least don't expect the results to match what > you'd get if the operation were done on linearized RGB. The workaround is to > stay at gamma precision and convert the image to a true linear gamma color > space, do the inversion, and then convert back to the GIMP built-in sRGB > color space. > > * Using Curves to invert on linearized RGB, use linear precision and *do* > use the gamma hack, but out of gamut colors will be clipped. > > * Using Levels bottom slider to invert on linearized RGB, use linear > precision and *do* use the gamma hack. Out of gamut colors won't be clipped. > > See here for how to patch GIMP to avoid all these issues: > http://ninedegreesbelow.com/photography/patch-gimp-in-prefix-for-artists. > html. Then convert to a true linear gamma color space (profiles can be > downloaded from > http://ninedegreesbelow.com/photography/lcms-make-icc-profiles.html), so you > know for sure that you are operating on linear RGB. > > It would be much less confusing if the linear vs. gamma precisions were > eliminated from GIMP, and the user had the option to specifically choose > whether to operate on linearized or perceptually uniform RGB, for every RGB > operation, with good defaults. > > > ISSUES: > > - most jpegs from cameras do have a certain degree of oversaturation > > especially in mid-tones and shadows. (desired behaviour --> vendor-specific > > "base-curves") The new blend mode works better with linear "base-curve" > > (nothing new, see darktable documentation) > > - clipping: does turning luminance to maximum cut off color-information? > > This should be handled by color-management!? > > I don't understand what you are asking. Sorry, maybe I expressed myself too difficult. I just wanted to say: - "curves" does definitely alter colorfulness/saturation/chromaticity. No matter, whether linear or gamma precision: - Easier example: horizontal line@50% --> results always in gray image. - draft a "sine-curve" --> the effect in color-change is obvious. - there is only one "special case", where "curves" has no impact on hue/saturation: straigt line with origin 0, 0 (only linearized RGB!). Then all channel values are multiplied with the same factor. And this is indeed, what gegl:exposure is doing and what the suggested blend mode would be doing pixel by pixel. - the suggested blend mode never changes hue or saturation, it maybe has just to struggle with clipping issues (high chromaticity @ maximum Lightness). And yes, maybe I do mix up lightness definitions. Unfortunately I've got limited brain. :-)
Created attachment 309974 [details] [review] Patch to create new blend mode "Luminance (RGB)" Probably "Lumunance (RGB)" is the right name for the new blend mode. My apologies, I meant to add Immanuel's name to the copyright information for gimpoperationluminancemode.c/h, but I don't know the right first/last name to use.
(In reply to immanuel from comment #17) > (In reply to Elle Stone from comment #15) > > (In reply to immanuel from comment #13) > > > This should be handled by color-management!? > > > > I don't understand what you are asking. > > Sorry, maybe I expressed myself too difficult. I just wanted to say: > - "curves" does definitely alter colorfulness/saturation/chromaticity. No > matter, whether linear or gamma precision: It was the part about "handled by color management" that I didn't understand. > - Easier example: horizontal line@50% --> results always in gray image. > - draft a "sine-curve" --> the effect in color-change is obvious. > - there is only one "special case", where "curves" has no impact on > hue/saturation: straigt line with origin 0, 0 (only linearized RGB!). You are absolutely right, anything other than a straight-line curve that passes through (0,0) does modify saturation. Whether done using linear or perceptually uniform RGB, straight-line curves through (0,0) shouldn't modify saturation, except for clipping issues. > And yes, maybe I do mix up lightness definitions. Unfortunately I've got > limited brain. :-) Well, if your brain is limited, mine is too. When it comes to describing color and tonality, there are too many diverse concepts - some technical and well-defined, some quite informal - all making use of too few terms. You've done a lot of research on why the LCH Lightness blend mode doesn't accomplish a very important editing goal. I was having trouble following some of your arguments, which is why I asked if we were sometimes using different definitions of Lightness.
Created attachment 314676 [details] [review] changes the copyright information The only thing this new attachment changes is adding an additional copyright line to two files. I've been using the RGB Luminance blend mode for awhile now, and I can't imagine editing without it, it's that useful. Imho, it should be made part of the GIMP 2.10 release. It's not a replacement for LCH Lightness. It's a different and equally useful blend mode. Sometimes the two blend modes give the exact same result, sometimes close to the same, and sometimes very different results, depending on the editing task. I explain the differences and suggest some uses for both blend modes in this article: http://ninedegreesbelow.com/photography/high-bit-depth-gimp-tutorial-edit-tonality-color-separately.html#awesome-Luminance-blend-mode
Created attachment 345048 [details] [review] Updates the patch to GIMP code as of January 21 2017 I haven't succeeded in updating the patch to GIMP master code current as of February 06 2017. But here's a patch that applies to GIMP master code through January 21 2017, commit a1b844897c4581a8af2017c40a6c8f124a09b48d.
Created attachment 345052 [details] [review] unsuccessful attempt at a patch to add Luminence blend to current GIMP code A lot happened to the layer blend code between January 21 2017 and February 6 2007. This patch fails with the following error messages: gimpoperationluminance.c: In function 'gimp_operation_luminance_process': gimpoperationluminance.c:86:3: error: unknown type name 'GimpOperationPointLayerMode' GimpOperationPointLayerMode *layer_mode = (gpointer) operation; ^ gimpoperationluminance.c:90:61: error: request for member 'opacity' in something not a structure or union layer_mode->opacity, ^ gimpoperationluminance.c:92:61: error: request for member 'blend_trc' in something not a structure or union layer_mode->blend_trc, ^ gimpoperationluminance.c:93:61: error: request for member 'composite_trc' in something not a structure or union layer_mode->composite_trc, ^ gimpoperationluminance.c:94:61: error: request for member 'composite_mode' in something not a structure or union layer_mode->composite_mode); ^ gimpoperationluminance.c: At top level: gimpoperationluminance.c:167:1: error: conflicting types for 'gimp_operation_luminance_process_pixels' gimp_operation_luminance_process_pixels (gfloat *in, ^ In file included from gimpoperationluminance.c:33:0: gimpoperationluminance.h:54:10: note: previous declaration of 'gimp_operation_luminance_process_pixels' was here gboolean gimp_operation_luminance_process_pixels (gfloat *in, ^ gimpoperationluminance.c: In function 'gimp_operation_luminance_process_pixels': gimpoperationluminance.c:188:3: warning: return makes pointer from integer without a cast return TRUE; ^ gimpoperationluminance.c: In function 'gimp_operation_luminance_process': gimpoperationluminance.c:95:1: warning: control reaches end of non-void function [-Wreturn-type] } If anyone has some hints as to how to procede, that would be great.
Created attachment 345064 [details] [review] patch that makes a placeholder for Luminance blend This patch adds a "Luminance placeholder" blend mode. In other words, all the "other stuff" is in place to add a Luminance blend mode. But the function "blendfun_luminance" just sets "out" equal to "src". So the next step is to add some code that actually produces a Luminance blend.
Comment on attachment 345052 [details] [review] unsuccessful attempt at a patch to add Luminence blend to current GIMP code see comment 22
Comment on attachment 345048 [details] [review] Updates the patch to GIMP code as of January 21 2017 see comment 21
Elle's patches require Immanuel's patch, I assume? What is the state of Immanuel's patch?
(In reply to Michael Schumacher from comment #26) > Elle's patches require Immanuel's patch, I assume? What is the state of > Immanuel's patch? Elle's patch doesn't actually require any modification to Immanuel's patch as Elle already incorporated the code from Immanuel's patch into attachment 345048 [details] [review]. Immanuel's code for Luminance blend has been part of my patched GIMP for a long time now. It works very well to solve the problem that Immanuel describes. It would be wonderful to add this blend mode to default GIMP. Attachment 314676 [details] from November 2015 worked just fine with default GIMP (and my patched GIMP) until the recent radical modifications to GIMP's layer blend mode code. Attachment 345048 [details] could have been applied to recent GIMP code before January 21, 2017. But it won't work with GIMP code after January 21, 2017. To work with GIMP code as of February 2017, the "working parts" of attachment 345048 [details] [review] - that is, the code in the files app/operations/layer-modes/gimpoperationluminance.c(h) created by the patch - need to somehow be "transplanted" into the placeholder code in attachment 345064 [details] [review], into the function "blendfun_luminance"
Comment on attachment 309838 [details] [review] patch Ok, so this is obsoleted by the more recent patch.
Comment on attachment 345064 [details] [review] patch that makes a placeholder for Luminance blend see comment 23
Created attachment 346199 [details] gimpoperationluminance.c (In reply to Michael Schumacher from comment #29) > Comment on attachment 345064 [details] [review] [review] > patch that makes a placeholder for Luminance blend > > see comment 23 To summarize the current state of the patches, see comment 27. I have attached gimpoperationluminance.c (to avert any need to actually apply patch 345048). The code in this file needs to be somehow put into blendfun_luminace created by attachment 345064 [details] [review].
Created attachment 346249 [details] [review] patch that works with code as of Feb 20 2017 This patch can be applied to GIMP code as of commit eeebd98005deb6e6a41776d23e56d678c7e16a11 on February 20, 2017. This patch includes "sort of working" code for blendfun_luminance. The code only "sort of works" because it looks like it processes the entire image for every pixel that's processed. This is because I'm not quite sure how to "translate" pre-January-21-2017 code to more recent code. Please look at the patch. I'm sure it can be fixed to "work all the way" instead of only "sort of work".
commit ae03b155226e1297e2956f0d5bd7933a988afd60 Author: Øyvind Kolås <pippin@gimp.org> Date: Mon Feb 20 13:53:33 2017 +0100 app: make blendfunction of RGB luminance work again commit aaed8a6eb95af8d98ebf0102acc7a3eca5857914 Author: Elle Stone <ellestone@ninedegreesbelow.com> Date: Mon Feb 20 05:26:51 2017 -0500 app: Bug 753163 - Add blend mode "RGB Luminance" This adds a blend mode similar to CIE Luminance - but that does not alter saturation.