2015-04-19 3 views
0

Использование GPUImage Я пытаюсь воспроизвести Photoshop Lighten Blend Mode с непрозрачностью. К сожалению, альфа-канал не имеет эффекта, используя GPUImageLightenBlendFilter.GPUImageLightenBlendFilter с непрозрачностью

Photoshop Lighten Blend Mode with opacity

Брэд подтверждает то, возможно, проблемы с альфа: GPUImage's GPUImageOpacityFilter not behaving as expected, doesn't change alpha channel

я успешно воспроизвели PS смешивания с использованием CoreImage, сохраняющее значение альфа.

CIImage *ciImage1 = [[CIImage alloc] initWithImage:input1]; 
CIImage *ciImage2 = [[CIImage alloc] initWithImage:input2]; 

// Alpha adjustment for input1 
CIFilter *alphaFilter = [CIFilter filterWithName:@"CIColorMatrix"]; 
CGFloat rgba[4] = { 0.0, 0.0, 0.0, 0.5 }; 
CIVector *alphaVector = [CIVector vectorWithValues:rgba count:4]; 
[alphaFilter setValue:alphaVector forKey:@"inputAVector"]; 
[alphaFilter setValue:ciImage1 forKey:kCIInputImageKey]; 

// Lighten blend 
CIFilter *blendFilter = [CIFilter filterWithName:@"CILightenBlendMode"]; 
[blendFilter setValue:alphaFilter.outputImage forKey:kCIInputImageKey]; 
[blendFilter setValue:ciImage2 forKey:kCIInputBackgroundImageKey]; 

Есть 2 версии GPUImage я пытался (они корректируют альфа для input1 с использованием другого метода).

GPUImagePicture *input1 = [[GPUImagePicture alloc] initWithImage:input1]; 
GPUImagePicture *input2 = [[GPUImagePicture alloc] initWithImage:input2]; 

// Alpha adjustment for input1 
GPUImageOpacityFilter *alphaFilter = [GPUImageOpacityFilter new]; 
alphaFilter.opacity = 0.5; 
[input1 addTarget:alphaFilter]; 

// Lighten blend 
GPUImageLightenBlendFilter *blendFilter = [GPUImageLightenBlendFilter new]; 
[alphaFilter addTarget:blendFilter]; 
[input2 addTarget:blendFilter]; 

или:

GPUImagePicture *input1 = [[GPUImagePicture alloc] initWithImage:input1]; 
GPUImagePicture *input2 = [[GPUImagePicture alloc] initWithImage:input2]; 

// Alpha adjustment for input1 
GPUImageColorMatrixFilter *alphaFilter = [GPUImageColorMatrixFilter new]; 
alphaFilter.colorMatrix = (GPUMatrix4x4) { 
    { 1.0, 0.0, 0.0, 0.0 }, 
    { 0.0, 1.0, 0.0, 0.0 }, 
    { 0.0, 0.0, 1.0, 0.0 }, 
    { 0.0, 0.0, 0.0, 0.5 } 
}; 
[input1 addTarget:alphaFilter]; 

// Lighten blend 
GPUImageLightenBlendFilter *blendFilter = [GPUImageLightenBlendFilter new]; 
[alphaFilter addTarget:blendFilter]; 
[input2 addTarget:blendFilter]; 

Оба GPUImage реализации возвращают выход, как если бы альфа для input1 был 1.0.

Я посмотрел на документацию Lighten режим смешивания в различных источниках в Интернете, и все они используют эту формулу:

max(blend, base) 

Глядя на шейдера в реализации GPUImageLightenBlendFilter он также использует ту же формулу:

lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); 
lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); 
gl_FragColor = max(textureColor, textureColor2); 

Однако, кажется, что Photoshop и CoreImage имеют некоторые дополнительные манипуляции с альфой (вероятно, похожие на Gimp: https://github.com/GNOME/gimp/blob/783bbab8a889d4eba80b6a83f2e529937a73a471/app/operations/gimpoperationlightenonlymode.c).

У кого-нибудь есть идеи, как включить альфа-канал в формулу GPUImageLightenBlendFilter?

ответ

0

Я нашел этот Shader код самое лучшее для моего случая:

lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); 
lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); 

textureColor.rgb *= textureColor.a; 
textureColor2.rgb *= textureColor2.a; 
lowp vec4 textureOut = max(textureColor, textureColor2); 
textureOut.rgb /= textureOut.a; 

gl_FragColor = textureOut; 

Найдено здесь: https://github.com/BradLarson/GPUImage/pull/1297

0

Ниже приведен код шейдера для GPUImageLightenBlendFilter с непрозрачностью и количеством.

precision highp float; 
uniform sampler2D inputImageTexture; 
uniform sampler2D inputImageTexture2; 
uniform float alpha; // used for opacity.... 
uniform float amount; // amount of blend.... 
varying vec2 textureCoordinate; 

void main() 
{ 
    // Get samples from both layers 
    vec4 dst = texture2D(inputImageTexture, textureCoordinate); 
    vec4 src = texture2D(inputImageTexture2, textureCoordinate); 

src.a *= alpha; 
vec4 colour = vec4(0.0, 0.0, 0.0, 0.0); 

colour = vec4(max(dst, src).rgb, src.a) * src.a + dst * (1.0 - src.a); 
colour = clamp(colour, 0.0, 1.0); 
gl_FragColor.xyz = mix(dst, colour, amount).rgb; 
gl_FragColor.w = 1.0; 
} 

отлично работает для меня ....

+0

Спасибо за код шейдера , – pirags

Смежные вопросы