Wie mischt Photoshop zwei Bilder zusammen? [geschlossen]

84

Kann jemand bitte erklären, wie Photoshop zwei Bilder miteinander verbindet, damit ich die gleichen Effekte in meiner Anwendung reproduzieren kann.

Nathan Moinvaziri
quelle
2
Dies ist definitiv keine Frage zu allgemeiner Computerhardware oder -software. Es geht um Algorithmen, C ++ und Bildverarbeitung. Diese Art von Frage ist ausdrücklich erlaubt und wird aktiv gefördert
Panagiotis Kanavos
Nach 8 Jahren Fahrklicks auf diese Seite gilt sie erst jetzt als nicht zum Thema gehörend?
Nathan Moinvaziri
Alles was es braucht sind 5 enge Stimmen von Leuten mit mindestens 3000 Wiederholungen. Es ist ziemlich offensichtlich, dass diese Frage von der SO-Community nicht als nicht zum Thema gehörend angesehen wird
Panagiotis Kanavos
PS: Die 4 Downvotes könnten 8 Jahre alt sein. Möglicherweise ist jemand letzte Woche in der Warteschlange auf die Frage gestoßen und hat für das Schließen gestimmt. SO hat momentan so viele Fragen, dass es schwierig ist, Fragen mehr richtig zu beachten. Der Bearbeitungsverlauf zeigt, dass die ursprüngliche Frage ebenfalls etwas bearbeitet werden musste
Panagiotis Kanavos
Vielleicht würde eine Rückkehr zu Revision 3 oder ähnlichem die Wahrscheinlichkeit erhöhen, dass dies von den Gutachtern wieder geöffnet wird. Im aktuellen Zustand ist es leicht, die Frage als "Wie verwende ich Photoshop?" - Frage zu verwechseln und sie als nicht recherchierend abzulehnen.
Adam Millerchip

Antworten:

210

Photoshop mischt zwei Bilder zusammen, indem für jedes Pixel in Bild A eine Mischoperation mit dem entsprechenden Pixel in Bild B ausgeführt wird. Jedes Pixel ist eine Farbe, die aus mehreren Kanälen besteht. Angenommen, wir arbeiten mit RGB-Pixeln, wären die Kanäle in jedem Pixel rot, grün und blau. Um zwei Pixel zu mischen, mischen wir ihre jeweiligen Kanäle.

Der Mischvorgang, der für jeden Mischmodus in Photoshop ausgeführt wird, kann in den folgenden Makros zusammengefasst werden:

