美文网首页
二、MagicCamera3#Kotlin部分

二、MagicCamera3#Kotlin部分

作者: YongtaoHuang | 来源:发表于2019-11-09 15:29 被阅读0次

    两个部分

    代码分为app和pickphotoview两个部分
    app依赖于pickphotoview:

    dependencies {
        implementation project(':pickphotoview')
    }
    

    pickphotoview是一个用来选择图片的Android UI程序,可以忽略。
    app部分是核心。

    app部分结构

    app.png

    MainActivity→
    → CameraActivity // 普通摄像头功能的活动
    → CameraFilterActivity // 滤镜摄像头功能的活动
    → ImageEditActivity // 图片编辑,这里使用了pickphotoview

    CameraFilterActivity是主要需要阅读的部分:


    kotlin.png

    CameraFilterV2Activity中使用的3个类

    这个Activity涉及的3个主要类

    • FilterAdapter
    • CameraCompat
    • CameraFilterSurfaceCallbackV2(核心)
    FilterAdapter

    FilterAdapter是选择滤镜类型的RecyclView:

    // FilterAdapter继承了RecycleView.Adapter
    class FilterAdapter(private val context: Context, private val filters: IntArray) : RecyclerView.Adapter<FilterAdapter.FilterHolder>() {
        private var selected = 0
    
        interface onFilterChangeListener {
            fun onFilterChanged(filterType: Int)
        }
    
        var filterListener: onFilterChangeListener? = null
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FilterHolder {
            val view = LayoutInflater.from(context).inflate(R.layout.filter_item_layout,
                    parent, false)
            return FilterHolder(view)
        }
    
        override fun onBindViewHolder(holder: FilterHolder, position: Int) {
            holder.thumbImage.setImageResource(FilterTypeHelper.FilterType2Thumb(filters[position]))
            holder.filterName.setText(FilterTypeHelper.FilterType2Name(filters[position]))
            holder.filterName.setBackgroundColor(context.resources.getColor(
                    FilterTypeHelper.FilterType2Color(filters[position])))
            if (position == selected) {
                holder.thumbSelected.visibility = View.VISIBLE
                holder.thumbSelected_bg.setBackgroundColor(context.resources.getColor(
                        FilterTypeHelper.FilterType2Color(filters[position])))
                holder.thumbSelected_bg.alpha = 0.7f
            } else {
                holder.thumbSelected.visibility = View.GONE
            }
    
            holder.filterRoot.setOnClickListener { v ->
                if (selected != position) {
                    val lastSelected = selected
                    selected = position
                    notifyItemChanged(lastSelected)
                    notifyItemChanged(position)
                    filterListener?.onFilterChanged(filters[position])
                }
            }
        }
    
        override fun getItemCount(): Int {
            return filters.size
        }
    
        inner class FilterHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            var thumbImage: ImageView
            var filterName: TextView
            var thumbSelected: FrameLayout
            var filterRoot: FrameLayout
            var thumbSelected_bg: View
    
            init {
            // ......
            }
        }
    }
    
    
    CameraCompat

    这是一个Camera抽象类,包含预览功能:

    abstract class CameraCompat(protected var mContext: Context) {
    
        private var mSwitchFlag: Boolean = false
        protected var mSurfaceTexture: SurfaceTexture? = null   
        private var mSupportFlash = false // 是否支持闪光灯    
        protected var mCameraReady: Boolean = false // 相机是否初始化完成    
        protected var mStarted: Boolean = false // 是否开始预览
     
        @CameraType
        protected var mCameraType = BACK_CAMERA
    
        var outputSize: CameraSize? = null
    
        private val mCameraInfo = SparseArray<String>(2)
    
        protected val frontCameraIdV19: Int
            get() = Integer.valueOf(mCameraInfo.get(FRONT_CAMERA))
    
        protected val backCameraIdV19: Int
            get() = Integer.valueOf(mCameraInfo.get(BACK_CAMERA))
    
        protected val frontCameraIdV21: String
            get() = mCameraInfo.get(FRONT_CAMERA)
    
        protected val backCameraIdV21: String
            get() = mCameraInfo.get(BACK_CAMERA)
    
        @IntDef(FRONT_CAMERA, BACK_CAMERA)
        @Retention(RetentionPolicy.SOURCE)
        annotation class CameraType
    
        init {
            mSupportFlash = mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
            initCameraInfo()
        }
    
        fun setSurfaceTexture(texture: SurfaceTexture) {
            this.mSurfaceTexture = texture
        }
    
        protected fun setFrontCameraId(id: String) {
            mCameraInfo.put(FRONT_CAMERA, id)
        }
    
        protected fun setFrontCameraId(id: Int) {
            mCameraInfo.put(FRONT_CAMERA, id.toString())
        }
    
        protected fun setBackCameraId(id: Int) {
            mCameraInfo.put(BACK_CAMERA, id.toString())
        }
    
        protected fun setBackCameraId(id: String) {
            mCameraInfo.put(BACK_CAMERA, id)
        }
    
        protected abstract fun initCameraInfo()
    
        fun startPreview() {  }
    
        protected abstract fun onStartPreview()
    
        fun stopPreview(releaseSurface: Boolean) { }
    
        abstract fun onStopPreview()
    
        protected fun openCamera(@CameraType cameraType: Int) {
            mCameraType = cameraType
            onOpenCamera(cameraType)
        }
    
        protected abstract fun onOpenCamera(@CameraType cameraType: Int)
    
        fun turnLight(on: Boolean) { }
    
        protected abstract fun onTurnLight(on: Boolean)
    
        fun switchCamera() { }
    
        class CameraSize {
            var width: Int = 0
            var height: Int = 0
            // ...
        }
    
        companion object {
            const val DESIRED_HEIGHT = 720
            const val FRONT_CAMERA = 1
            const val BACK_CAMERA = 2
            fun newInstance(context: Context): CameraCompat {
                val api = Build.VERSION.SDK_INT
                return if (api >= 21) {
                    CameraCompatV21(context)
                } else {
                    CameraCompatV19(context)
                }
            }
        }
    
    }
    
    
    CameraFilterSurfaceCallbackV2

    CameraFilterSurfaceCallbackV2继承SurfaceHolder,用来实现相机滤镜的响应:

    // CameraFilterSurfaceCallbackV2继承SurfaceHolder
    class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback{
        // 覆写surfaceChanged方法
        override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
            changeOpenGL(width,height)
        }
        // 覆写surfaceDestroyed方法
        override fun surfaceDestroyed(holder: SurfaceHolder?) {
            releaseOpenGL()
        }
        // 覆写surfaceCreated方法
        override fun surfaceCreated(holder: SurfaceHolder?) {
            initOpenGL(it.surface)
        }
        // 初始化OpenGL
        fun initOpenGL(surface: Surface){
            // 相机滤镜创建是在C++底层实现的
            val textureId = OpenGLJniLib.magicFilterCreate(surface,BaseApplication.context.assets)
        }
        
        fun changeCamera(camera:CameraCompat? ){}
    
        fun changeOpenGL(width:Int,height:Int){}
    
        fun drawOpenGL(){}
    
        fun releaseOpenGL(){}
        // 设置滤镜类型
        fun setFilterType(type:Int){}
    
        fun doStartPreview(){}
    
        fun takePhoto(){}
        
    }
    

    渲染一个素描摄像头的流程

    运行CameraFilterV2Activity

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            initView() // 调用 initView()和initCamera()
        }
    

    调用 initView():

        fun initView(){
            filter_listView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false)
            mAdapter = FilterAdapter(this, types)
            mAdapter?.filterListener= object:FilterAdapter.onFilterChangeListener{
                override fun onFilterChanged(type: Int) {
                    mSurfaceCallback?.setFilterType(type) // 此处设置滤镜类型
                }
            }
            filter_listView.adapter= mAdapter
        }
    

    调用initCamera():

        private fun initCamera(){
            mCamera = CameraCompat.newInstance(this)
            // pay great attention,please!!! 
            mSurfaceCallback = CameraFilterSurfaceCallbackV2(mCamera)
            glsurfaceview_camera.holder.addCallback(mSurfaceCallback)
            mCamera?.startPreview()
        }
    

    CameraFilterSurfaceCallbackV2是核心类,它继承了SurfaceHolder#Callback

    class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback{
        override fun surfaceCreated(holder: SurfaceHolder?) {
            holder?.let {
                initOpenGL(it.surface)
            }
        }
    
        fun initOpenGL(surface: Surface){
            mExecutor.execute {
                // 这一行代码将这个SurfaceView和这个应用的assets(内部主要包含glsl语言)传递给C++底层操作了。
                val textureId = OpenGLJniLib.magicFilterCreate(surface,BaseApplication.context.assets)
    //            OpenGLJniLib.setFilterType(MagicFilterType.NONE.ordinal)
                if (textureId < 0){
                    Log.e(TAG, "surfaceCreated init OpenGL ES failed!")
                    return@execute
                }
                mSurfaceTexture = SurfaceTexture(textureId)
                mSurfaceTexture?.setOnFrameAvailableListener { drawOpenGL() }
                try {
                    mSurfaceTexture?.let {
                        mCamera?.setSurfaceTexture(it)
                    }
                    doStartPreview()
                }catch (e:IOException){
                    Log.e(TAG,e.localizedMessage)
                    releaseOpenGL()
                }
            }
        }
    }
    

    这一行代码将这个SurfaceView和这个应用的assets(内部主要包含glsl语言)传递给C++底层操作了。

    OpenGLJniLib.magicFilterCreate(surface,BaseApplication.context.assets)
    

    这里通过JNI调用了C++的代码

    //相机滤镜surfaceView初始化的时候创建
    JNIEXPORT jint JNICALL
    Java_com_cangwang_magic_util_OpenGLJniLib_magicFilterCreate(JNIEnv *env, jobject obj,
                                                            jobject surface,jobject assetManager) {
        std::unique_lock<std::mutex> lock(gMutex);
        if(glCameraFilter){ //停止摄像头采集并销毁
            glCameraFilter->stop();
            delete glCameraFilter;
        }
    
        //初始化native window
        ANativeWindow *window = ANativeWindow_fromSurface(env,surface);
        //初始化app内获取数据管理
        aAssetManager= AAssetManager_fromJava(env,assetManager);
        //初始化相机采集
        glCameraFilter = new CameraFilter(window,aAssetManager);
        //创建
        return glCameraFilter->create();
    }
    

    相关文章

      网友评论

          本文标题:二、MagicCamera3#Kotlin部分

          本文链接:https://www.haomeiwen.com/subject/orsgvctx.html