I am wandering for seven hours for solving my issue. I have created project in which i m using GLSurfaceView on which i have set one image and after that i have implement different effects on it using EffectFactory class.
But my Problem is when i have taken a screen shot with effected image it always shows as a black screen instead of with image. I know that may be its because of SurFaceview. But If any suggestion which might be helpful for me.
Thanks in Advance.
Here is my code.
public class EffectsFilterActivity extends Activity implements
GLSurfaceView.Renderer {
private GLSurfaceView mEffectView;
private int[] mTextures = new int[2];
private EffectContext mEffectContext;
private Effect mEffect;
private TextureRenderer mTexRenderer = new TextureRenderer();
private int mImageWidth;
private int mImageHeight;
private boolean mInitialized = false;
int mCurrentEffect;
public void setCurrentEffect(int effect) {
mCurrentEffect = effect;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
Button b = (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Bitmap b = takeScreenshot();
saveBitmap(b);
}
});
mEffectView = (GLSurfaceView) findViewById(R.id.effectsview);
mEffectView.setEGLContextClientVersion(2);
mEffectView.setRenderer(this);
mEffectView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mCurrentEffect = R.id.none;
}
private void loadTextures() {
// Generate textures
GLES20.glGenTextures(2, mTextures, 0);
// Load input bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.puppy);
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
// Upload to texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Set texture parameters
GLToolbox.initTexParams();
}
private void initEffect() {
EffectFactory effectFactory = mEffectContext.getFactory();
if (mEffect != null) {
mEffect.release();
}
/**
* Initialize the correct effect based on the selected menu/action item
*/
switch (mCurrentEffect) {
case R.id.none:
break;
case R.id.autofix:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_AUTOFIX);
mEffect.setParameter("scale", 0.5f);
break;
case R.id.bw:
mEffect = effectFactory
.createEffect(EffectFactory.EFFECT_BLACKWHITE);
mEffect.setParameter("black", .1f);
mEffect.setParameter("white", .7f);
break;
case R.id.brightness:
mEffect = effectFactory
.createEffect(EffectFactory.EFFECT_BRIGHTNESS);
mEffect.setParameter("brightness", 2.0f);
break;
case R.id.contrast:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_CONTRAST);
mEffect.setParameter("contrast", 1.4f);
break;
case R.id.crossprocess:
mEffect = effectFactory
.createEffect(EffectFactory.EFFECT_CROSSPROCESS);
break;
case R.id.documentary:
mEffect = effectFactory
.createEffect(EffectFactory.EFFECT_DOCUMENTARY);
break;
case R.id.duotone:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_DUOTONE);
mEffect.setParameter("first_color", Color.YELLOW);
mEffect.setParameter("second_color", Color.DKGRAY);
break;
case R.id.filllight:
mEffect = effectFactory
.createEffect(EffectFactory.EFFECT_FILLLIGHT);
mEffect.setParameter("strength", .8f);
break;
case R.id.fisheye:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FISHEYE);
mEffect.setParameter("scale", .5f);
break;
case R.id.flipvert:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FLIP);
mEffect.setParameter("vertical", true);
break;
case R.id.fliphor:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FLIP);
mEffect.setParameter("horizontal", true);
break;
case R.id.grain:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_GRAIN);
mEffect.setParameter("strength", 1.0f);
break;
case R.id.grayscale:
mEffect = effectFactory
.createEffect(EffectFactory.EFFECT_GRAYSCALE);
break;
case R.id.lomoish:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_LOMOISH);
break;
case R.id.negative:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_NEGATIVE);
break;
case R.id.posterize:
mEffect = effectFactory
.createEffect(EffectFactory.EFFECT_POSTERIZE);
break;
case R.id.rotate:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_ROTATE);
mEffect.setParameter("angle", 180);
break;
case R.id.saturate:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SATURATE);
mEffect.setParameter("scale", .5f);
break;
case R.id.sepia:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SEPIA);
break;
case R.id.sharpen:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SHARPEN);
break;
case R.id.temperature:
mEffect = effectFactory
.createEffect(EffectFactory.EFFECT_TEMPERATURE);
mEffect.setParameter("scale", .9f);
break;
case R.id.tint:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_TINT);
mEffect.setParameter("tint", Color.MAGENTA);
break;
case R.id.vignette:
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_VIGNETTE);
mEffect.setParameter("scale", .5f);
break;
default:
break;
}
}
private void applyEffect() {
mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]);
}
private void renderResult() {
if (mCurrentEffect != R.id.none) {
// if no effect is chosen, just render the original bitmap
mTexRenderer.renderTexture(mTextures[1]);
} else {
// render the result of applyEffect()
mTexRenderer.renderTexture(mTextures[0]);
}
}
@Override
public void onDrawFrame(GL10 gl) {
if (!mInitialized) {
// Only need to do this once
mEffectContext = EffectContext.createWithCurrentGlContext();
mTexRenderer.init();
loadTextures();
mInitialized = true;
}
if (mCurrentEffect != R.id.none) {
// if an effect is chosen initialize it and apply it to the texture
initEffect();
applyEffect();
}
renderResult();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if (mTexRenderer != null) {
mTexRenderer.updateViewSize(width, height);
}
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
setCurrentEffect(item.getItemId());
mEffectView.requestRender();
return true;
}
public Bitmap takeScreenshot() {
mEffectView.getRootView();
mEffectView.setDrawingCacheEnabled(true);
mEffectView.buildDrawingCache();
mEffectView.requestRender();
return mEffectView.getDrawingCache();
}
public void saveBitmap(Bitmap bitmap) {
File imagePath = new File(Environment.getExternalStorageDirectory()
+ "/Piyush.png");
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
}
GLToolbox.java
public class GLToolbox {
public static int loadShader(int shaderType, String source) {
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
String info = GLES20.glGetShaderInfoLog(shader);
GLES20.glDeleteShader(shader);
shader = 0;
throw new RuntimeException("Could not compile shader "
+ shaderType + ":" + info);
}
}
return shader;
}
public static int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0) {
return 0;
}
int program = GLES20.glCreateProgram();
if (program != 0) {
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GLES20.GL_TRUE) {
String info = GLES20.glGetProgramInfoLog(program);
GLES20.glDeleteProgram(program);
program = 0;
throw new RuntimeException("Could not link program: " + info);
}
}
return program;
}
public static void checkGlError(String op) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
throw new RuntimeException(op + ": glError " + error);
}
}
public static void initTexParams() {
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_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);
}
}
TextureRenderer.java
public class TextureRenderer {
private int mProgram;
private int mTexSamplerHandle;
private int mTexCoordHandle;
private int mPosCoordHandle;
private FloatBuffer mTexVertices;
private FloatBuffer mPosVertices;
private int mViewWidth;
private int mViewHeight;
private int mTexWidth;
private int mTexHeight;
private static final String VERTEX_SHADER = "attribute vec4 a_position;\n"
+ "attribute vec2 a_texcoord;\n" + "varying vec2 v_texcoord;\n"
+ "void main() {\n" + " gl_Position = a_position;\n"
+ " v_texcoord = a_texcoord;\n" + "}\n";
private static final String FRAGMENT_SHADER = "precision mediump float;\n"
+ "uniform sampler2D tex_sampler;\n" + "varying vec2 v_texcoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(tex_sampler, v_texcoord);\n" + "}\n";
private static final float[] TEX_VERTICES = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f };
private static final float[] POS_VERTICES = { -1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f, 1.0f };
private static final int FLOAT_SIZE_BYTES = 4;
public void init() {
// Create program
mProgram = GLToolbox.createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
// Bind attributes and uniforms
mTexSamplerHandle = GLES20
.glGetUniformLocation(mProgram, "tex_sampler");
mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texcoord");
mPosCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_position");
// Setup coordinate buffers
mTexVertices = ByteBuffer
.allocateDirect(TEX_VERTICES.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTexVertices.put(TEX_VERTICES).position(0);
mPosVertices = ByteBuffer
.allocateDirect(POS_VERTICES.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mPosVertices.put(POS_VERTICES).position(0);
}
public void tearDown() {
GLES20.glDeleteProgram(mProgram);
}
public void updateTextureSize(int texWidth, int texHeight) {
mTexWidth = texWidth;
mTexHeight = texHeight;
computeOutputVertices();
}
public void updateViewSize(int viewWidth, int viewHeight) {
mViewWidth = viewWidth;
mViewHeight = viewHeight;
computeOutputVertices();
}
public void renderTexture(int texId) {
// Bind default FBO
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
// Use our shader program
GLES20.glUseProgram(mProgram);
GLToolbox.checkGlError("glUseProgram");
// Set viewport
GLES20.glViewport(0, 0, mViewWidth, mViewHeight);
GLToolbox.checkGlError("glViewport");
// Disable blending
GLES20.glDisable(GLES20.GL_BLEND);
// Set the vertex attributes
GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT,
false, 0, mTexVertices);
GLES20.glEnableVertexAttribArray(mTexCoordHandle);
GLES20.glVertexAttribPointer(mPosCoordHandle, 2, GLES20.GL_FLOAT,
false, 0, mPosVertices);
GLES20.glEnableVertexAttribArray(mPosCoordHandle);
GLToolbox.checkGlError("vertex attribute setup");
// Set the input texture
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLToolbox.checkGlError("glActiveTexture");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
GLToolbox.checkGlError("glBindTexture");
GLES20.glUniform1i(mTexSamplerHandle, 0);
// Draw
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
private void computeOutputVertices() {
if (mPosVertices != null) {
float imgAspectRatio = mTexWidth / (float) mTexHeight;
float viewAspectRatio = mViewWidth / (float) mViewHeight;
float relativeAspectRatio = viewAspectRatio / imgAspectRatio;
float x0, y0, x1, y1;
if (relativeAspectRatio > 1.0f) {
x0 = -1.0f / relativeAspectRatio;
y0 = -1.0f;
x1 = 1.0f / relativeAspectRatio;
y1 = 1.0f;
} else {
x0 = -1.0f;
y0 = -relativeAspectRatio;
x1 = 1.0f;
y1 = relativeAspectRatio;
}
float[] coords = new float[] { x0, y0, x1, y0, x0, y1, x1, y1 };
mPosVertices.put(coords).position(0);
}
}
}
My Xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
tools:ignore="HardcodedText" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="0.1"
android:text="Button" />
<android.opengl.GLSurfaceView
android:id="@+id/effectsview"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0.9" />
</LinearLayout>
try this...