1

搜索了整整 3 天,找到了很多相关信息,但由于我缺乏计算机图形知识,没有一个足够准确。我只是想在这里问一个问题。

为了清楚起见,

1)我有框架布局

2)我添加了一个 TextureView 到它

3)我将 LayoutParams 到 FrameLayout 设置为一种方形,因此不知何故 TextureView 也根据该形状调整大小,变成方形,这不是很混乱

4)Camera Previewing 工作和 TextureView 显示工作之间的一切工作正常但

4!)众所周知,就像在 SurfaceView 时代一样。如果我们强制将相机预览数据绘制到一个不太适合相机预览尺寸的视图中,最终结果就会被拉伸。

4.)我的意思是我知道如何调整 FrameLayout/TextureView 的大小以使其成为 4:3/~16:9(风景或肖像),但我需要它是方形的,真的,当然不要拉伸

5?)我认为我应该通过openGL Thins预处理SurfaceTexture数据。(我认为这很明显,但我不太确定,所以如果你有完全不同的方式来获得结果。它也将不胜感激。

5)关于preAsking工作。我有很多这样做的样本,但只有一个普通的 SurfaceView 或 GLSurfaceView。因为我对原始的openGL编程不太熟悉。当我尝试将代码变形到我的项目中时,我感到很痛苦

5+) 不,我必须使用 TextureView。如果您怀疑原因是因为谷歌将他们的相机样本转移到使用 TextureView 中,所以我认为我必须学习处理 TextureView+openGL 组合。无论如何,TextureView 上台只是为了让它更简单,就像只生活一个 View 并与轻量级 openGL 处理配合而没有划痕不是吗

6)我真的无法将那些在线样本移植到我的。即使在使用 SurfaceTexture (omg) 附加 openGL 上下文时我也遇到了麻烦

7) 是的,我有一个类似骨架的代码结构,除了 drawFrame impl 之外,一切都可以正常工作。我到底应该在里面放什么

活动

public class MainActivity extends ActionBarActivity {

private ImageView imageView;
private TextView textView;

private Camera mCamera;
private MirrorScope mScope;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    imageView = (ImageView) findViewById(R.id.qrCode);
    textView = (TextView) findViewById(R.id.title);

    // Create an instance of Camera
    mCamera = getCameraInstance();

    // Create our Preview view and set it as the content of our activity.
    mScope = new MirrorScope(this, mCamera);
    mScope.setSurfaceTextureListener(mScope);
    FrameLayout scopeDrawer = (FrameLayout) findViewById(R.id.camera_preview);
    scopeDrawer.setLayoutParams(new LinearLayout.LayoutParams(700,700));

    scopeDrawer.addView(mScope);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}


/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}

/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}

}

纹理视图

    public class MirrorScope extends TextureView  implements TextureView.SurfaceTextureListener {

    private Camera mCamera;  
    private Context mContext;
    private TextureView mTextureView;  
    private ScopeGLThread renderer;

    public MirrorScope(Context context , Camera camera) {  
        super(context);  
        mCamera = camera;  
        // TODO Auto-generated constructor stub  
    }  
    @Override  
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,  
            int height) {  
//        mCamera = Camera.open();  
        try {  
            mCamera.setPreviewTexture(surface);  
            mCamera.startPreview();  
        } catch (IOException ioe) {  
            // Something bad happened  
        }  
        renderer = new ScopeGLThread(surface);
        renderer.start();
    }  

    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,  
            int height) {  
        // Ignored, Camera does all the work for us  
    }  

    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {  
        renderer = null;  
        mCamera.stopPreview();  
        mCamera.release();  
        return true;  
    }  

    public void onSurfaceTextureUpdated(SurfaceTexture surface) {  
        // Invoked every time there's a new Camera preview frame 
        //renderer.notify();

    }  

}  

openGL 线程

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;

import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.util.Log;

public class ScopeGLThread extends Thread {

    SurfaceTexture mSurface;
    EGL10 mEgl;
    EGLDisplay mEglDisplay;
    EGLConfig mEglConfig;
    EGLContext mEglContext;
    EGLSurface mEglSurface;

