问题
I am trying to create an app, in android using opengl es 2.0, that has a button on pressing which it would take the screenshot and would blurr it using any blur algo (here Fast blur) and would display the blurred screenshot. The sole aim of developing such an app is to try and implement blurring. Using various internet resources i was able to take the screenshot and implement blurring but i dont know how to display the blurred bitmap on the screen in opengl. Can anyone please help me with this? Thanks in advance. Following is my Main activity:
package com.example.ankurtest;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class MainActivity extends Activity {
GLSurfaceView mView;
GLRendererEX myRenderer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//setContentView(mView);
mView = (MyGLSurfaceview)findViewById(R.id.glSurfaceViewID);
myRenderer = new GLRendererEX(this);
mView.setEGLContextClientVersion(2);
mView.setRenderer(myRenderer);
myRenderer.queueDoSomethingNextTick(GLRendererEX.DO_THIS);
findViewById(R.id.buttonID).setOnTouchListener(new OnTouchListener(){
/* public void onTouch(MotionEvent event){
myRenderer.queueDoSomethingNextTick(GLRendererEX.DO_THAT);
// Compiler might complain about myRenderer not being final
}*/
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
myRenderer.queueDoSomethingNextTick(GLRendererEX.DO_THAT);
return true;
}
return false;
}
});
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
mView.onPause();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
mView.onResume();
}
}
Following is my MyGLsurfaceview class:
package com.example.ankurtest;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
public class MyGLSurfaceview extends GLSurfaceView {
//private final GLRendererEX mRenderer;
public MyGLSurfaceview(Context context) {
super(context);
// Create an OpenGL ES 2.0 context.
//setEGLContextClientVersion(2);
// Set the Renderer for drawing on the GLSurfaceView
//mRenderer = new GLRendererEX();
//setRenderer(mRenderer);
// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
public MyGLSurfaceview(Context context, AttributeSet attrs)
{
super(context, attrs);
// Create an OpenGL ES 2.0 context.
setEGLContextClientVersion(2);
// Set the Renderer for drawing on the GLSurfaceView
//mRenderer = new GLRendererEX();
//setRenderer(mRenderer);
}
}
Following is my Renderer class:
package com.example.ankurtest;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Build;
import android.view.Display;
import android.view.WindowManager;
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public class GLRendererEX implements Renderer{
private final Context context;
private int command;
public static final int DO_THIS = 1;
public static final int DO_THAT = 2;
public GLRendererEX(Context activitycontext) {
context = activitycontext;
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.8f, 0.0f, 0.2f, 1f);
// TODO Auto-generated method stub
}
@Override
public void onDrawFrame(GL10 gl) {
if (command==DO_THAT) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Point size = new Point();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
//myactivity.getWindowManager().getDefaultDisplay().getSize(size);
display.getSize(size);
int width = size.x; // use your favorite width
int height = size.y; // use your favorite height
int screenshotSize = width * height;
ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
bb.order(ByteOrder.nativeOrder());
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, bb);
int pixelsBuffer[] = new int[screenshotSize];
bb.asIntBuffer().get(pixelsBuffer);
bb = null;
for (int i = 0; i < screenshotSize; ++i) {
// The alpha and green channels' positions are preserved while the red and blue are swapped
pixelsBuffer[i] = ((pixelsBuffer[i] & 0xff00ff00)) | ((pixelsBuffer[i] & 0x000000ff) << 16) | ((pixelsBuffer[i] & 0x00ff0000) >> 16);
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixelsBuffer, screenshotSize-width, -width, 0, 0, width, height);
Bitmap fast = Fastblur(bitmap,10);
command = DO_THIS;
}
// TODO Auto-generated method stub
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
}
public void queueDoSomethingNextTick(int command){
this.command = command;
}
}
Herein Fastblur() method is used to blur the screenshot and it returns the blurred screenshot. Now, my question is how to display the bitmap returned by Fastblur() using opengl?
回答1:
The common method to display a full sized image is to use an orthogonal projection matrix:
(example using fixed functionality)
GLES20.glViewport(0, 0, windowWidth, windowHeight);
GLES20.glMatrixMode(GL_PROJECTION);
GLES20.glLoadIdentity();
GLES20.glOrtho(-1, 1, -1, 1, 1, -1);
than draw a fullscreen quad with your image bound as texture2D.
basic texture tutorial here.
basic quad tutorial here.
set quad coordinate as follow:
static float squareCoords[] = {
-1f, -1f, 0.0f, // top left
-1f, 1f, 0.0f, // bottom left
1f, 1f, 0.0f, // bottom right
1f, -1f, 0.0f }; // top right
来源:https://stackoverflow.com/questions/22574817/how-to-display-blurred-bitmap-of-screenshot-using-opengl-es-2-0-on-android