[even worse] Photoshop CC 2019: Apply Image, Soft Light, and the 6-years old "50% Gray in 16-bit mode" bug (+ workaround)

  • 3
  • Problem
  • Updated 2 months ago
I got no answer in the comments, so I'm posting this as a new issue.

------------

I'm afraid the problem from my previous post (click for details) is NOT fixed

In version 20.0.3 the problem is even worse than before :( Now there is no easy way(*) of getting idempotent apply image with aforementioned settings (that is: creating a gray value that would not be affected at all by applying the Apply Image). It seems that you have corrected the gray value in one place (the "New layer" dialog) but forgot to correct it in the "Apply image" function.

From your own manual ( https://helpx.adobe.com/photoshop/using/channel-calculations.html#add_and_subtract_blending_modes ), the "Add" mode in Apply Image should work as follows: "Add mode divides the sum of the pixel values by the Scale amount, and then adds the Offset value to the sum."

Using the 50% gray color = (128,128,128) = 0x808080, filling with that color and using the info panel to read out the 16-bit values, we get the gray value of 16384. So we should be able to assume that 128 (8-bit) == 16384 (16-bit).

For 2 layers containing "Photoshop-correct 16-bit 50% gray" (that is: 16384) the Apply Image settings {Blending: Add, Scale: 1, Offset: -128}, we should get (16384+16384)/1 - convert_to_16bit(128) = 2 * 16384 - 16384 = 16384.

But in the current version (20.0.3) of Photoshop we get an incorrect value: (16384+16384)/1 - convert_to_16bit(128)=16320. From that we can calculate convert_to_16bit(128)= (16384+16384)/1 - 16320 = 32768-16320 = 16448 (wrong value). Should be 16384.

(*) To get a gray value that doesn't change after Apply Image, we have to produce the 16448-gray value. Fortunately the old trick still works: create the 16448-gray layer, create new fill layer with the color of #010101, fill 75%, opacity 66%, blend mode Linear Dodge (Add). Merge those two layers to get a 16448-gray layer.  Now proceed from the step 3 of the section "Steps to reproduce (with incorrect 50% gray value 16448)". You also can use the method from the section: Workaround (with some losses).
Photo of Damian Sepczuk

Damian Sepczuk

  • 11 Posts
  • 1 Reply Like
  • hopeless

Posted 2 months ago

  • 3
Photo of eartho

eartho, Champion

  • 1048 Posts
  • 311 Reply Likes
Really sucks that this has never been fixed, but i can imagine that the code relating to the bug is ancient and buried deep within.
Out of curiosity, what do you use this process for?
Photo of Damian Sepczuk

Damian Sepczuk

  • 11 Posts
  • 1 Reply Like
It bite me, when I created an action to join multiple Soft Light layers Each layer had non-gray content in a different place and I wanted all modifications on a single layer: take a layer, offset it by 50% gray (a.k.a "128") and add the offset to the "master soft light" layer.

It seems fine at first, but then I noticed that my image was getting progressively darker and darker. The change is so minute that it is nearly impossible to see after just one Apply Image. But after doing that 20 times the effect got very noticeable. Just like in boiling frog...
Photo of Damian Sepczuk

Damian Sepczuk

  • 11 Posts
  • 1 Reply Like
but i can imagine that the code relating to the bug is ancient and buried deep within
Maybe it is. But I was able to "fix" it using adjustments and adjustment layers (see my original post). Well, sort of... I'm loosing ~1/256th of the full 16-bit range on the merged layers (once!), but I can live with it. I bet that Adobe, with access to the source code, can do much better, can't they? ;)
Photo of Jeffrey Tranberry

Jeffrey Tranberry, Sr. Product Manager, Digital Imaging

  • 15339 Posts
  • 2229 Reply Likes
Hi Damian,

Regarding:

Using the 50% gray color = (128,128,128) = 0x808080, filling with that color and using the info panel to read out the 16-bit values, we get the gray value of 16384. So we should be able to assume that 128 (8-bit) == 16384 (16-bit).

For 2 layers containing "Photoshop-correct 16-bit 50% gray" (that is: 16384) the Apply Image settings {Blending: Add, Scale: 1, Offset: -128}, we should get (16384+16384)/1 - convert_to_16bit(128) = 2 * 16384 - 16384 = 16384.

But in the current version (20.0.3) of Photoshop we get an incorrect value: (16384+16384)/1 - convert_to_16bit(128)=16320. From that we can calculate convert_to_16bit(128)= (16384+16384)/1 - 16320 = 32768-16320 = 16448 (wrong value). Should be 16384.

Here is an explanation from the Photoshop architect:

The fundamental error the customer is making is that 128 or #80 in 8-bit does not map to 16384 in 16-bit. 0 in 8-bit maps to 0 in 16-bit. 255 in 8-bit maps to 32768 in 16-bit. The mappings in between are linear. There is no 8-bit value that maps to 16384 in 16-bit. Middle gray in 16-bit is exactly 16384. 127 in 8-bit maps to 16320 and 128 in 8-bit maps to 16448. There is no value that is exactly middle gray in 8-bit — 127 is slightly darker than middle gray and 128 is slightly lighter. We arbitrarily pick 128 when we want "middle gray" in 8-bit, but it's not exactly halfway between 0 and 255. That would be 127.5. 

The user interfaces in Photoshop that only allow 8-bit inputs cannot give the "right" answer for middle gray on a 16-bit document because there is no 8-bit value that maps to 16384. The only way to get the expected answer in all cases would be to allow input of 16-bit values everywhere.

The issue described here is fixed in 20.0.3.

Photo of Damian Sepczuk

Damian Sepczuk

  • 11 Posts
  • 1 Reply Like
Hi, Jeffrey!

Thank you for investigating this further! :)