#define ChannelBlend_Normal(A,B)     ((uint8)(A))
#define ChannelBlend_Lighten(A,B)    ((uint8)((B > A) ? B:A))
#define ChannelBlend_Darken(A,B)     ((uint8)((B > A) ? A:B))
#define ChannelBlend_Multiply(A,B)   ((uint8)((A * B) / 255))
#define ChannelBlend_Average(A,B)    ((uint8)((A + B) / 2))
#define ChannelBlend_Add(A,B)        ((uint8)(min(255, (A + B))))
#define ChannelBlend_Subtract(A,B)   ((uint8)((A + B < 255) ? 0:(A + B - 255)))
#define ChannelBlend_Difference(A,B) ((uint8)(abs(A - B)))
#define ChannelBlend_Negation(A,B)   ((uint8)(255 - abs(255 - A - B)))
#define ChannelBlend_Screen(A,B)     ((uint8)(255 - (((255 - A) * (255 - B)) >> 8)))
#define ChannelBlend_Exclusion(A,B)  ((uint8)(A + B - 2 * A * B / 255))
#define ChannelBlend_Overlay(A,B)    ((uint8)((B < 128) ? (2 * A * B / 255):(255 - 2 * (255 - A) * (255 - B) / 255)))
#define ChannelBlend_SoftLight(A,B)  ((uint8)((B < 128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255))))
#define ChannelBlend_HardLight(A,B)  (ChannelBlend_Overlay(B,A))
#define ChannelBlend_ColorDodge(A,B) ((uint8)((B == 255) ? B:min(255, ((A << 8 ) / (255 - B)))))
#define ChannelBlend_ColorBurn(A,B)  ((uint8)((B == 0) ? B:max(0, (255 - ((255 - A) << 8 ) / B))))
#define ChannelBlend_LinearDodge(A,B)(ChannelBlend_Add(A,B))
#define ChannelBlend_LinearBurn(A,B) (ChannelBlend_Subtract(A,B))
#define ChannelBlend_LinearLight(A,B)((uint8)(B < 128)?ChannelBlend_LinearBurn(A,(2 * B)):ChannelBlend_LinearDodge(A,(2 * (B - 128))))
#define ChannelBlend_VividLight(A,B) ((uint8)(B < 128)?ChannelBlend_ColorBurn(A,(2 * B)):ChannelBlend_ColorDodge(A,(2 * (B - 128))))
#define ChannelBlend_PinLight(A,B)   ((uint8)(B < 128)?ChannelBlend_Darken(A,(2 * B)):ChannelBlend_Lighten(A,(2 * (B - 128))))
#define ChannelBlend_HardMix(A,B)    ((uint8)((ChannelBlend_VividLight(A,B) < 128) ? 0:255))
#define ChannelBlend_Reflect(A,B)    ((uint8)((B == 255) ? B:min(255, (A * A / (255 - B)))))
#define ChannelBlend_Glow(A,B)       (ChannelBlend_Reflect(B,A))
#define ChannelBlend_Phoenix(A,B)    ((uint8)(min(A,B) - max(A,B) + 255))
#define ChannelBlend_Alpha(A,B,O)    ((uint8)(O * A + (1 - O) * B))
#define ChannelBlend_AlphaF(A,B,F,O) (ChannelBlend_Alpha(F(A,B),A,O))

Um ein einzelnes RGB-Pixel zu mischen, gehen Sie wie folgt vor:

ImageTColorR = ChannelBlend_Glow(ImageAColorR, ImageBColorR); 
ImageTColorB = ChannelBlend_Glow(ImageAColorB, ImageBColorB);
ImageTColorG = ChannelBlend_Glow(ImageAColorG, ImageBColorG);

ImageTColor = RGB(ImageTColorR, ImageTColorB, ImageTColorG);

Wenn wir einen Mischvorgang mit einer bestimmten Deckkraft ausführen möchten, sagen wir 50%:

ImageTColorR = ChannelBlend_AlphaF(ImageAColorR, ImageBColorR, Blend_Subtract, 0.5F);

Wenn Sie Zeiger auf die Bilddaten für die Bilder A, B und T (unser Ziel) haben, können wir das Mischen aller drei Kanäle mithilfe dieses Makros vereinfachen:

#define ColorBlend_Buffer(T,A,B,M)      (T)[0] = ChannelBlend_##M((A)[0], (B)[0]),
                                        (T)[1] = ChannelBlend_##M((A)[1], (B)[1]),
                                        (T)[2] = ChannelBlend_##M((A)[2], (B)[2])

Und kann die folgenden RGB-Farbmischungsmakros ableiten:

