Using GPUImage
I am trying to replicate Photoshop Lighten Blend Mode with opacity. Unfortunately the alpha channel has no effect using the GPUImageLightenBlendFilter
.
Brad confirms there might problems with alpha: GPUImage's GPUImageOpacityFilter not behaving as expected, doesn't change alpha channel
I have successfully replicated the PS blending using CoreImage
which respects the alpha value.
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];
There are 2 versions of GPUImage
I have tried (they are adjusting alpha for input1
using a different method).
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];
or:
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];
Both GPUImage
implementations return output as if alpha for input1
was 1.0
.
I have looked at Lighten Blending Mode documentation in different sources on the internet and they all use this formula:
max(blend, base)
Looking at the shader in implementation of GPUImageLightenBlendFilter
it also uses the same formula:
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = max(textureColor, textureColor2);
However, it seems that Photoshop and CoreImage
have some extra manipulation with the alpha (probably similar to Gimp: https://github.com/GNOME/gimp/blob/783bbab8a889d4eba80b6a83f2e529937a73a471/app/operations/gimpoperationlightenonlymode.c).
Anyone has ideas how to include the alpha channel in the GPUImageLightenBlendFilter
formula?
I found this Shader code the best for my case:
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;
Found here: https://github.com/BradLarson/GPUImage/pull/1297