Frage Wie mischt Photoshop zwei Bilder zusammen?


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


75
2018-05-07 07:17


Ursprung


Antworten:


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

Die Überblendungsoperation, die für jeden Überblendungsmodus 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, würden Sie Folgendes tun:

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

ImageTColor = RGB(ImageTColorR, ImageTColorB, ImageTColorG);

Wenn wir eine Mischoperation mit einer bestimmten Deckkraft durchfü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 mit diesem Makro 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-Farbmischmakros 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 zu HLS und 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 Umwandlung 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;
}

Es gibt mehr Ressourcen zu diesem Thema, hauptsächlich:

  1. PegTop-Mischmodi 
  2. Forensisches Photoshop 
  3. Einblick in Photoshop 7.0 Blend Modes
  4. SF - Grundlagen - Mischmodi
  5. Beende die Mischmodi
  6. Romz Blog
  7. ReactOS RGB-HLS Konvertierungsfunktionen

195
2018-05-08 02:22



Die Mischmodi Farbton, Farbe, Sättigung sind in dieser Antwort falsch. Kein Adobe-Produkt wird in HSB konvertiert, sondern direkt mit RGB-Werten.

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..sey-Anweisungen in CIKernels, daher die Verwendung von ternären Operatoren.


6
2017-10-22 09:00



Die beliebte Antwort ist 99,9% richtig, aber wie Greyfriars sagte, wird es nicht das genaue Ergebnis erhalten, da Adobe HLS keinen Moment in der Mischung verwendet.

Aber Sie müssen nicht bei Adobe arbeiten, um das zu tun ... Sie können exakt die gleiche Mischung erreichen, indem Sie alle Regeln 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 exakte Ergebnis! Pixel für Pixel!


3
2018-05-06 16:55



Während die beliebte Antwort größtenteils korrekt ist, ist die folgende Aussage falsch. "Der Rest der Photoshop-Mischmodi besteht darin, RGB in HLS und wieder zurück zu konvertieren." Nein, Photoshop (und nur Photoshop) verwendet Chroma und Luma anstelle von HLS.

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


0
2018-05-06 16:28