Это определенно не вопрос общего компьютерного оборудования или программного обеспечения. Речь идет об алгоритмах, C ++ и обработке изображений. Этот тип вопросов явно разрешен и активно поощряется
Панайотис Канавос
1
После 8 лет увеличения количества переходов на этот сайт только теперь он считается не по теме?
Nathan Moinvaziri 05
Все, что для этого нужно, это 5 близких голосов людей с минимум 3000 репутацией. Совершенно очевидно, что этот вопрос не считается вне темы сообществом SO
Панайотис Канавос 08
PS: 4 отрицательных голоса могут быть возрастом 8 лет. Кто-то мог столкнуться с вопросом в очереди на закрытие на прошлой неделе и проголосовал за закрытие. У SO сейчас так много вопросов, что уже трудно уделять им должное внимание. История редактирования показывает, что исходный вопрос тоже нуждался в небольшом редактировании
Панайотис Канавос 08
Возможно, возврат к редакции 3 или чему-то подобному повысит вероятность того, что рецензенты снова откроют ее. В его нынешнем состоянии легко принять вопрос за вопрос «как мне использовать Photoshop», а также отклонить его как не отражающий никаких исследовательских усилий.
Adam Millerchip
Ответы:
210
Photoshop смешивает два изображения вместе, выполняя операцию смешивания для каждого пикселя в изображении A и его соответствующего пикселя в изображении B. Каждый пиксель представляет собой цвет, состоящий из нескольких каналов. Предполагая, что мы работаем с пикселями RGB, каналы в каждом пикселе будут красным, зеленым и синим. Чтобы смешать два пикселя, мы смешиваем их соответствующие каналы.
Операцию наложения, выполняемую для каждого режима наложения в Photoshop, можно описать в следующих макросах:
Если у вас есть указатели на данные изображения для изображений A, B и T (наша цель), мы можем упростить смешивание всех трех каналов с помощью этого макроса:
да, отличный ответ, спасибо! Мне было интересно, знает ли кто-нибудь, как делается непрозрачность слоя в фотошопе? т.е. я хочу использовать функцию затемнения наложения, но только на 50% ... Я проверил значения в фотошопе, и мне не кажется, что достаточно взять только 50% значений
смешанного
2
Приведенная альфа-формула не является полной - она работает только для случая, когда фон полностью непрозрачен. Если фон прозрачный, результат после рисования может быть прозрачным. Вам нужно применить альфа-смешивание, подобное тому, что описано в Википедии для этого более общего случая.
thenickdude
2
Как насчет альфа-канала? Должен ли я применить к нему функции?
akhy
Отличный ответ !! Reflect и Glow переключаются. В противном случае: отлично !! (Хотя альфа-композитинг отсутствует ..)
TaW
Решение c # для альфа-компоновки: static 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); float 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 ((byte) (ar * 255), r, g, b); }
TaW
7
Режимы наложения Hue, Color, Saturation в этом ответе неправильные. Ни один продукт Adobe не конвертируется в HSB, они выполняют операцию непосредственно со значениями RGB.
Популярный ответ - правильный на 99,9%, но, как сказал Грейфрайарс, точного результата он не получит, потому что Adobe не использует HLS в любой момент при смешивании.
Но вам не обязательно работать в Adobe для этого ... вы можете достичь точно такого же смешивания, следуя всем правилам, приведенным в этом документе от Adobe:
Хотя популярный ответ в основном правильный, следующее утверждение неверно. «Остальные режимы наложения фотошопа включают преобразование RGB в HLS и обратно». Нет, Photoshop (и только Photoshop) использует Chroma и Luma вместо HLS.
Поэтому для режимов Hue, Color, Luminosity и Saturation нельзя использовать простые алгоритмы. Чтобы использовать метод Photoshop в этих случаях, вам нужно работать в Adobe.
Ответы:
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);
Остальные режимы наложения фотошопа включают преобразование 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; }
По этой теме есть больше ресурсов, в основном:
источник
Режимы наложения Hue, Color, Saturation в этом ответе неправильные. Ни один продукт 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); }
В CIKernels нет поддержки операторов if .. else, следовательно, используются тернарные операторы.
источник
Популярный ответ - правильный на 99,9%, но, как сказал Грейфрайарс, точного результата он не получит, потому что Adobe не использует HLS в любой момент при смешивании.
Но вам не обязательно работать в Adobe для этого ... вы можете достичь точно такого же смешивания, следуя всем правилам, приведенным в этом документе от Adobe:
в основном главы 4 и 7: http://partners.adobe.com/public/developer/en/pdf/PDFReference.pdf
Тогда вы получите точный результат, как это делает Adobe! Пиксель за пикселем!
источник
Хотя популярный ответ в основном правильный, следующее утверждение неверно. «Остальные режимы наложения фотошопа включают преобразование RGB в HLS и обратно». Нет, Photoshop (и только Photoshop) использует Chroma и Luma вместо HLS.
Поэтому для режимов Hue, Color, Luminosity и Saturation нельзя использовать простые алгоритмы. Чтобы использовать метод Photoshop в этих случаях, вам нужно работать в Adobe.
источник