Android相机预览SurfaceTexture翻译界限

时间:2014-10-23 15:45:25

标签: android opengl-es android-camera opengl-es-2.0

我正在开展一个项目,要求我“围观”相机预览以找到一个小区域。通过将预览渲染到SurfaceTexture并将变换应用于传递到顶点着色器的顶点,我得到了部分工作。用户看到并能够“平移”的“裁剪”区域为1024x1024,相机预览尺寸为1920x1080。

我遇到的问题基本上是找到预览的界限。我可以将顶点完全从屏幕上移开,它将继续移动。我已经尝试了几种解决这个问题的策略,但我没有运气。

我尝试的第一件事是计算形状顶点中的值,使预览与视图齐平。如果没有应用任何比例,形状顶点的范围应为[-1,1]。向下,向下和向左方向的顶点都是如此。但是,我通过反复试验发现右边缘的偏移量为.12。这完全符合逻辑,因为相机预览比显示它的视图宽得多。我不确定为了强制执行边界我应该如何解释。

/* Initial position of the shape */
{ -1.0  1.0 
  -1.0 -1.0 
   1.0 -1.0 
   1.0  1.0 }

/* Right edge against the screen */
{    -1.12  1.0 
     -1.12 -1.0 
      0.88 -1.0 
      0.88  1.0  }

出于好奇,接下来我尝试使用glReadPixel来获取屏幕边缘的像素列。如果形状从屏幕上移开,我发现我得到的像素都是相同的。这一直都有效,直到我达到上面提到的偏移量。在[-1,1]有效切断最后一部分后,我所拥有的像素都相等。这只是我用来测试水域的东西。

glReadPixel(1023, 0, 1, 1024);

鉴于我正在使用openGL es 2.0,显然很难从着色器解释数据。为了试着看看发生了什么,我编写了一个小实用程序函数来在着色器中应用转换并将它们打印出来,这就是上面顶点的来源。

有没有人对此有任何见解?我试图寻找任何可以指向正确方向的东西,但我什么都没有。如果有任何有用的代码请告诉我,如果可以,我会发布。

public void printFinalShapeCoords(float coords[]) {
    float shapeCoords[] = new float[8];
    for(int i = 0; i < coords.length; i+=2) {
        mScratchVector[0] = coords[i];
        mScratchVector[1] = coords[i+1];
        mScratchVector[2] = 0;
        mScratchVector[3] = 1;
        Matrix.multiplyMV(mTempVector, 0, mMVPMatrix, 0, mScratchVector, 0);
        shapeCoords[i] = mTempVector[0];
        shapeCoords[i+1] = mTempVector[1];
    }
    Log.e(TAG, "Final shape coords:\n"+Arrays.toString(shapeCoords));
}

顶点着色器:

                "uniform mat4 u_MVPMatrix;"+                /* 4x4 MVP matrix */
            "attribute vec4 vPosition;" +               /* Position vector */
            "attribute vec2 inputTextureCoordinate;" +  /* Texture coordinates */
            "varying vec2 textureCoordinate;" +         /* Texture coordinates that are passed to the fragment shader */
            "void main()" +
            "{"+
                "gl_Position = u_MVPMatrix*vPosition;"+ /* Multiply the MVP matrix and the position vector */
                "textureCoordinate = inputTextureCoordinate;" +
            "}";

Fragment Shader:

            "#extension GL_OES_EGL_image_external : require\n"+
            "precision mediump float;" +
            "varying vec2 textureCoordinate;\n" +
            "uniform samplerExternalOES s_texture;\n" +
            "void main() {" +
            "  gl_FragColor = texture2D( s_texture, textureCoordinate );\n" +
            "}";

编辑(2014年10月24日美国东部时间下午3:07)

一条评论提到我不太清楚我想要完成什么,我想尝试澄清一下。

基本上,我正在尝试显示相机预览的一部分,同时能够在按下按钮时查看剩余的预览。显示的部分为1024x1024,而相机预览尺寸为1920x1080。我想要的行为的一个例子是在Gallery应用程序中。在查看图片时,用户可以“缩放”然后“遍历”图片的其余部分。我试图这样做,但使用相机预览而不是静态图像。正如我之前提到的,我有缩放/平移工作正常,但我找不到停止平移的点。

1 个答案:

答案 0 :(得分:0)

答案是你必须手动跟踪你的偏移和比例(即在用户平移后强制偏移在某些边界内)。

我这样做的方法是直接使用clip space坐标。所以对于1024x1024视图和1920x1080纹理,你的顶点是y [-1,1]和x [-1.77778,1.77778](然后比例[1.0,1.0,1.0]泛滥视图)。

完全从着色器中删除MVP。

然后介绍制服比例和偏移量。平移移动偏移,缩放会改变比例。

因此:

attribute mediump vec3 vertex;
attribute mediump vec2 texCoord;
varying mediump vec2 v_texCoord;
uniform mediump vec3 offset;
uniform mediump vec3 scale;
void main(){
 gl_Position=vec4((vertex-offset)*scale,1.0);
 v_texCoord=vec2(texCoord);
}

在Java中有一个健全性检查函数,可以确保偏移始终在顶点边界内,记住要考虑到比例。