1

I have a fixed size frame buffer (1200x720 RGBA efficiently converted from YUV) in a java byte array.

I would like to set a certain shade of a color (white in my case, regardless of its alpha value) to fully transparent.

Currently I am doing this via CPU by traversing the byte array and zero'ing the pixel if RGB > 0xC8. This somewhat works but is obviously extremely slow (>1sec/frame) for doing so on a live stream.

I've been researching methods to do this via GPU/OpenGL on Android and I see mentioning of Alpha test, blending, and color keying. It seems the alpha test is not useful here since it relies on the alpha information rather than RGB's values.

Any idea how to do this on Android using OpenGL/java?

Janvi Vyas
  • 732
  • 5
  • 16
John Smith
  • 307
  • 3
  • 14

2 Answers2

1

It seems the alpha test is not useful here

The logic for an alpha-test is implemented in the fragment shader, so rather than testing alpha just change the test to implement a check on the RGB value. The technique here is generic and 100% flexible. The underlying operation you are looking for is fragment shaders which trigger the discard operation when the color key matches.

Alternatively you can use the same conditional check but rather than calling discard just set the output color to vec4(0.0) and use blending to avoid modifying the framebuffer for that fragment. On the whole I would expect this to be more efficient; discard tends to have odd perfomance side-effects.

solidpixel
  • 10,688
  • 1
  • 20
  • 33
  • Got it. Used the code from https://stackoverflow.com/questions/12130790/yuv-to-rgb-conversion-by-fragment-shader/17615696#17615696 – John Smith May 07 '18 at 20:06
  • "and use blending to avoid modifying.." Any idea where to start regarding this? I'm able to hide the pixel by outputing vec4(0.0) just not sure how to use blending here – John Smith May 07 '18 at 20:07
  • Blending typically uses the source alpha to determine the weighting of the computed fragment color (source) vs the current framebuffer (dst). A standard blend is `(SRC_COLOR * SRC_ALPHA) + (DST_COLOR * (1 - SRC_ALPHA))`, so if you set the fragment alpha to zero then you should only get the destination color emitted (assuming blending is enabled). – solidpixel May 11 '18 at 19:55
0

You should create a custom renderscript script to convert those pixels, you can also use it to convert from yuv so you only process the pixels in the buffer once

Quentin Menini
  • 160
  • 1
  • 1
  • 12