Problems and suggestions for blending modes

In photoshop, after mixing red(255 0 0) and white(255 255 255) with “hard mix”, the result is white, but in krita, the result is red
image

Hard Mix (Photoshop)

This is the hard mix blending mode as it is implemented in photoshop.

../../_images/Krita_4_0_hard_mix_ps.png

Left: Dots are mixed in with the normal blending mode, on the Right: Dots are mixed in with hardmix.

This add the two values, and then checks if the value is above the maximum. If so it will output the maximum, otherwise the minimum.

In krita, there is no further classification for the case of A+B=255(A is the base color, B is the mixed color)

The information I found in the book is:

A+B<255, C=0
A+B>255, C=255
A+B=255
if A≥128, C=255
if A<128, C=0

Test: A: 128 0 0 and B: 127 0 0


A:127 0 0 and B:128 0 0

https://bugs.kde.org/show_bug.cgi?id=442081
I reported it on bugs.KDE. It is worth mentioning that the current algorithms are not useless. It is needed when simulating sai’s “color binarization” function (it is also divided into two cases:larger than and less than or equal to)
So the original algorithm may be retained and changed to another name, perhaps “hard mix (simple)”?

1 Like

Well, after some research I think the code should look like this:

template<class T>
inline T cfHardMixPhotoshop(T src, T dst) {
    using namespace Arithmetic;
    typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type;

    const composite_type sum = composite_type(src) + dst;
    
    if (sum == unitValue<T>()){
        return src > halfValue<T>() ? unitValue<T>() : zeroValue<T>();
    }

    return sum > unitValue<T>() ? unitValue<T>() : zeroValue<T>();
}

I found another small problem. The color of Luminosity/Shine (SAI) is too dark

Luminosity/Shine (SAI)

Similar to Addition.

Takes the opacity of the new color (combined opacity of the layer, the brush, any used transparency masks, etc.) and multiplies the color by the opacity, then adds to the original/previous color.

cnew=cabove∗αabove+cbelow

The result of this operation is the same as combining the new pixels with a fully opaque black layer in a Normal mode and then combining the result with the original layer using Addition mode. It should be also the same as the results of “Luminosity” blending mode in SAI1 or “Shine” blending mode in SAI2.

There is no problem with its formula. The key is that black should not be added when mixing does not occur
image

Then after some research of mine, I found that the blending mode of the photoshop brush is different from the layer.

  • photoshop blending mode [brush] = sai blending mode = photoshop blending mode [layer] with “transparent shape layer” off
  • photoshop blending mode [layer]=krita blending mode=[TS]sai blending mode

    The blending mode used for brushes handles translucent areas better. I want to request them for krita

We can wait for krita to implement functions such as “transparent shape layer” and “fill”. But the action to crack the psd is too painful. When I recently researched “fill”, I found that the logic of ps is confusing. Then how to apply it to the brush may also require some thinking. We can’t copy the confusing scheme of ps

Another solution is to make them into the same blending mode as Luminosity/Shine (SAI), and then group them independently. Csp and sai do this. Although the “fill” is missing, it is simple to do so. The brush also does not need the “fill” parameter

  • Linear Dodge、Difference: newsrc=src*sa
  • Burn、Linear Burn: newsrc=src*sa+255(1-sa)
  • Vivid Light、Linear Light: newsrc=src*sa+128(1-sa)

Then use newsrc instead of src to import the formula

Hard-mix
Cr=src+(dst+src-255)*sa/1-sa

This is probably this bug: 410516 – SAI Luminosity blending mode makes blocky edges it’s caused by the partial transparency.
(I mean I know that bug there looks different, but it’s just caused by the same thing).

Yes, this should be the same bug.
It only happens on transparent areas:

  • Paint on a transparent layer
  • Turn off the background color layer, then blend the two layers

If you set any background color to it, it will not happen

    newsrc = mul(src, sa);
    dst = clamp<TReal>(newsrc + dst)

Its algorithm is not wrong. But “newsrc = mul(src, sa)” is only needed when mixing.
If da=0, it will not be mixed, and there is no need for “newsrc = mul(src, sa)”