photoshop ผสมผสานสองภาพเข้าด้วยกันอย่างไร? [ปิด]


84

ใครช่วยอธิบายวิธีการที่ Photoshop ผสมผสานภาพสองภาพเข้าด้วยกันเพื่อที่ฉันจะสร้างเอฟเฟกต์เดียวกันในแอปพลิเคชันของฉันได้


3
นี่ไม่ใช่คำถามเกี่ยวกับฮาร์ดแวร์หรือซอฟต์แวร์คอมพิวเตอร์ทั่วไปอย่างแน่นอน มันเกี่ยวกับอัลกอริทึม C ++ และการประมวลผลภาพ คำถามประเภทนี้ได้รับอนุญาตอย่างชัดเจนและได้รับการสนับสนุนอย่างแข็งขัน
Panagiotis Kanavos

1
หลังจาก 8 ปีของการกระตุ้นให้เกิดการคลิกมายังไซต์นี้ตอนนี้ถือว่าอยู่นอกหัวข้อหรือไม่
Nathan Moinvaziri

สิ่งที่ต้องการคือ 5 คะแนนโหวตจากผู้ที่มีตัวแทนอย่างน้อย 3000 ค่อนข้างชัดเจนว่าคำถามนี้ไม่ถือว่านอกประเด็นโดยชุมชน SO
Panagiotis Kanavos

PS: ผู้โหวตทั้ง 4 คนอาจมีอายุ 8 ปี อาจมีคนเจอคำถามในคิวปิดเมื่อสัปดาห์ที่แล้วและปิดโหวต SO มีคำถามมากมายในตอนนี้ซึ่งมันยากที่จะใส่ใจกับคำถามอีกต่อไป ประวัติการแก้ไขแสดงให้เห็นว่าคำถามเดิมต้องการการแก้ไขเล็กน้อยเช่นกัน
Panagiotis Kanavos

บางทีการเปลี่ยนกลับเป็นรุ่นที่ 3 หรือสิ่งที่คล้ายกันอาจทำให้ผู้ตรวจสอบมีแนวโน้มที่จะเปิดอีกครั้ง ในสถานะปัจจุบันเป็นเรื่องง่ายที่จะเข้าใจผิดว่าคำถามเป็นคำถาม "ฉันจะใช้ Photoshop ได้อย่างไร" และยังบอกอีกว่าไม่แสดงความพยายามในการค้นคว้าใด ๆ
Adam Millerchip

คำตอบ:


210

Photoshop ผสมผสานภาพสองภาพเข้าด้วยกันโดยดำเนินการผสมผสานในแต่ละพิกเซลในภาพ A กับพิกเซลที่สอดคล้องกันในภาพ B แต่ละพิกเซลเป็นสีที่ประกอบด้วยหลายช่องสัญญาณ สมมติว่าเรากำลังทำงานกับพิกเซล RGB ช่องในแต่ละพิกเซลจะเป็นสีแดงเขียวและน้ำเงิน ในการผสมผสานสองพิกเซลเราผสมผสานช่องต่างๆ

การดำเนินการผสมผสานที่เกิดขึ้นสำหรับโหมดผสมผสานแต่ละโหมดใน Photoshop สามารถสรุปได้ในมาโครต่อไปนี้:

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

ในการผสมผสานพิกเซล RGB เดียวคุณต้องทำสิ่งต่อไปนี้:

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

ImageTColor = RGB(ImageTColorR, ImageTColorB, ImageTColorG);

หากเราต้องการดำเนินการผสมผสานกับความทึบที่เฉพาะเจาะจงให้พูด 50%:

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

หากคุณมีตัวชี้ข้อมูลรูปภาพสำหรับรูปภาพ A, B และ T (เป้าหมายของเรา) เราสามารถทำให้การผสมของทั้งสามช่องง่ายขึ้นโดยใช้มาโครนี้:

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

และสามารถรับมาโครการผสมผสานสี RGB ต่อไปนี้:

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

และตัวอย่างจะเป็น:

ColorBlend_Glow(TargetPtr, ImageAPtr, ImageBPtr);

ส่วนที่เหลือของโหมดผสมผสาน photoshop เกี่ยวข้องกับการแปลง RGB เป็น HLS และกลับมาอีกครั้ง

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

ฟังก์ชันเหล่านี้จะเป็นประโยชน์ในการแปลง RGB เป็น 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;
}

มีแหล่งข้อมูลเพิ่มเติมในหัวข้อนี้ส่วนใหญ่:

  1. โหมดผสมผสาน PegTop
  2. โฟโต้ชอปนิติวิทยาศาสตร์
  3. ข้อมูลเชิงลึกเกี่ยวกับ Photoshop 7.0 Blend Modes
  4. SF - พื้นฐาน - โหมดผสม
  5. จบโหมดผสมผสาน
  6. บล็อก Romz
  7. ฟังก์ชั่นการแปลง ReactOS RGB-HLS

