Ai đó có thể vui lòng giải thích cách Photoshop kết hợp hai hình ảnh với nhau để tôi có thể tạo lại các hiệu ứng giống nhau trong ứng dụng của mình không.
Ai đó có thể vui lòng giải thích cách Photoshop kết hợp hai hình ảnh với nhau để tôi có thể tạo lại các hiệu ứng giống nhau trong ứng dụng của mình không.
Câu trả lời:
Photoshop trộn hai hình ảnh với nhau bằng cách thực hiện thao tác trộn trên mỗi pixel trong hình ảnh A với pixel tương ứng của nó trong hình ảnh B. Mỗi pixel là một màu bao gồm nhiều kênh. Giả sử chúng ta đang làm việc với các pixel RGB, các kênh trong mỗi pixel sẽ có màu đỏ, xanh lục và xanh lam. Để trộn hai pixel, chúng tôi trộn các kênh tương ứng của chúng.
Hoạt động hòa trộn xảy ra cho mỗi chế độ hòa trộn trong Photoshop có thể được tóm tắt trong các macro sau:
#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))
Để pha trộn một pixel RGB duy nhất, bạn sẽ làm như sau:
ImageTColorR = ChannelBlend_Glow(ImageAColorR, ImageBColorR);
ImageTColorB = ChannelBlend_Glow(ImageAColorB, ImageBColorB);
ImageTColorG = ChannelBlend_Glow(ImageAColorG, ImageBColorG);
ImageTColor = RGB(ImageTColorR, ImageTColorB, ImageTColorG);
Nếu chúng tôi muốn thực hiện thao tác trộn với độ mờ cụ thể, hãy nói 50%:
ImageTColorR = ChannelBlend_AlphaF(ImageAColorR, ImageBColorR, Blend_Subtract, 0.5F);
Nếu bạn có con trỏ đến dữ liệu hình ảnh cho hình ảnh A, B và T (mục tiêu của chúng tôi), chúng tôi có thể đơn giản hóa việc kết hợp cả ba kênh bằng cách sử dụng macro này:
#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])
Và có thể lấy các macro pha trộn màu RGB sau:
#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))
Và ví dụ sẽ là:
ColorBlend_Glow(TargetPtr, ImageAPtr, ImageBPtr);
Phần còn lại của các chế độ hòa trộn trong photoshop liên quan đến việc chuyển đổi RGB sang HLS và quay lại một lần nữa.
#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]);
}
Các chức năng này sẽ hữu ích trong việc chuyển đổi RGB sang 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;
}
Có nhiều tài nguyên hơn về chủ đề này, chủ yếu là:
Các chế độ hòa trộn Hue, Color, Saturation trong câu trả lời này là sai. Không có sản phẩm Adobe nào chuyển đổi sang HSB, chúng thực hiện thao tác trực tiếp trên các giá trị RGB.
Đây là GLSL để thiết lập độ sáng, ví dụ:
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);
}
Không hỗ trợ các câu lệnh if .. else trong CIKernels, do đó việc sử dụng các toán tử bậc ba.
Câu trả lời phổ biến là đúng 99,9%, nhưng như Greyfriars đã nói, nó sẽ không nhận được kết quả chính xác vì Adobe không sử dụng HLS bất kỳ lúc nào trong quá trình hòa trộn.
Nhưng bạn không cần phải làm việc tại Adobe để làm điều đó ... bạn có thể đạt được sự kết hợp chính xác theo tất cả các quy tắc ở đây trong tài liệu này từ Adobe:
về cơ bản chương 4 và 7: http://partners.adobe.com/public/developer/en/pdf/PDFReference.pdf
Sau đó, bạn sẽ đạt được kết quả chính xác giống như Adobe làm! Pixel by Pixel!
Trong khi câu trả lời phổ biến hầu hết là đúng, câu sau đây là sai. "Phần còn lại của các chế độ hòa trộn trong photoshop liên quan đến việc chuyển đổi RGB sang HLS và quay lại một lần nữa." Không, Photoshop (và chỉ Photoshop) sử dụng Chroma và Luma thay vì HLS.
Vì vậy, đối với các chế độ Hue, Color, Luminosity và Saturation, bạn không thể sử dụng các thuật toán đơn giản. Để phù hợp với phương pháp của Photoshop trong những trường hợp này, bạn cần phải làm việc cho Adobe.