5 votes

Comment gérer l'alpha dans une opération de fusion manuelle "Overlay" ?

Je m'amuse à faire du traitement d'image manuel (en marchant sur les pixels), et je recrée le mélange standard "overlay". Je regarde les macros "Photoshop math" ici :

http://www.nathanm.com/photoshop-blending-math/ ( Voir aussi ici pour une version plus lisible de Overlay)

Les deux images sources sont dans un format RGBA (8 bits chacune) assez standard, tout comme la destination. Lorsque les deux images sont totalement opaques (l'alpha est de 1,0), le résultat est mélangé correctement comme prévu :

Mais si mon calque "blend" (l'image du haut) contient de la transparence, je suis un peu perdue. Comment prendre en compte cet alpha dans l'équation de mélange ? correctement. Je m'attends à ce que le fonctionnement soit tel que les pixels transparents de la couche de fusion n'aient aucun effet sur le résultat, que les pixels opaques de la couche de fusion effectuent le mélange de la superposition normalement, et que les pixels semi-transparents de la couche de fusion aient un certain effet d'échelle sur le résultat.

Quelqu'un peut-il m'expliquer les équations du mélange ou le concept qui sous-tend cette opération ?

Points bonus si vous pouvez m'aider à le faire de telle sorte que l'image résultante ait un alpha correctement prémultiplié (qui n'entre en jeu que pour les pixels qui ne sont pas opaques dans les deux couches, je pense).

Merci !

// factor in blendLayerA, (1-blendLayerA) somehow?
resultR = ChannelBlend_Overlay(baseLayerR, blendLayerR); 
resultG = ChannelBlend_Overlay(baseLayerG, blendLayerG);
resultB = ChannelBlend_Overlay(baseLayerB, blendLayerB);
resultA = 1.0; // also, what should this be??

5voto

Raginmari Points 584

Après avoir mélangé la couleur de base et la couleur de mélange, mélangez la couleur de base originale et la couleur résultant du mélange en utilisant l'alpha de la couleur de mélange :

vec4 baseColor = ...;
vec4 blendColor = ...;
vec4 blendedColor = blend(baseColor, blendColor);
vec4 fragmentColor = (1.0 - blendColor.a) * baseColor + blendColor.a * blendedColor;

Je l'utilise pour "superposer" une couleur de base opaque et une texture de mélange qui a beaucoup de pixels (semi) transparents.

1voto

Timbo Points 14117

C'est juste une supposition, mais j'essaierais

resultA = 1 - (1-baseAlpha) * (1-blendAlpha)

0voto

Geri Points 3572

J'étais en train d'expérimenter avec ce problème, jusqu'à ce que je découvre que le mieux est d'avoir la base et le calque de fusion avec un alpha direct, puis de prémultiplier seulement le résultat avec l'alpha de la base.

0voto

Thomas Points 176

Cela fonctionne très bien, en utilisant la formule d'ici : https://dev.w3.org/SVG/modules/compositing/master/ . Ma fonction est un peu bizarre car elle prend un DoubleColor qui est 0-1, et une couleur de pixel T* qui est 0-maxValDouble() (qui est la valeur maximale du type d'entier utilisé, en tant que double).

template<typename T> static inline void blendColorOverlay(T* rgba, DoubleColor overColor) {
    if (overColor.a == 0)
        return;

    double Da = rgba[3]/maxValDouble<T>();
    double Sa = overColor[3];
    double Dca, Sca;

    double outAlpha = (Sa + Da - Sa*Da);

    for (int k = 0; k < 3; k++) {
        Dca = (rgba[k]/maxValDouble<T>())*Da;
        Sca = overColor[k]*Sa;
        if (2*Dca <= Da)
            rgba[k] = (2*Sca*Dca + Sca*(1.0 - Da) + Dca*(1.0 - Sa))*maxValDouble<T>()/outAlpha;
        else
            rgba[k] = (Sca*(1.0 + Da) + Dca*(1.0 + Sa) - 2.0*Dca*Sca - Da*Sa)*maxValDouble<T>()/outAlpha;
        }

    rgba[3] = outAlpha*maxValDouble<T>();
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X