1
ใช่คำตอบที่ดีขอบคุณ! ฉันสงสัยว่ามีใครรู้บ้างว่าเลเยอร์ทึบใน photoshop ทำอย่างไร? เช่นฉันต้องการใช้ฟังก์ชัน Blend Darken แต่มีเพียง 50% ... ฉันตรวจสอบค่าใน photoshop แล้วดูเหมือนจะไม่เพียงพอที่จะใช้เพียง 50% ของค่าของภาพผสม ...
Maecky

2
สูตรอัลฟาที่ระบุยังไม่สมบูรณ์ - ใช้ได้เฉพาะในกรณีที่พื้นหลังทึบแสงเต็มที่ หากพื้นหลังโปร่งใสผลลัพธ์ที่ได้หลังจากการวาดจะโปร่งใส คุณต้องใช้การผสมอัลฟาเช่นที่อธิบายไว้ในวิกิพีเดียสำหรับกรณีทั่วไปนั้น
thenickdude

2
แล้ว alpha channel ล่ะ ฉันควรใช้ฟังก์ชันนี้ด้วยหรือไม่
akhy

ตอบโจทย์มาก !! สะท้อนให้เห็นถึงและบริษัท โกลว์จะเปลี่ยน มิฉะนั้น: เยี่ยม !! (แม้ว่าอัลฟาคอมโพสิตจะหายไป .. )
TAW

โซลูชัน c # สำหรับ alpha-comp'ing: คง Color alphaComposite (Color c1, Color c2, Color cb, float op) {float a1, a2, ab, ar = 1; ar = v [c1.A] + v [c2.A] * op - (v [c1.A] * v [c2.A] * op); ลอย asr = v [c2.A] * op / ar; a1 = 1 - asr; a2 = asr * (1 - v [c1.A]); ab = asr * v [c1.A]; ไบต์ r = (ไบต์) (c1.R * a1 + c2.R * a2 + cb.R * ab); ไบต์ g = (ไบต์) (c1.G * a1 + c2.G * a2 + cb.G * ab); ไบต์ b = (ไบต์) (c1.B * a1 + c2.B * a2 + cb.B * ab); คืนค่า Color.FromArgb ((ไบต์) (ar * 255), r, g, b); }

7

คำตอบนี้ไม่ถูกต้องโหมดการผสมเฉดสีสีความอิ่มตัวของสี ไม่มีผลิตภัณฑ์ Adobe แปลงเป็น HSB แต่ดำเนินการโดยตรงกับค่า RGB

นี่คือ GLSL สำหรับการตั้งค่าความส่องสว่างตัวอย่างเช่น:

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

ไม่มีการสนับสนุนสำหรับ if .. else ข้อความใน CIKernels ดังนั้นการใช้ตัวดำเนินการ ternary


4

คำตอบยอดนิยมนั้นถูกต้อง 99.9% แต่อย่างที่ Greyfriars กล่าวไว้มันจะไม่ได้ผลลัพธ์ที่แน่นอนเพราะ Adobe ไม่ได้ใช้ HLS เลยในการผสม

แต่คุณไม่จำเป็นต้องทำงานที่ Adobe เพื่อที่จะทำเช่นนั้น ... คุณสามารถเข้าถึงการผสมผสานที่เหมือนกันโดยปฏิบัติตามกฎทั้งหมดในเอกสารนี้จาก Adobe:

โดยทั่วไปบทที่ 4 และ 7: http://partners.adobe.com/public/developer/en/pdf/PDFReference.pdf

แล้วคุณจะได้ผลลัพธ์ที่แน่นอนเหมือนกับที่ Adobe ทำ! Pixel by Pixel!


i.imgur.com/G5MbHOH.pngมันบอกว่า HSL ถูกใช้ในลิงค์ (ฉันไปที่นี่เพราะลิงก์นั้นเสียสำหรับฉัน: adobe.com/content/dam/acom/en/devnet/pdf/pdfs/… )
eri0o

0

ในขณะที่คำตอบยอดนิยมส่วนใหญ่ถูกต้อง แต่ข้อความต่อไปนี้ผิด "ส่วนที่เหลือของโหมดผสมผสาน photoshop เกี่ยวข้องกับการแปลง RGB เป็น HLS และกลับมาอีกครั้ง" ไม่ Photoshop (และเฉพาะ Photoshop) ใช้ Chroma และ Luma แทน HLS

ดังนั้นสำหรับโหมด Hue, Color, Luminosity และ Saturation คุณจะไม่สามารถใช้อัลกอริทึมง่ายๆได้ เพื่อให้เข้ากับวิธีการของ Photoshop ในกรณีเหล่านี้คุณต้องทำงานกับ Adobe

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.