当前位置: 首页 > 知识库问答 >
问题:

使用GLSURFACHEVIEW修改具有效果的摄影机预览

缪兴腾
2023-03-14

我已经创建了一个自定义相机应用程序,我正在使用GLsurfaceviewGLsurfaceview。用于创建摄影机预览的渲染器。我已经成功地完成了它,现在我正在尝试应用过滤器(乌贼模式,空白n白色等)的相机预览。如何在摄影机预览上应用效果。

这是我的视频。渲染器

public class MainRenderer implements GLSurfaceView.Renderer,SurfaceTexture.OnFrameAvailableListener{

private final String vss =
        "attribute vec2 vPosition;\n" +
                "attribute vec2 vTexCoord;\n" +
                "varying vec2 texCoord;\n" +
                "void main() {\n" +
                "  texCoord = vTexCoord;\n" +
                "  gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n" +
                "}";
private final String fss =
        "#extension GL_OES_EGL_image_external : require\n" +
                "precision mediump float;\n" +
                "uniform samplerExternalOES sTexture;\n" +
                "varying vec2 texCoord;\n" +
                "void main() {\n" +
                "  gl_FragColor = texture2D(sTexture,texCoord);\n" +
                "}";

private int[] hTex;
private FloatBuffer pVertex;
private FloatBuffer pTexCoord;
private int hProgram;

private Camera mCamera;
private SurfaceTexture mSTexture;

private boolean mUpdateST = false;

private CameraPreview mView;
Context mContext;
private String fileName;
private File sdRoot;
private String dir;
private ExifInterface exif;
private int orientation;
private android.hardware.Camera.PictureCallback pictureCallBack = new Camera.PictureCallback() {

    public void onPictureTaken(byte[] data, Camera camera) {

        fileName = "IMG_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()).toString() + ".jpg";
        File mkDir = new File(sdRoot, dir);
        mkDir.mkdirs();
        File pictureFile = new File(sdRoot, dir + fileName);
        try {
            FileOutputStream purge = new FileOutputStream(pictureFile);
            purge.write(data);
            purge.close();
        } catch (FileNotFoundException e) {
            Log.d("DG_DEBUG", "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d("DG_DEBUG", "Error accessing file: " + e.getMessage());
        }
        // Adding Exif data for the orientation. For some strange reason the
        // ExifInterface class takes a string instead of a file.
        try {
            exif = new ExifInterface("/sdcard/" + dir + fileName);
            exif.setAttribute(ExifInterface.TAG_ORIENTATION, "" + orientation);
            exif.saveAttributes();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(pictureFile)));

    }
};;

public MainRenderer(CameraPreview cameraPreview, Context context) {
    mView = cameraPreview;
    mContext = context;
    mCamera = getCameraInstance();
    float[] vtmp = { 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f };




    float[] ttmp = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };
    pVertex = ByteBuffer.allocateDirect(8 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
    pVertex.put ( vtmp );
    pVertex.position(0);
    pTexCoord = ByteBuffer.allocateDirect(8*4).order(ByteOrder.nativeOrder()).asFloatBuffer();
    pTexCoord.put ( ttmp );
    pTexCoord.position(0);
}
public void close()
{
    mUpdateST = false;
    mSTexture.release();
    mCamera.stopPreview();
    mCamera.release();
    mCamera = null;
    deleteTex();
}
public void takePicture(File file,String dir,int orientation){
    this.orientation = orientation;
    sdRoot = file;
    this.dir=dir;
    mCamera.takePicture(null,null,pictureCallBack);
}
private void initTex() {
    hTex = new int[1];
    GLES20.glGenTextures(1, hTex, 0);
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, hTex[0]);
    GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
    GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
}

private void deleteTex() {
    GLES20.glDeleteTextures ( 1, hTex, 0 );
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    initTex();
    mSTexture = new SurfaceTexture ( hTex[0] );
    mSTexture.setOnFrameAvailableListener(this);
    try {
        mCamera.setPreviewTexture(mSTexture);
    } catch ( IOException ioe ) {
    }
    catch (Exception e){
    }
    GLES20.glClearColor ( 1.0f, 1.0f, 0.0f, 1.0f );
    hProgram = loadShader ( vss, fss );
}

public Camera getCameraInstance() {
    Camera c = null;
    Camera.CameraInfo ci = new Camera.CameraInfo();
    try {
        for(int i=0;i<Camera.getNumberOfCameras();i++){
            Camera.getCameraInfo(i,ci);
            if(ci.facing== Camera.CameraInfo.CAMERA_FACING_FRONT)
                c=Camera.open(i);
        }
    } catch (Exception e) {
    }
    return c;

}
private static int loadShader ( String vss, String fss ) {
    int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
    GLES20.glShaderSource(vshader, vss);
    GLES20.glCompileShader(vshader);
    int[] compiled = new int[1];
    GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, compiled, 0);
    if (compiled[0] == 0) {
        Log.e("Shader", "Could not compile vshader");
        Log.v("Shader", "Could not compile vshader:"+GLES20.glGetShaderInfoLog(vshader));
        GLES20.glDeleteShader(vshader);
        vshader = 0;
    }

    int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
    GLES20.glShaderSource(fshader, fss);
    GLES20.glCompileShader(fshader);
    GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, compiled, 0);
    if (compiled[0] == 0) {
        Log.e("Shader", "Could not compile fshader");
        Log.v("Shader", "Could not compile fshader:"+GLES20.glGetShaderInfoLog(fshader));
        GLES20.glDeleteShader(fshader);
        fshader = 0;
    }

    int program = GLES20.glCreateProgram();
    GLES20.glAttachShader(program, vshader);
    GLES20.glAttachShader(program, fshader);
    GLES20.glLinkProgram(program);

    return program;
}

