chrisbatt / AndroidFastImageProcessing

A framework for speeding up image processing on android devices by taking advantage of shaders on the GPU.
MIT License
285 stars 118 forks source link

Blend filters don't work correctly with images that has transparency. #3

Closed igor-korotenko closed 10 years ago

igor-korotenko commented 10 years ago

I've also noticed that not only normal blend filter has an error, but when trying to apply almost all blend filters I've got either black screen or my overlay image but with black color in place where transparent should be. Also I've noticed some differences in behaviour of filters on htc ONE X and samsung galaxy SIII. HTC behaves like nexus genymotion emulator in blending, but samsung works another way and some of filters working. But normal filter don't work too. I've tried to change colors in NormalBlend shader to this. +"void main(){\n" +" vec4 color2 = texture2D("+UNIFORM_TEXTURE+","+VARYING_TEXCOORD+");\n" +" vec4 color1 = texture2D("+UNIFORM_TEXTURE2+","+VARYING_TEXCOORD+");\n"

I've made a little videos. https://www.youtube.com/watch?v=FBimYZQZWy4 - sgs3 https://www.youtube.com/watch?v=5Dccx4nW0N4 - htc one x

chrisbatt commented 10 years ago

From looking at the videos, my best guess is that you are using a texture that is not a power of two width or height (128, 256, 512, etc...). Some hardware does not support non-power of two opengl es textures and my guess is that the htc one x is one of the phones that does not. This would result in the top texture being completely black and in the video that appears to be what is happening. I never got around to check the support for non-power of two textures and handling the alteration of the image to make it usable, so it is currently up to the user of this framework to make sure the texture is the correct size for the supported hardware. I will leave this ticket open until I get a chance to add that feature in. To make sure that is the problem, could you check the size of the image that you are passing in and could you trying using that image in one of the single image filters and see if produces a black screen?

As for the black where it should be transparent, it is transparent and not black. What you are seeing is actually the background on the opengl view. Some of the filters use the first input's alpha as the output alpha and therefore are meant to be used with a non-transparent front layer. In your tests you are using an image with transparency, so the resulting blend of the two images has the same transparency. This lets you see straight through the two images to the black opengl background behind them. You can test this by changing the opengl background colour. There may be a couple filters in there that have missed a divide by 0 check, but filters such as the ColourBlend or LinearBurn are not examples of such.

On a side note, changing the text coords to use the specific coords for each of the images is not required, because the size of the images when rendering will always be the same and we always want to look at the same pixel in each of the two images.

Cheers, Chris Batt

igor-korotenko commented 10 years ago

Concerning size that should be a power of two your theory is right, I used 512x512 overlay picture and now effect on htc is the same as on sgs3. Also I checked this on single input filter and yes, it produces a black screen when 513x513 image for example, at same time when i changed it to 512x512 its ok.

igor-korotenko commented 10 years ago

But I've tried to change alpha of final filter and had no effect, still black instead of transparent.

chrisbatt commented 10 years ago

Instead of having your image with a transparent background. Set the background to white and see what effect it has on the filter. Some filters require alpha values and some require the alpha values to be set to 1.0, so finding an image that works for all filters is probably not feasible, but to understand how the filters work you should try some different kinds of alpha value images.

igor-korotenko commented 10 years ago

I tried with white pixels in place of transparent in overlay image and black becomes white in blended output, also tried to change the code of normal blend fragment shader to: ... +" vec4 color2 = texture2D("+UNIFORM_TEXTURE+","+VARYING_TEXCOORD+");\n" +" vec4 color1 = texture2D("+UNIFORM_TEXTURE2+","+VARYING_TEXCOORD+");\n" +" vec4 outputColor;\n" +" float a = color1.a + color2.a * (1.0 - color1.a);\n" +" outputColor.r = color1.r + color2.r * color2.a * (1.0 - color1.a);\n" +" outputColor.g = color1.g + color2.g * color2.a * (1.0 - color1.a);\n" +" outputColor.b = color1.b + color2.b * color2.a * (1.0 - color1.a);\n" +" outputColor.a = a;\n" ...

I made a lot of experiments with GLRenderer.setBackgroundAlpha() but transparent parts pixels are still black

chrisbatt commented 10 years ago

Changed the GLTextureOutputRenderer to use RGBA instead of RGB. Should be fixed :)