#define ColorBlend_Normal(T,A,B)        (ColorBlend_Buffer(T,A,B,Normal))
#define ColorBlend_Lighten(T,A,B)       (ColorBlend_Buffer(T,A,B,Lighten))
#define ColorBlend_Darken(T,A,B)        (ColorBlend_Buffer(T,A,B,Darken))
#define ColorBlend_Multiply(T,A,B)      (ColorBlend_Buffer(T,A,B,Multiply))
#define ColorBlend_Average(T,A,B)       (ColorBlend_Buffer(T,A,B,Average))
#define ColorBlend_Add(T,A,B)           (ColorBlend_Buffer(T,A,B,Add))
#define ColorBlend_Subtract(T,A,B)      (ColorBlend_Buffer(T,A,B,Subtract))
#define ColorBlend_Difference(T,A,B)    (ColorBlend_Buffer(T,A,B,Difference))
#define ColorBlend_Negation(T,A,B)      (ColorBlend_Buffer(T,A,B,Negation))
#define ColorBlend_Screen(T,A,B)        (ColorBlend_Buffer(T,A,B,Screen))
#define ColorBlend_Exclusion(T,A,B)     (ColorBlend_Buffer(T,A,B,Exclusion))
#define ColorBlend_Overlay(T,A,B)       (ColorBlend_Buffer(T,A,B,Overlay))
#define ColorBlend_SoftLight(T,A,B)     (ColorBlend_Buffer(T,A,B,SoftLight))
#define ColorBlend_HardLight(T,A,B)     (ColorBlend_Buffer(T,A,B,HardLight))
#define ColorBlend_ColorDodge(T,A,B)    (ColorBlend_Buffer(T,A,B,ColorDodge))
#define ColorBlend_ColorBurn(T,A,B)     (ColorBlend_Buffer(T,A,B,ColorBurn))
#define ColorBlend_LinearDodge(T,A,B)   (ColorBlend_Buffer(T,A,B,LinearDodge))
#define ColorBlend_LinearBurn(T,A,B)    (ColorBlend_Buffer(T,A,B,LinearBurn))
#define ColorBlend_LinearLight(T,A,B)   (ColorBlend_Buffer(T,A,B,LinearLight))
#define ColorBlend_VividLight(T,A,B)    (ColorBlend_Buffer(T,A,B,VividLight))
#define ColorBlend_PinLight(T,A,B)      (ColorBlend_Buffer(T,A,B,PinLight))
#define ColorBlend_HardMix(T,A,B)       (ColorBlend_Buffer(T,A,B,HardMix))
#define ColorBlend_Reflect(T,A,B)       (ColorBlend_Buffer(T,A,B,Reflect))
#define ColorBlend_Glow(T,A,B)          (ColorBlend_Buffer(T,A,B,Glow))
#define ColorBlend_Phoenix(T,A,B)       (ColorBlend_Buffer(T,A,B,Phoenix))

Und ein Beispiel wäre:

ColorBlend_Glow(TargetPtr, ImageAPtr, ImageBPtr);

Der Rest der Photoshop-Mischmodi umfasst die Konvertierung von RGB in HLS und wieder zurück.

#define ColorBlend_Hue(T,A,B)            ColorBlend_Hls(T,A,B,HueB,LuminationA,SaturationA)
#define ColorBlend_Saturation(T,A,B)     ColorBlend_Hls(T,A,B,HueA,LuminationA,SaturationB)
#define ColorBlend_Color(T,A,B)          ColorBlend_Hls(T,A,B,HueB,LuminationA,SaturationB)
#define ColorBlend_Luminosity(T,A,B)     ColorBlend_Hls(T,A,B,HueA,LuminationB,SaturationA)

#define ColorBlend_Hls(T,A,B,O1,O2,O3) {
    float64 HueA, LuminationA, SaturationA;
    float64 HueB, LuminationB, SaturationL;
    Color_RgbToHls((A)[2],(A)[1],(A)[0], &HueA, &LuminationA, &SaturationA);
    Color_RgbToHls((B)[2],(B)[1],(B)[0], &HueB, &LuminationB, &SaturationB);
    Color_HlsToRgb(O1,O2,O3,&(T)[2],&(T)[1],&(T)[0]);
    }

Diese Funktionen sind hilfreich bei der Konvertierung von RGB in HLS.

int32 Color_HueToRgb(float64 M1, float64 M2, float64 Hue, float64 *Channel)
{
    if (Hue < 0.0)
        Hue += 1.0;
    else if (Hue > 1.0)
        Hue -= 1.0;

    if ((6.0 * Hue) < 1.0)
        *Channel = (M1 + (M2 - M1) * Hue * 6.0);
    else if ((2.0 * Hue) < 1.0)
        *Channel = (M2);
    else if ((3.0 * Hue) < 2.0)
        *Channel = (M1 + (M2 - M1) * ((2.0F / 3.0F) - Hue) * 6.0);
    else
        *Channel = (M1);

    return TRUE;
}

