Android 需要从TextureView中使用openGL将相机预览数据作为SurfaceTexture处理的帮助吗
搜索了整整3天,找到了很多相关信息,但没有一个是足够准确的,因为我缺乏计算机图形学知识。我决定在这里问一个问题 说清楚了, 1) 我有框架布局 2) 我添加了一个纹理视图 3) 我将FrameLayout的LayoutParams设置为一种square形状,因此TextureView也会根据该形状调整大小,成为一个正方形,这不是很容易混淆 4) 相机预览工作和TextureView显示工作之间的一切都很好,但是 4!)正如我们都知道的,就像在SurfaceView时代一样。如果我们强制将摄影机预览数据绘制到一个不太适合摄影机预览大小的视图中,则最终结果将被拉伸 4.)我的意思是,我知道如何调整FrameLayout/TextureView的大小,使其成为4:3/~16:9(Landscap或肖像),但我需要它是sqaure,真的,当然不是拉伸 5?)我想我应该通过openGL thins对SurfacetTexture数据进行预处理。(我认为这是很明显的,但如果你有一个完全不同的方法来实现这个结果,我不太确定。我们也将不胜感激 5) 关于预任务。我有很多这样做的例子,但只有一个普通的SurfaceView或GLSurfaceView。因为我不太熟悉原始的openGL编程。当我试图将代码变形到我的项目中时,我很痛苦 5+)不,我必须使用TextureView。如果你怀疑原因,那是因为谷歌将他们的相机样本转移到了使用TextureView,所以我认为我必须学习如何处理TextureView+openGL组合。不管怎么说,TextureView上台只是为了让bahave更简单,并且只提供一个视图,并与轻量级openGL处理协作,而不产生任何划痕,不是吗 6) 我真的无法将这些在线样本移植到我的。我甚至在用SurfaceTexture(omg)连接openGL上下文时也有困难 7) 是的,我有一个骨架式的代码结构,除了drawFrame impl之外,所有的东西都可以工作。我该往里面放什么 活动Android 需要从TextureView中使用openGL将相机预览数据作为SurfaceTexture处理的帮助吗,android,opengl-es,android-camera,textureview,Android,Opengl Es,Android Camera,Textureview,搜索了整整3天,找到了很多相关信息,但没有一个是足够准确的,因为我缺乏计算机图形学知识。我决定在这里问一个问题 说清楚了, 1) 我有框架布局 2) 我添加了一个纹理视图 3) 我将FrameLayout的LayoutParams设置为一种square形状,因此TextureView也会根据该形状调整大小,成为一个正方形,这不是很容易混淆 4) 相机预览工作和TextureView显示工作之间的一切都很好,但是 4!)正如我们都知道的,就像在SurfaceView时代一样。如果我们强制将摄影机预
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来实现这一点
顺便说一句,由于我国的网络状况,谷歌样本无法访问。我可以但没有做非常令人满意的预搜索工作,对此我深表歉意。请在GitHub查看我的tiny。我选择根本不扩展android.view.TextureView;您的里程可能不同
答案在重写后的TextureView.SurfaceTextRelistener.onSurfaceTextureAvailable()
回调中。查看变换矩阵。当您想要补偿不同的纵横比时,只需使用transform.setScale()
,直到您对结果满意为止。官方文件说
某些变换可能会阻止内容绘制所有像素
包含在此视图的边界内。在这种情况下,请确保此纹理视图未标记为不透明
我必须承认,我不完全理解他们在说什么,但实验表明,如果你愿意,选择正确的
矩阵可以实现相机预览的有效裁剪。你可以在Grafika中获得你想要的大部分代码。
只需参考此活动:,opengl代码已为您准备好
演示对您非常有用。首先,它将摄影机连接到OES SurfaceTexture,以便将摄影机帧(16:9或4:3)发送到此纹理。然后将纹理中的帧绘制到textureview或其他位置
你需要做的是切断纹理中每个帧的一些部分,使帧1:1。通过修改opengl的纹理坐标可以实现裁剪。看看这个问题,你会明白的。()Grafika()中的“相机纹理”活动可能与此相关。(这里的各种示例使用GLSURFACHEVIEW、SURFACHEVIEW和TextureView。)如果使用GLE进行渲染,则可以使用GL进行缩放/裁剪,而不是通过操纵TextureView;这更复杂,但给了您更多的灵活性。