    public ScopeGLThread(SurfaceTexture surface) {
        mSurface = surface;
    }

    @Override
    public void run() {
        initGL();

        while(true) {
            drawFrame();
            Log.v("omg","oooomg"); //this do print thus I think the main loop is kidda work-ful
            //wait(); //however this hurts even with try/catch bloack it kills my app
        }
    }

    private void initGL() {
        mEgl = (EGL10)EGLContext.getEGL();
        mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

        int versions[] = new int[2];
        mEgl.eglInitialize(mEglDisplay, versions);

        int configsCount[] = new int[1];
        EGLConfig configs[] = new EGLConfig[1];
        int configSpec[] = new int[]{
            EGL10.EGL_RENDERABLE_TYPE, 
            EGL14.EGL_OPENGL_ES2_BIT,
            EGL10.EGL_RED_SIZE, 8,
            EGL10.EGL_GREEN_SIZE, 8,
            EGL10.EGL_BLUE_SIZE, 8,
            EGL10.EGL_ALPHA_SIZE, 8,
            EGL10.EGL_DEPTH_SIZE, 0,
            EGL10.EGL_STENCIL_SIZE, 0,
            EGL10.EGL_NONE };
        mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount);
        mEglConfig = configs[0];

        int contextSpec[] = new int[]{
                EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL10.EGL_NONE };
        mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, contextSpec);

        mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null);

        mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
    }

    private void drawFrame() {
        //mSurface.attachToGLContext(1);
        //mSurface.detachFromGLContext();
        //mEgl..glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        //mSurface.updateTexImage();
    // everything I put here kills everything ( and some deleted other kind of trying)
    }


}

我应该如何获得 gl 实例?当某些示例使用 gl (从无处...或参数),其他示例使用 EGL14.blahblah 事物时,我发现它感到困惑。我的意思是......天哪,我真的不知道 openGL,Android.com 上的 khronos 包参考是无效的......)

确实需要逐步解决确切问题的教程,但是如果您以文本形式清楚地解释它,那也很棒。当我需要正方形时,我认为我们可以通过裁剪相机预览数据的左上角来使其变得最简单。那将非常有帮助。是的,我可能需要添加某种过滤功能,所以不要破解平方问题。我坚持通过openGL来做这件事,相当。

顺便说一句,由于我所在国家/地区的网络状况,无法访问 Google 示例。我可以但不是很令人满意的预先搜索工作,我为此道歉。

4

2 回答 2

0

请在 GitHub 上查看我的小示例。我选择完全不延长 android.view.TextureView;您的里程可能会有所不同。

答案在TextureView.SurfaceTextureListener.onSurfaceTextureAvailable()我们覆盖的回调中。看看变换 Matrix。当您想补偿不同的纵横比时,您只需玩弄transform.setScale()直到您对结果感到满意。官方文档说,

某些转换可能会阻止内容绘制此视图边界内包含的所有像素。在这种情况下,请确保此纹理视图未标记为不透明。

我必须承认,我并不完全理解他们在说什么,但实验表明Matrix,如果你愿意,选择正确的购买可以实现相机预览的有效裁剪。

于 2014-09-17T09:02:56.640 回答
0

您可以在 Grafika 中获得所需的大部分代码。只需参考这个活动:https ://github.com/google/grafika/blob/master/src/com/android/grafika/ContinuousCaptureActivity.java,opengl代码都准备好了。

该演示对您非常有用。首先它将相机连接到 OES SurfaceTexture,因此相机帧(16:9 或 4:3)被发送到这个纹理。然后将纹理中的框架绘制到textureview或某处。

您需要做的是切断纹理中每一帧的某些部分,以使帧为 1:1。可以通过修改opengl的纹理坐标来实现切割。看看这个问题,你会明白的。(在使用 MediaCodec 为 Grafika 的“连续捕获”活动进行编码之前裁剪视频

于 2017-03-03T12:18:01.803 回答