Unfortunately, I'm well aware of the Photoshop internals, from a similar discussion several years ago and my own investigation. Photoshop's 16-bit mode is in reality a "15-bit + 1" mode, hence we have values from "0" to "2^15 -1 + 1=32768". In the (true) 8-bit mode we have "0" to "2^8 - 1 = 255" (this is the 8-bit mode implemented by Photoshop). By analogy, a (true) 16-bit should have values ranging from "0" to "2^16 - 1 = 65535" (this is NOT implemented by Photoshop). This is an internal detail of Photoshop implementation and I'm fine with that (I know some people aren't), as long as everything else works as expected.


I'm afraid that the "fundamental error" is not on my side. The mathematics checks out, but the user experience does not :(


It is true, that 8-bit to "Photoshop's 16-bit" mapping is currently implemented in Photoshop as a (rounded) linear mapping from 0..255 to 0..32768, so
  convert_8bit_to_16bit(x) = round(x * (32768 / 255)),
where round means round to the nearest integer (of course, not implemented this way).

The formula above gives exactly the same values as Photoshop (checked with info panel in Photoshop):
 convert_8_bit_to_16_bit(0)=0
 convert_8_bit_to_16_bit(1)=129
 convert_8_bit_to_16_bit(2)=257
 convert_8_bit_to_16_bit(3)=386
...
 convert_8_bit_to_16_bit(127)=16320
 convert_8_bit_to_16_bit(128)=16448
 convert_8_bit_to_16_bit(129)=16577
...
 convert_8_bit_to_16_bit(253)=32511
 convert_8_bit_to_16_bit(254)=32639 
 convert_8_bit_to_16_bit(255)=32768
so to get convert_8_bit_to_16_bit(x)=16384, x must be equal to 127.5. And that IS the problem.


Since 128 was designated as a "special 50% gray value in 8-bit" (>>We arbitrarily pick 128 when we want "middle gray" in 8-bit<<), the meaning of convert_8_bit_to_16_bit(128) should also behave like a "(not so special) 50% gray value in 16-bit", from the user perspective.


In other words when I'm in 8-bit mode, and I enter the value "128" I expect that the color I get behaves like a "50% gray in 8-bit mode".


Similarly, when I'm in "Photoshop's 16-bit mode" and I'm presented with an input filed that accepts only integer values from 0 to 255,  I think "since 128 behaves like a 50% gray value in 8-bit mode, when I enter 128 in this input field, I should get a color that behaves like a 50% gray in 16-bit mode".


As to the final conclusion of the Photoshop architect:
The user interfaces in Photoshop that only allow 8-bit inputs cannot give the "right" answer for middle gray on a 16-bit document because there is no 8-bit value that maps to 16384. The only way to get the expected answer in all cases would be to allow input of 16-bit values everywhere.  

Well... no, it is NOT the only way. Allowing 16-bit input would be great for me, but I looks like a lot of work. Other possible solutions:
  1. Introduce a non-linearity in the convert_8_bit_to_16_bit function that treats the input value x=128 special and always returns 16384. Since the 128 was designated as special 50% gray value in 8-bit mode, another "special" treatment in the conversion function should be a natural consequence of that.
  2. Allow specifying non-integer values in the input fields, so that I can actually enter "127.5" to get 16384 in the "Photoshop's 16-bit" mode. I can enter non-integer Scale in the Apply Image dialog box, so why not a non-integer Offset?
  3. Introduce a special non-numeric symbol (for example "G") that always maps to the 50% gray value in the current bit depth.
And to be honest, the only place I came across this issue (so far!) is the "Apply Image" dialog box, so here's a solution number 4:

         4. Introduce a checkbox which says "Use 50% gray value" in the "Apply Image" dialog box, which causes that in 8-bit mode the offset is "128" and in 16-bit mode the offset is "16384".





I would kindly request that the Photoshop team give this issue some more thought.