博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
谈谈Android中的SurfaceTexture
阅读量:6281 次
发布时间:2019-06-22

本文共 6422 字,大约阅读时间需要 21 分钟。

2015.7.2更新

由于很多人要代码,我把代码下载链接放在了。不过还是要说一下,surfaceTexture和OpenGL ES结合才能发挥出它最大的效果,我这种写法只是我自己的想法,还有很多种解决方法,如果大家学习一下OpenGL ES,会发现更多有意思的东西。

SurfaceTexture是从Android3.0(API 11)加入的一个新类。这个类跟SurfaceView很像,可以从camera preview或者video decode里面获取图像流(image stream)。但是,和SurfaceView不同的是,SurfaceTexture在接收图像流之后,不需要显示出来。有做过Android camera开发的人都知道,比较头疼的一个问题就是,从camera读取到的预览(preview)图像流一定要输出到一个可见的(Visible)SurfaceView上,然后通过Camera.PreviewCallback的public void onPreviewFrame(byte[] data, Camera camera)函数来获得图像帧数据的拷贝。这就存在一个问题,比如我希望隐藏摄像头的预览图像或者对每一帧进行一些处理再显示到手机显示屏上,那么在Android3.0之前是没有办法做到的,或者说你需要用一些小技巧,比如用其他控件把SurfaceView给挡住,注意这个显示原始camera图像流的SurfaceView其实是依然存在的,也就是说被挡住的SurfaceView依然在接收从camera传过来的图像,而且一直按照一定帧率去刷新,这是消耗cpu的,而且如果一些参数设置的不恰当,后面隐藏的SurfaceView有可能会露出来,因此这些小技巧并不是好办法。但是,有了SurfaceTexture之后,就好办多了,因为SurfaceTexture不需要显示到屏幕上,因此我们可以用SurfaceTexture接收来自camera的图像流,然后从SurfaceTexture中取得图像帧的拷贝进行处理,处理完毕后再送给另一个SurfaceView用于显示即可。

在我的应用场景中,我需要从camera读取图像流,然后对其处理,最后将处理结果显示到手机屏幕上。因此我写了一个GameDisplay类用于处理以上所有事务,而在MainActivity中,只需要创建一个GameDisplay类的实例并且初始化即可。