int32 Color_RgbToHls(uint8 Red, uint8 Green, uint8 Blue, float64 *Hue, float64 *Lumination, float64 *Saturation)
{
    float64 Delta;
    float64 Max, Min;
    float64 Redf, Greenf, Bluef;

    Redf    = ((float64)Red   / 255.0F);
    Greenf  = ((float64)Green / 255.0F);
    Bluef   = ((float64)Blue  / 255.0F); 

    Max     = max(max(Redf, Greenf), Bluef);
    Min     = min(min(Redf, Greenf), Bluef);

    *Hue        = 0;
    *Lumination = (Max + Min) / 2.0F;
    *Saturation = 0;

    if (Max == Min)
        return TRUE;

    Delta = (Max - Min);

    if (*Lumination < 0.5)
        *Saturation = Delta / (Max + Min);
    else
        *Saturation = Delta / (2.0 - Max - Min);

    if (Redf == Max)
        *Hue = (Greenf - Bluef) / Delta;
    else if (Greenf == Max)
        *Hue = 2.0 + (Bluef - Redf) / Delta;
    else
        *Hue = 4.0 + (Redf - Greenf) / Delta;

    *Hue /= 6.0; 

    if (*Hue < 0.0)
        *Hue += 1.0;       

    return TRUE;
}

int32 Color_HlsToRgb(float64 Hue, float64 Lumination, float64 Saturation, uint8 *Red, uint8 *Green, uint8 *Blue)
{
    float64 M1, M2;
    float64 Redf, Greenf, Bluef;

    if (Saturation == 0)
        {
        Redf    = Lumination;
        Greenf  = Lumination;
        Bluef   = Lumination;
        }
    else
        {
        if (Lumination <= 0.5)
            M2 = Lumination * (1.0 + Saturation);
        else
            M2 = Lumination + Saturation - Lumination * Saturation;

        M1 = (2.0 * Lumination - M2);

        Color_HueToRgb(M1, M2, Hue + (1.0F / 3.0F), &Redf);
        Color_HueToRgb(M1, M2, Hue, &Greenf);
        Color_HueToRgb(M1, M2, Hue - (1.0F / 3.0F), &Bluef);
        }

    *Red    = (uint8)(Redf * 255);
    *Blue   = (uint8)(Bluef * 255);
    *Green  = (uint8)(Greenf * 255);

    return TRUE;
}

Zu diesem Thema gibt es weitere Ressourcen, hauptsächlich:

  1. PegTop-Mischmodi
  2. Forensisches Photoshop
  3. Einblick in die Mischmodi von Photoshop 7.0
  4. SF - Grundlagen - Mischmodi
  5. Beenden Sie die Mischmodi
  6. Romz Blog
  7. ReactOS RGB-HLS-Konvertierungsfunktionen
Nathan Moinvaziri
quelle
1
Ja, tolle Antwort, danke! Ich habe mich gefragt, ob jemand weiß, wie die Deckkraft von Ebenen in Photoshop erfolgt. dh ich möchte die Überblendungsdunkelfunktion verwenden, aber nur 50% ... Ich habe die Werte in Photoshop überprüft und es scheint nicht, dass es ausreicht, nur 50% der Werte des Überblendungsbildes zu übernehmen ...
Maecky
2
Die angegebene Alpha-Formel ist nicht vollständig - sie funktioniert nur für den Fall, dass der Hintergrund vollständig undurchsichtig ist. Wenn der Hintergrund transparent ist, kann das Ergebnis nach dem Zeichnen transparent sein. Für diesen allgemeineren Fall müssen Sie Alpha-Blending anwenden, wie es in Wikipedia beschrieben ist.
thenickdude
2
Wie wäre es mit Alpha-Kanal? Soll ich die Funktionen auch darauf anwenden?
Akhy
Gute Antwort!! Reflect und Glow werden umgeschaltet. Ansonsten: Großartig !! (Obwohl Alpha-Compositing fehlt ..)
TaW
c # -Lösung für Alpha-Comp'ing: statische Farbe alphaComposite (Farbe c1, Farbe c2, Farbe cb, float op) {float a1, a2, ab, ar = 1; ar = v [c1.A] + v [c2.A] * op - (v [c1.A] * v [c2.A] * op); float asr = v [c2.A] * op / ar; a1 = 1 - asr; a2 = asr * (1 - v [c1.A]); ab = asr * v [c1.A]; Byte r = (Byte) (c1.R * a1 + c2.R * a2 + cb.R * ab); Byte g = (Byte) (c1.G * a1 + c2.G * a2 + cb.G * ab); Byte b = (Byte) (c1.B * a1 + c2.B * a2 + cb.B * ab); return Color.FromArgb ((Byte) (ar * 255), r, g, b); }
TaW
7

