【问题标题】:How to Display blurred bitmap of screenshot using opengl es 2.0 on android?如何在android上使用opengl es 2.0显示屏幕截图的模糊位图?
【发布时间】:2014-03-22 07:34:22
【问题描述】:

我正在尝试使用opengl es 2.0在android中创建一个应用程序,该应用程序有一个按下按钮,它将截取屏幕截图并使用任何模糊算法(此处为快速模糊)对其进行模糊处理,并显示模糊的屏幕截图。开发这样一个应用程序的唯一目的是尝试和实现模糊。使用各种互联网资源,我能够截取屏幕截图并实现模糊,但我不知道如何在 opengl 的屏幕上显示模糊的位图。谁能帮我解决这个问题?提前致谢。 以下是我的主要活动:

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();
}

    }

以下是我的 MyGLsurfaceview 类:

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);
}

}

以下是我的渲染器类:

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;

}

}

这里使用Fastblur()方法对截图进行模糊处理,返回模糊后的截图。现在,我的问题是如何使用 opengl 显示 Fastblur() 返回的位图?

【问题讨论】:

  • orthographic projection绘制一个由2个三角形组成的带纹理的四边形(精灵)或使用任何你喜欢的精灵绘图包装器。

标签: android opengl-es bitmap blur


【解决方案1】:

显示全尺寸图像的常用方法是使用正交投影矩阵:

(使用固定功能的示例)

GLES20.glViewport(0, 0, windowWidth, windowHeight);
GLES20.glMatrixMode(GL_PROJECTION);
GLES20.glLoadIdentity();
GLES20.glOrtho(-1, 1, -1, 1, 1, -1);

而不是绘制一个将图像绑定为 texture2D 的全屏四边形。

纹理基础教程here.

基本四边形教程here

设置四边形坐标如下:

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

【讨论】:

  • Fixed function 是常用方法吗?在stone age?
  • @Drop 你在哪里看到固定功能?如果他想要一个着色器没有问题,但是看到它的代码级别,他可能还没有准备好在片段着色器中进行模糊......
  • glMatrixMode(), glLoadIdentity(), glOrtho() 是一个矩阵堆栈功能,它是固定功能管道的一部分,已经过时了几年。无论如何,这不再常见了。这正是我想说的。
  • 固定管道使用这些矩阵的事实并不意味着在更简单的顶点缓冲区中使用它们已过时。使用它们可以让您访问不影响性能的默认着色器变量(例如:gl_ModelViewProjectionMatrix),至少我猜是这样......
  • @Drop 好的,你是对的,但是对于简单的示例和教程,它们是无价的!​​span>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 2020-05-14
相关资源
最近更新 更多