1 package com.song.camgame;  2   3 import java.io.IOException;  4 import java.util.List;  5 import java.util.Timer;  6 import java.util.TimerTask;  7   8 import android.app.Activity;  9 import android.content.Context; 10 import android.graphics.Bitmap; 11 import android.graphics.Canvas; 12 import android.graphics.ImageFormat; 13 import android.graphics.Rect; 14 import android.graphics.SurfaceTexture; 15 import android.hardware.Camera; 16 import android.hardware.Camera.Size; 17 import android.util.Log; 18 import android.view.SurfaceHolder; 19 import android.view.SurfaceView; 20  21 public class GameDisplay extends SurfaceView implements SurfaceHolder.Callback, 22 Camera.PreviewCallback{ 23     public final static String TAG="GameDisplay"; 24      25     private static final int MAGIC_TEXTURE_ID = 10; 26     public static final int DEFAULT_WIDTH=800; 27     public static final int DEFAULT_HEIGHT=480; 28     public static final int BLUR = 0; 29     public static final int CLEAR = BLUR + 1; 30     //public static final int PAUSE = PLAY + 1; 31     //public static final int EXIT = PAUSE + 1; 32     public SurfaceHolder gHolder; 33     public  SurfaceTexture gSurfaceTexture; 34     public Camera gCamera; 35     public byte gBuffer[]; 36     public int textureBuffer[]; 37     public ProcessThread gProcessThread; 38     private int bufferSize; 39     private Camera.Parameters parameters; 40     public int previewWidth, previewHeight; 41     public int screenWidth, screenHeight; 42     public Bitmap gBitmap; 43     private Rect gRect; 44     // timer 45     private Timer sampleTimer; 46     private TimerTask sampleTask; 47      48     public GameDisplay(Context context,int screenWidth,int screenHeight) { 49         super(context); 50         gHolder=this.getHolder(); 51         gHolder.addCallback(this); 52         gHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 53         gSurfaceTexture=new SurfaceTexture(MAGIC_TEXTURE_ID); 54         this.screenWidth=screenWidth; 55         this.screenHeight=screenHeight; 56         gRect=new Rect(0,0,screenWidth,screenHeight); 57         Log.v(TAG, "GameDisplay initialization completed"); 58     } 59  60     @Override 61     public void surfaceChanged(SurfaceHolder holder, int format, int width, 62             int height) { 63         Log.v(TAG, "GameDisplay surfaceChanged"); 64         parameters = gCamera.getParameters();     65         List
preSize = parameters.getSupportedPreviewSizes(); 66 previewWidth = preSize.get(0).width; 67 previewHeight = preSize.get(0).height; 68 for (int i = 1; i < preSize.size(); i++) { 69 double similarity = Math 70 .abs(((double) preSize.get(i).height / screenHeight) 71 - ((double) preSize.get(i).width / screenWidth)); 72 if (similarity < Math.abs(((double) previewHeight / screenHeight) 73 - ((double) previewWidth / screenWidth))) { 74 previewWidth = preSize.get(i).width; 75 previewHeight = preSize.get(i).height; 76 } 77 } 78 gBitmap= Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888); 79 parameters.setPreviewSize(previewWidth, previewHeight); 80 gCamera.setParameters(parameters); 81 bufferSize = previewWidth * previewHeight; 82 textureBuffer=new int[bufferSize]; 83 bufferSize = bufferSize * ImageFormat.getBitsPerPixel(parameters.getPreviewFormat()) / 8; 84 gBuffer = new byte[bufferSize]; 85 gCamera.addCallbackBuffer(gBuffer); 86 gCamera.setPreviewCallbackWithBuffer(this); 87 gCamera.startPreview(); 88 //gProcessThread = new ProcessThread(surfaceView,handler,null,previewWidth,previewHeight); 89 //processThread.start(); 90 } 91 92 @Override 93 public void surfaceCreated(SurfaceHolder holder) { 94 Log.v(TAG, "GameDisplay surfaceCreated"); 95 if (gCamera == null) { 96 gCamera = Camera.open(); 97 } 98 gCamera.setPreviewTexture(gSurfaceTexture); 99 //sampleStart();100 }101 102 @Override103 public void surfaceDestroyed(SurfaceHolder holder) {104 Log.v(TAG, "GameDisplay surfaceDestroyed");105 //gProcessThread.isRunning=false;106 //sampleTimer.cancel();107 //sampleTimer = null;108 //sampleTask.cancel();109 //sampleTask = null;110 gCamera.stopPreview();111 gCamera.release();112 }113 114 @Override115 public void onPreviewFrame(byte[] data, Camera camera) {116 Log.v(TAG, "GameDisplay onPreviewFrame");117 //gProcessThread.raw_data=data; 118 camera.addCallbackBuffer(gBuffer);119 for(int i=0;i

以上程序中115-130行是最重要的部分,data是从SurfaceTexture获得的camera图像帧的拷贝,119-121行对其进行了简单的处理,122-128行将处理过的图像数据传递给负责显示的SurfaceView并显示出来。

MainActivity对GameDisplay的调用如下:

1 //声明 2 private GameDisplay gameDisplay; 3 //初始化 4 gameDisplay.setVisibility(SurfaceView.VISIBLE); 5 DisplayMetrics dm = getResources().getDisplayMetrics(); 6 screenWidth = dm.widthPixels; 7 screenHeight = dm.heightPixels; 8 gameDisplay= new GameDisplay(this,dm.widthPixels,dm.heightPixels); 9 //加入到当前activity的layout中10 FrameLayout root = (FrameLayout) findViewById(R.id.root);11 root.addView(gameDisplay,0);

 

 

转载地址:http://cuiva.baihongyu.com/

你可能感兴趣的文章
基于 HTML5 Canvas 实现的文字动画特效
查看>>
PHP开发环境之WVL-NMP环境搭建
查看>>
javasimon
查看>>
Java集合(六)List概括,总结
查看>>
python2.7 链接MySQL 在Eclipse PyDev下 windows平台
查看>>
jquery如何判断checkbox(复选框)是否被选中
查看>>
js笔记精华版
查看>>
PLSQL基本结构
查看>>
关于typedef的用法总结
查看>>
Apache用户认证、域名跳转、访问日志格式
查看>>
mwArray类说明
查看>>
CMD命令行:查看 Windows 操作系统的安装时间
查看>>
mysql explain
查看>>
golang交叉编译工具,gox使用入门
查看>>
Redis Master-Slave 读写分离测试
查看>>
git bash常用命令行以及初次接触yo以及bower
查看>>
修改MySQL默认空密码
查看>>
spring mvc访问静态文件(css/js/img)访问不到
查看>>
spring boot框架学习学前掌握之重要注解(1)-sprng的java配置方式
查看>>
plsql 书籍基础表结构
查看>>