Reputation: 744
I have a GLSurfaceView
on which I am putting an image and applying the GRAYSCALE
effect, as follows:
final GLSurfaceView glView = (GLSurfaceView) findViewById(R.id.glSurfaceImg);
glView.setEGLContextClientVersion(2);
glView.setRenderer(new EffectsRenderer(this, bitmap_resized, EffectFactory.EFFECT_GRAYSCALE));
glView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
Above code is working fine, that is, the image is showing properly, with the correct filter as well. But I have a button as well, clicking on which, I want the filter effect on the image to change from EFFECT_GRAYSCALE
to EFFECT_GRAIN
for which I am running the following code:
myButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
glView.setRenderer(new EffectsRenderer(ImageFiltersActivity.this, bitmap_resized, EffectFactory.EFFECT_GRAIN));
}
});
But the above code is not working. When I click on the button, I get the following error: java.lang.IllegalStateException: setRenderer has already been called for this instance.
What do I do now as a turnaround to this problem, in order to achieve my goal of applying a different filter on the image on clicking on my button?
My EffectsRenderer
class goes as follows (in case it is required for reference):
public class EffectsRenderer implements GLSurfaceView.Renderer {
private Bitmap photo;
private int photoWidth, photoHeight;
private int textures[] = new int[2];
private Square square;
private String filter;
private EffectContext effectContext;
private Effect effect;
public EffectsRenderer(Context context, Bitmap bitmap, String filter){
super();
photo = bitmap;
this.filter = filter;
photoWidth = photo.getWidth();
photoHeight = photo.getHeight();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0,0,width, height);
GLES20.glClearColor(0,0,0,1);
generateSquare();
}
@Override
public void onDrawFrame(GL10 gl) {
if(effectContext==null) {
effectContext = EffectContext.createWithCurrentGlContext();
}
if(effect!=null){
effect.release();
}
applyFilter();
square.draw(textures[1]);
}
private void generateSquare(){
GLES20.glGenTextures(2, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, photo, 0);
square = new Square();
}
private void applyFilter(){
EffectFactory factory = effectContext.getFactory();
effect = factory.createEffect(filter);
effect.apply(textures[0], photoWidth, photoHeight, textures[1]);
}
}
Upvotes: 0
Views: 938
Reputation: 52313
You aren't allowed to call setRenderer()
more than once, as noted in the documentation.
Instead, use a single Renderer instance, and have it switch behavior. Modify your onDrawFrame()
to detect that the requested filter has changed, and react appropriately.
Upvotes: 1