Die Mischmodi Farbton, Farbe und Sättigung in dieser Antwort sind falsch. Kein Adobe-Produkt wird in HSB konvertiert. Der Vorgang wird direkt mit RGB-Werten ausgeführt.

Hier ist die GLSL zum Einstellen der Leuchtkraft, zum Beispiel:

float lum(vec4 color)
{
    return ((0.3 * color.r) + (0.59 * color.g) + (0.11 * color.b));
}

vec4 clipColor(vec4 color)
{
    vec4 newColor=color;
    float l=lum(color);
    float n=min(min(color.r,color.g),color.b);
    float x=max(max(color.r,color.g),color.b);

    newColor.r=(n<0.0) ? l+(((color.r-l)*l)/(l-n)) : color.r;
    newColor.r=(x>1.0) ? l+(((color.r-l)*(1.0-l))/(x-l)) : color.r;

    newColor.g=(n<0.0) ? l+(((color.g-l)*l)/(l-n)) : color.g;
    newColor.g=(x>1.0) ? l+(((color.g-l)*(1.0-l))/(x-l)) : color.g;

    newColor.b=(n<0.0) ? l+(((color.b-l)*l)/(l-n)) : color.b;
    newColor.b=(x>1.0) ? l+(((color.b-l)*(1.0-l))/(x-l)) : color.b;

    return clamp(newColor,0.0,1.0);
}

vec4 setlum(vec4 color, float l)
{
    float d=l-lum(color);
    color.r+=d;
    color.g+=d;
    color.b+=d;

    return clipColor(color);    
}

kernel vec4 blendLuminosity(sampler topimage, sampler bottomimage)
{
    vec4 base=sample(bottomimage, samplerCoord(bottomimage));
    vec4 blend=sample(topimage, samplerCoord(topimage));

    float bl=lum(blend);
    return setlum(base,bl);
}

Keine Unterstützung für if .. else-Anweisungen in CIKernels, daher die Verwendung von ternären Operatoren.

Jon Gilkison
quelle
4

Die beliebte Antwort lautet zu 99,9% richtig, aber wie Greyfriars sagte, wird das genaue Ergebnis nicht erzielt, da Adobe HLS zu keinem Zeitpunkt beim Mischen verwendet.

Sie müssen jedoch nicht bei Adobe arbeiten, um dies zu tun. Sie können genau die gleiche Mischung erzielen, indem Sie alle Regeln hier in diesem Dokument von Adobe befolgen:

Grundsätzlich Kapitel 4 und 7: http://partners.adobe.com/public/developer/en/pdf/PDFReference.pdf

Dann erreichen Sie genau wie Adobe das genaue Ergebnis! Pixel für Pixel!

Wagner Patriota
quelle
i.imgur.com/G5MbHOH.png es sagt HSL in der Verbindung verwendet wird (I gefolgt hier , weil diese Verbindung für mich war gebrochen: adobe.com/content/dam/acom/en/devnet/pdf/pdfs/... )
eri0o
0

Während die populäre Antwort größtenteils richtig ist, ist die folgende Aussage falsch. "Der Rest der Photoshop-Mischmodi umfasst die Konvertierung von RGB in HLS und wieder zurück." Nein, Photoshop (und nur Photoshop) verwendet Chroma und Luma anstelle von HLS.

Für die Modi Farbton, Farbe, Leuchtkraft und Sättigung können Sie also keine einfachen Algorithmen verwenden. Um in diesen Fällen mit der Photoshop-Methode übereinzustimmen, müssen Sie für Adobe arbeiten.

Greyfriars Bobby
quelle