最近公司在做自定义相机这一块,之前使用的是第三方,后来需求变更,第三方不支持添加动态贴纸,所以只能自己扩展。当然网上有很多例子,但是关于添加动态贴纸的例子几乎找不到,反正我是没找到(欲哭无泪)。当然,现在是所有功能都实现了。觉得openGl还是蛮有意思的,所以从头再梳理一遍,打算整理一个openGl的学习系列。供学习参考。如果对OpenGl没有了解的话,推荐先看Android openGl开发详解(一)——绘制简单图形
您能从本文了解到如下知识:1. SurfaceView,GlSurfaceView,SurfaceTexture,TextureView的优缺点及区别。2. 如何通过SurfaceView显示Camera预览。 3. 如何通过TextureView显示Camera预览。 4. 如何通过GlSurfaceView处理Camera预览。 5. 总结 6. 源码链接 7.关注打赏
1. SurfaceView,GlSurfaceView,SurfaceTexture,TextureView的优缺点及区别
SurfaceView
继承自View,拥有View的大部分属性,但是由于holder的存在,不能设置透明度。
优点:可以在一个独立的线程中进行绘制,不会影响主线程,使用双缓冲机制,播放视频时画面更流畅
缺点:surface的显示不受View属性的控制,不能将其放在ViewGroup中,SurfaceView不能嵌套使用。
GlSurfaceView
GlSurfaceView继承自SurfaceView类,专门用来显示OpenGL渲染的,简单理解可以显示视频,图像及3D场景这些的。
SurfaceTexture
和SurfaceView功能类似,区别是,SurfaceTexure可以不显示在界面中。使用OpenGl对图片流进行美化,添加水印,滤镜这些操作的时候我们都是通过SurfaceTexre去处理,处理完之后再通过GlSurfaceView显示。缺点,可能会导致个别帧的延迟。本身管理着BufferQueue,所以内存消耗会多一点。
TextureView
同样继承自View,必须在开启硬件加速的设备中使用(保守估计目前百分之九十的Android设备都开启了),TextureView通过setSurfaceTextureListener的回调在子线程中进行更新UI.
优点:支持动画效果。
缺点:在5.0之前在主线程渲染,在5.0之后在单独线程渲染。
TextureView | SurfaceView | |
---|---|---|
绘制 | 稍微延时 | 及时 |
内存 | 高 | 低 |
动画 | 支持 | 不支持 |
耗电 | 高 | 低 |
适用场景(推荐) | 视频播放,相机应用 | 大量画布更新(游戏绘制) |
2. 如何通过SurfaceView显示Camera预览。
基本步骤
- 在xml文件中设置SurfaceView 。
- 实现SurfaceHolder.Callback的回调。
- 打开摄像头Camera.open(0);
- 设置摄像头相关参数;
- 将摄像头数据设置到SurfaceView中,并开启预览。
代码部分
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" tools:context="com.aserbao.aserbaosandroid.opengl.openGlCamera.simpleCameraOpengl.simpleCamera.CameraSurfaceViewShowActivity">
<FrameLayout
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mSurface" />
<Button
android:id="@+id/btn_change"
android:text="给动画,SurfaceView不支持设置透明度"
android:textAllCaps="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
</android.support.constraint.ConstraintLayout>
/**
* 使用SurfaceView预览Camera数据
*/
public class CameraSurfaceViewShowActivity extends AppCompatActivity implements SurfaceHolder.Callback {
@BindView(R.id.mSurface)
SurfaceView mSurfaceView;
public SurfaceHolder mHolder;
private Camera mCamera;
private Camera.Parameters mParameters;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base_camera);
ButterKnife.bind(this);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
// Open the Camera in preview mode
mCamera = Camera.open(0);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
mParameters = mCamera.getParameters();
mParameters.setPictureFormat(PixelFormat.JPEG); //图片输出格式
// mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);//预览持续发光
mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//持续对焦模式
mCamera.setParameters(mParameters);
mCamera.startPreview();
mCamera.cancelAutoFocus();
}
}
});
}