@Override
public void onSurfaceChanged ( GL10 unused, int width, int height ) {
    GLES20.glViewport( 0, 0, width, height );
    Camera.Parameters param = mCamera.getParameters();
    List<Camera.Size> psize = param.getSupportedPreviewSizes();
    if ( psize.size() > 0 ) {
        int i;
        for ( i = 0; i < psize.size(); i++ ) {
            if ( psize.get(i).width < width || psize.get(i).height < height )
                break;
        }
        if ( i > 0 )
            i--;
        param.setPreviewSize(psize.get(i).width, psize.get(i).height);
        //Log.i("mr","ssize: "+psize.get(i).width+", "+psize.get(i).height);
    }
    param.set("orientation", "portrait");
    mCamera.setParameters ( param );
    mCamera.startPreview();
}

@Override
public void onDrawFrame ( GL10 unused ) {
    GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT );

    synchronized(this) {
        if ( mUpdateST ) {
            mSTexture.updateTexImage();
            mUpdateST = false;
        }
    }

    GLES20.glUseProgram(hProgram);


    int ph = GLES20.glGetAttribLocation(hProgram, "vPosition");
    int tch = GLES20.glGetAttribLocation ( hProgram, "vTexCoord" );
    int th = GLES20.glGetUniformLocation ( hProgram, "sTexture" );

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, hTex[0]);
    GLES20.glUniform1i(th, 0);

    GLES20.glVertexAttribPointer(ph, 2, GLES20.GL_FLOAT, false, 4*2, pVertex);
    GLES20.glVertexAttribPointer(tch, 2, GLES20.GL_FLOAT, false, 4*2, pTexCoord );
    GLES20.glEnableVertexAttribArray(ph);
    GLES20.glEnableVertexAttribArray(tch);

    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    GLES20.glFlush();
}

@Override
public synchronized void onFrameAvailable ( SurfaceTexture st ) {
    mUpdateST = true;
    mView.requestRender();
}

}

共有1个答案

陈和裕
2023-03-14

在OpengGL中应用过滤器基本上只是对片段着色器中的gl\u FragColor的值执行一些操作。一些复杂的过滤器可能需要在顶点着色器中执行计算(尺寸、坐标)。

例如,如果要应用黑/白过滤器,请更改片段着色器,如下所示。

private final String fss =
    "#extension GL_OES_EGL_image_external : require\n" +
            "precision mediump float;\n" +
            "uniform samplerExternalOES sTexture;\n" +
            "varying vec2 texCoord;\n" +
            "void main() {\n" +
            "  vec4 tc = texture2D(sTexture, texCoord);\n" +
            "  float luminance = 0.3 * tc.r + 0.59 * tc.g + 0.11 * tc.b;\n" +
            "  gl_FragColor = vec4(luminance, luminance, luminance, 1.0);\n" +
            "}";

您可以在Android GPUImage中找到更多示例和过滤效果。

 类似资料:
  • 使用摄影机 安装PSP™专用的摄影机(选购品)后,可拍摄静止图像或影像。 若要使用此机能,需先准备另售的周边机器。有关周边机器的详情,请参阅各区域的官方网站。 您使用的PSP™ 必要的周边机器 PSP-1000/2000/3000系列 摄影机(PSP™主机专用) Memory Stick™ PSP-N1000系列 摄影机(PSP™主机专用) 转接线转换器 部分区域可能并未贩卖摄影机。 拍摄图像或影

  • 我正在尝试制作一个在实时相机上画画的应用程序。在这种情况下,我用xib创建了一个名为的类,其中所有与绘画相关的功能都在运行。 我正在添加到视图。视图添加正确。但是当我触摸设备屏幕时,应用程序无法绘制任何东西,日志显示以下错误 我添加子视图的代码是 请帮助我,如何在现场摄像机上画画!!! 提前谢谢。 编辑:在绘制视图中,我创建了图像视图,初始化如下 =[[UIImageView alloc]init

  • 在这个框架中,每一个元素都一个 z 方向的深度,这个决定了这个元素是远离页面还是贴近页面。 你可以很简单的应用一个阴影效果,通过增加 class="z-depth-2" 类到 HTML 标签中。或者你可以继承这些阴影通过 Sass,通过使用 @extend .z-depth-2. A z-depth-0 来移除元素原有的深度的阴影。 <div class="col s12 m2"> <p clas

  • 问题内容: 我是Python和Matplotlib的新手。我的计算机连接到两个USB摄像机,我打算使用matplotlib中的subplot(1,2,1)和subplot(1,2,2)来按时间序列绘制来自两个摄像机的帧。当我用代码执行此操作时,我要么只绘制一帧,要么在绘制区域中出现黑屏。 我的代码如下所示 问题答案: 互动模式 在matplotlib中更新图的一种方法是使用交互模式()。然后,您不

  • 在CSS3之前,要在网页中使用倒影效果,只能事先使用 photoshop 将倒影设计好,然后导入到网页中,这不但耗费资源,而且影响开发的效率。 CSS3中,新增了 box-reflect属性,通过该属性为元素添加倒影效果。语法格式为: box-reflect:<direction> <offset>? <mask-box-image>? 也就是说,在 box-reflect属性中,通过 dire

  • 问题内容: 我可以使用以下内容滚动到200px 但是我想要一个平滑的滚动效果。我该怎么做呢? 问题答案: 现在,您可以使用来平滑滚动页面。 较旧的解决方案 您可以执行以下操作: ES6 递归方法: