android下自定义相机com.otaliastudios.cameraview源码解析(一)

mac2024-05-12  48

目录

android下自定义相机com.otaliastudios.cameraview源码解析(一)

android下自定义相机com.otaliastudios.cameraview源码解析(二)

前言    

最近在android下相机下的开发,引入了com.otaliastudios.cameraview,这个第三方类,顺便看了下它的源码,在这里记录一下,以便以后查询,在平时的开发,都是调用系统的相机,并没有自己去定义一个相机来使用,发现这里还是有不少问题的。这里是以2.4.0版本源码为基础进行分析的。

基础

支持相机和视频的控件,android目前提供了两个一个是TextureView,一个是SurfaceView,是用来展示相机的,视频也是使用这两个控件。

解析

一、主类

CameraView是这个类的主类,入口类,在这里进行了一切的操作。在它的构造函数都会执行一个【initialize】初始化方法,这里初始化了属性、插件(如网格线GridLinesLayout等)、Engine类(是使用camera1还是camera2)、自定义属性等

1.1 Engine

doInstantiateEngine()方法,是在初始化中调用,再通过调用instantiateCameraEngine方法,引入了Engine类,实现了使用camera1还是camera2的选择

1.2 生命周期

定义了生命周期OnLifecycleEvent,这里是androidx的内容,主要是定义了三个生命周期。这三个生命周期是可以对外的调用的,可以学习下的使用方法。

open(@OnLifecycleEvent(Lifecycle.Event.ON_RESUME))这里是打开,配合退到后台进行一系列的操作。

close(@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)),这里是暂停的生命周期

destroy(@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY))这个是销毁的生命周期。

在这里,cameraview类是一个统筹的类,所以的其它子控件都是围绕它使用的。

二 、触摸

2.1 Gesture和GestureAction

第一步,这里分为了两个方法,一个是定义手势,一个是定义触摸,定义了以下几个手势,用这个图我们可以看到,当你选择不同的手势时,效果是不同的。在这里是通过mapGesture方法进行的初始化,主要是把手势写入到mGestureMap,这个HashMap中,在mGestureMap,会存储Gesture和对应的GestureAction。在mapGesture,还行了一系列的Finder操作。这里学到的技巧就是我们可以在定义通过一些变量把一些复杂和行为进行拆分类分后,非常清晰。

Gesture(手势)GestureAction(手势行为)TAP(点击)

AUTO_FOCUS

TAKE_PICTURE

NONE

LONG_TAP

AUTO_FOCUS

TAKE_PICTURE

NONE

PINCH(缩放)

ZOOM

EXPOSURE_CORRECTION

FILTER_CONTROL_1

FILTER_CONTROL_2

NONE

SCROLL_HORIZONTAL(水平滚动)

ZOOM

EXPOSURE_CORRECTION

FILTER_CONTROL_1

FILTER_CONTROL_2

NONE

SCROLL_VERTICAL(垂直滚动)

ZOOM

EXPOSURE_CORRECTION

FILTER_CONTROL_1

FILTER_CONTROL_2

NONE

第二步是使用:

这里是在onTouch方法中进行调用的,会通过【mCameraEngine.getCameraOptions()】方法,获取相机的选项,然后根据不同的Finde来进行【onGesture】,这里就是通过mGestureMap,获取到gestureMap来进行不同的操作。

2.2 GestureType

在这里他又分为了是单次的,还是连续的。定义了两个字段GestureType

ONE_SHOT单次CONTINUOUS连续

然后又定义了Gesture和GestureAction,主要是定义了三种手势和用户可以要进行的行为。

2.3 GestureFinder

下面有三个PinchGestureFinder,ScrollGestureFinder,TapGestureFinder,这三类在CameraView中使用的,主要作用是从屏幕上获取手势进行解析。主要是【handleTouchEvent】这个方法,在这里进行处理的。

在GestureFinder构造函数中会定义系统的手势检测器GestureDetector,对用户的手势进行检测。

类名系统手势类系统手势方法PinchGestureFinderScaleGestureDetectoronScale(缩放)ScrollGestureFinderGestureDetectoronScroll(滚动)GestureDetectorGestureDetector

onSingleTapUp(单击)

onLongPress(长按)

三、渲染

主要分为两个包一个是filter,一个是filters,这两个包就是进行渲染的操作,filter主要是提供行为,而filters主要是提供各种类型的渲染方法。

3.1 Filter接口结构图

定义了接口filter,实现的类的BaseFilter,在这里filter只是定义了限制规则在camearView调用的就是setFilter(接口),接口的onDraw方法就是用来执行滤镜操作的。

onCreate(int programHandle)创建draw(long timestampUs, float[] transformMatrix)画的周期onDestroy getVertexShader getFragmentShader 

3.2 BaseFilter

在这里会去实现两个默认的Vertex和Fragment,进行调用,然后调用draw进行绘画。

在BaseFilter的子类中实现了OneParameterFilter和TwoParameterFilter两个方法

3.3 MultiFilter

是一个可以进行多个过滤的类,以ArrayList为基础进行存储

3.4 调用图

 在CameraView中去设置setFilter,这里会调用GlCameraPreview或者MockCameraPreview的setFilter方法,然后进入到EglViewport的setFilter方法,在EglViewport的drawFrame方法中,会有四个地方调用到

GlCameraPreview->Renderer继承于GLSurfaceView.Renderer(系统的)OverlayDrawer

SnapshotGlPictureRecorder(图片解码)

TextureMediaEncoder(视频解码)

SnapshotGlPictureRecorder(图片解码)TextureMediaEncoder(视频解码)

3.5 Filters包,提供渲染器‘

在这里的渲染器是基于opengl使用的,会在第五步中介绍。

AutoFixFilter自动修正渲染器BlackAndWhiteFilter黑白渲染器ContrastFilter对比渲染器CrossProcessFilter跨进程渲染器DocumentaryFilter写实DuotoneFilter双色调FillLightFilter GammaFilter GrainFilter GrayscaleFilter HueFilter InvertColorsFilter LomoishFilter PosterizeFilter SaturationFilter SepiaFilter SharpnessFilter清晰度TemperatureFilter TintFilter VignetteFilter 

四、internal

这个下面有egl包名,是用来渲染图片的

EglBaseSurface

五、EglViewport

所有的渲染操作都是在这里进行的,通过调用CameraView的setFilter方法,都会执行这个方法。

在这里需要介绍一下opengl在安卓下的调用流程,

       5.1 初始化

      在初始化的时候,需要一个Program,通过 GlUtils.createProgram(mFilter.getVertexShader(), mFilter.getFragmentShader());这里的VertexShader和FragmentShader是渲染器定义的。

5.2 绘画

GlUtils.checkError("draw start"); // Select the program and the active texture. GLES20.glUseProgram(mProgramHandle); GlUtils.checkError("glUseProgram"); GLES20.glActiveTexture(mTextureUnit); GLES20.glBindTexture(mTextureTarget, textureId); // Draw. mFilter.draw(timestampUs, textureMatrix); // 释放 GLES20.glBindTexture(mTextureTarget, 0); GLES20.glUseProgram(0);

具体的opengl学习可以参考这篇文章:https://blog.csdn.net/junzia/article/details/52801772

六、Marker

处理标记的

七、Overlay

可以在图片上绘画

最新回复(0)