Photoshop iki görüntüyü nasıl bir araya getiriyor? [kapalı]


84

Biri, uygulamamda aynı efektleri yeniden üretebilmem için Photoshop'un iki görüntüyü nasıl karıştırdığını açıklayabilir mi?


3
Bu kesinlikle genel bilgi işlem donanımı veya yazılımı ile ilgili bir soru değildir . Algoritmalar, C ++ ve görüntü işleme ile ilgili. Bu tür sorulara açıkça izin veriliyor ve aktif olarak teşvik
ediliyor

1
8 yıl boyunca bu siteye tıklama çektikten sonra, sadece şimdi konu dışı mı değerlendiriliyor?
Nathan Moinvaziri

İhtiyacı olan tek şey en az 3000 temsilcisi olan kişilerin 5 yakın oyu. Bu soru, daha ziyade belli değil SO topluluğu tarafından-konu dışı kabul
Panagiotis Kanavos

Not: 4 olumsuz oy 8 yaşında olabilir. Birisi geçen hafta kapanış kuyruğunda soruyla karşılaşmış ve kapatma kararı almış olabilir. SO'nun şu anda o kadar çok sorusu var ki, artık sorulara yeterince dikkat etmek zor. Düzenleme geçmişi, orijinal sorunun da biraz düzenleme gerektirdiğini gösteriyor
Panagiotis Kanavos

Belki de revizyon 3'e veya benzer bir şeye geri dönmek, bunun gözden geçirenler tarafından yeniden açılması olasılığını artıracaktır. Şu anki haliyle, soruyu "Photoshop'u nasıl kullanırım" sorusu olarak karıştırmak ve ayrıca herhangi bir araştırma çabası göstermediği için onu reddetmek kolaydır.
Adam Millerchip

Yanıtlar:


210

Photoshop, görüntü A'daki her piksel üzerinde görüntü B'deki karşılık gelen piksele karşı bir karıştırma işlemi gerçekleştirerek iki görüntüyü birbirine karıştırır. Her piksel, birden çok kanaldan oluşan bir renktir. RGB piksellerle çalıştığımızı varsayarsak, her pikseldeki kanallar kırmızı, yeşil ve mavi olacaktır. İki pikseli karıştırmak için ilgili kanallarını karıştırıyoruz.

Photoshop'taki her karışım modu için gerçekleşen karışım işlemi aşağıdaki makrolarda özetlenebilir:

#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))

Tek bir RGB pikselini karıştırmak için şunları yaparsınız:

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

ImageTColor = RGB(ImageTColorR, ImageTColorB, ImageTColorG);

Belirli bir opaklıkla bir harmanlama işlemi gerçekleştirmek istersek,% 50 deyin:

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

A, B ve T (hedefimiz) görüntüleri için görüntü verilerine işaretçileriniz varsa, bu makroyu kullanarak üç kanalın da harmanlanmasını basitleştirebiliriz:

#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])

Ve aşağıdaki RGB renk karışımı makrolarını türetebilir:

#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))

Ve örnek şöyle olacaktır:

ColorBlend_Glow(TargetPtr, ImageAPtr, ImageBPtr);

Photoshop harmanlama modlarının geri kalanı, RGB'yi HLS'ye ve tekrar geri dönüştürmeyi içerir.

#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]);
    }

Bu işlevler, RGB'yi HLS'ye dönüştürmede yardımcı olacaktır.

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;
}

Bu konuda daha fazla kaynak var, özellikle:

  1. PegTop karışım modları
  2. Adli Photoshop
  3. Photoshop 7.0 Karışım Modları Hakkında Bilgi
  4. SF - Temel Bilgiler - Karıştırma Modları
  5. karışım modlarını bitir
  6. Romz blogu
  7. ReactOS RGB-HLS dönüştürme fonksiyonları

1
evet, harika cevap, teşekkürler! Photoshop'ta katman opaklığının nasıl yapıldığını bilen biri olup olmadığını merak ediyordum. yani harman koyulaştırma işlevini kullanmak istiyorum ama sadece% 50 ... Photoshop'taki değerleri kontrol ettim ve görünmüyor, karışım görüntüsünün değerlerinin sadece% 50'sini almam yeterli ...
Maecky

2
Verilen alfa formülü tam değildir - yalnızca arka planın tamamen opak olduğu durumlarda işe yarar. Arka plan şeffafsa, çizimden sonraki sonuç şeffaf olabilir. Bu daha genel durum için Wikipedia'da anlatılana benzer alfa harmanlama uygulamanız gerekir .
thenickdude

2
Alfa kanalı nasıl olur? İşlevleri ona da uygulamalı mıyım?
akhy

Mükemmel cevap!! Reflect ve Glow değiştirildi. Aksi takdirde: Harika !! (Alfa birleştirme eksik olsa da ..)
TaW

alfa-comp'ing için c # çözümü: statik Renk alphaComposite (Renk c1, Renk c2, Renk 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]; bayt r = (bayt) (c1.R * a1 + c2.R * a2 + cb.R * ab); bayt g = (bayt) (c1.G * a1 + c2.G * a2 + cb.G * ab); bayt b = (bayt) (c1.B * a1 + c2.B * a2 + cb.B * ab); Color.FromArgb ((bayt) (ar * 255), r, g, b); }
TaW

7

Bu yanıttaki Ton, Renk, Doygunluk karıştırma modları yanlıştır. Hiçbir Adobe ürünü HSB'ye dönüşmez, işlemi doğrudan RGB değerleri üzerinde yaparlar.

Parlaklığı ayarlamak için GLSL, örneğin:

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);
}

CIKernel'lerde if .. else ifadeleri desteklenmez, dolayısıyla üçlü operatörler kullanılır.


4

Popüler cevap% 99,9 doğrudur, ancak Greyfriars'ın dediği gibi, Adobe harmanlamada HLS'yi hiçbir an kullanmadığı için kesin sonucu alamayacaktır.

Ancak bunu yapmak için Adobe'de çalışmanıza gerek yok ... Adobe'den bu belgedeki tüm kuralları uygulayarak tam olarak aynı harmanlamaya ulaşabilirsiniz:

temel olarak bölüm 4 ve 7: http://partners.adobe.com/public/developer/en/pdf/PDFReference.pdf

O zaman tıpkı Adobe'nin yaptığı gibi kesin sonuca ulaşacaksınız! Pixel by Pixel!


i.imgur.com/G5MbHOH.png , bağlantıda HSL kullanıldığını söylüyor (Burayı takip ettim çünkü bu bağlantı benim için koptu: adobe.com/content/dam/acom/en/devnet/pdf/pdfs/… )
eri0o

0

Popüler cevap çoğunlukla doğru olsa da, aşağıdaki ifade yanlıştır. "Photoshop karışım modlarının geri kalanı, RGB'yi HLS'ye ve tekrar geri dönüştürmeyi içerir." Hayır, Photoshop (ve yalnızca Photoshop) HLS yerine Chroma ve Luma kullanır.

Dolayısıyla Ton, Renk, Parlaklık ve Doygunluk modları için basit algoritmalar kullanamazsınız. Bu durumlarda Photoshop'un yöntemini eşleştirmek için Adobe için çalışıyor olmanız gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.