千家信息网

Android CameraX如何结合LibYUV和GPUImage自定义相机滤镜

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要介绍了Android CameraX如何结合LibYUV和GPUImage自定义相机滤镜,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一
千家信息网最后更新 2026年10月31日Android CameraX如何结合LibYUV和GPUImage自定义相机滤镜

这篇文章主要介绍了Android CameraX如何结合LibYUV和GPUImage自定义相机滤镜,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

本文目录:

实现效果

实现步骤

1.引入依赖库

这里我引入的依赖库有CameraX、GPUImage(滤镜库)、Utilcodex(一款好用的工具类)

// CameraX core library using camera2 implementation    implementation "androidx.camera:camera-camera2:1.0.1"// CameraX Lifecycle Library    implementation "androidx.camera:camera-lifecycle:1.0.1"// CameraX View class    implementation "androidx.camera:camera-view:1.0.0-alpha27"    implementation'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'    implementation 'com.blankj:utilcodex:1.30.6'

2.引入libyuv

这里我用的是这个案例(https://github.com/theeasiestway/android-yuv-utils)里面的libyuv,如下

3.编写CameraX预览代码

布局代码如下

    

Activity中开启相机预览代码如下,基本都是Google官方提供的案例代码

class MainActivity : AppCompatActivity() {    private lateinit var cameraExecutor: ExecutorService    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        cameraExecutor = Executors.newSingleThreadExecutor()        // Request camera permissions        if (allPermissionsGranted()) {            startCamera()        } else {            ActivityCompat.requestPermissions(                this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)        }    }    private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {        ContextCompat.checkSelfPermission(            baseContext, it) == PackageManager.PERMISSION_GRANTED    }    override fun onRequestPermissionsResult(        requestCode: Int, permissions: Array, grantResults:        IntArray) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults)        if (requestCode == REQUEST_CODE_PERMISSIONS) {            if (allPermissionsGranted()) {                startCamera()            } else {                Toast.makeText(this,                    "Permissions not granted by the user.",                    Toast.LENGTH_SHORT).show()                finish()            }        }    }    private fun startCamera() {        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)        cameraProviderFuture.addListener(Runnable {            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()            val preview = Preview.Builder()                .build()                .also {                    it.setSurfaceProvider(viewFinder.surfaceProvider)                }            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA            try {                cameraProvider.unbindAll()                cameraProvider.bindToLifecycle(                    this, cameraSelector, preview)            } catch(exc: Exception) {                Log.e(TAG, "Use case binding failed", exc)            }        }, ContextCompat.getMainExecutor(this))    }    override fun onDestroy() {        super.onDestroy()        cameraExecutor.shutdown()    }    companion object {        private const val TAG = "CameraXBasic"        private const val REQUEST_CODE_PERMISSIONS = 10        privateval REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)    }}

到这里就可以实现相机预览了

4.增加相机数据回调

我们要增加滤镜效果就必须对相机的数据进行操作,这里我们通过获取相机数据回调来获取可修改的数据

val imageAnalyzer = ImageAnalysis.Builder()                //设置回调数据的比例为16:9                .setTargetAspectRatio(AspectRatio.RATIO_16_9)                .build()                .also {                    it.setAnalyzer(cameraExecutor,this@MainActivity)                }

这里我们还需要进行绑定

除此之外我们还需要在Activity中实现ImageAnalysis.Analyzer接口,数据的获取就在此接口的回调方法中获取,如下所示,其中ImageProxy就包含了图像数据

override fun analyze(image: ImageProxy) {}

5.对回调数据进行处理

我们在相机数据回调的方法中对图像进行处理并添加滤镜,当然在此之前我们还需要创建GPUImage对象并设置滤镜类型

private var bitmap:Bitmap? = nullprivate var gpuImage:GPUImage? = null//创建GPUImage对象并设置滤镜类型,这里我使用的是素描滤镜private fun initFilter() {        gpuImage = GPUImage(this)        gpuImage!!.setFilter(GPUImageSketchFilter())    }@SuppressLint("UnsafeOptInUsageError")    override fun analyze(image: ImageProxy) {        //将Android的YUV数据转为libYuv的数据        var yuvFrame = yuvUtils.convertToI420(image.image!!)        //对图像进行旋转(由于回调的相机数据是横着的因此需要旋转90度)        yuvFrame = yuvUtils.rotate(yuvFrame, 90)        //根据图像大小创建Bitmap        bitmap = Bitmap.createBitmap(yuvFrame.width, yuvFrame.height, Bitmap.Config.ARGB_8888)        //将图像转为Argb格式的并填充到Bitmap上        yuvUtils.yuv420ToArgb(yuvFrame,bitmap!!)        //利用GpuImage给图像添加滤镜        bitmap = gpuImage!!.getBitmapWithFilterApplied(bitmap)        //由于这不是UI线程因此需要在UI线程更新UI        img.post {            img.setImageBitmap(bitmap)            //关闭ImageProxy,才会回调下一次的数据            image.close()        }    }

6.拍摄照片

这里我们加一个拍照的按钮

            

然后我们在Activity中添加拍照的逻辑,其实就是将Bitmap转为图片保存到SD卡,这里我们使用了之前引入的Utilcodex工具,当我们点击按钮的时候isTakePhoto会变为true,然后在相机的回调中就会进行保存图片的处理

bt_takepicture.setOnClickListener {            isTakePhoto = true        }

并且我们加入变量控制,在拍照的时候不处理回调数据

@SuppressLint("UnsafeOptInUsageError")    override fun analyze(image: ImageProxy) {        if(!isTakePhoto){            //将Android的YUV数据转为libYuv的数据            var yuvFrame = yuvUtils.convertToI420(image.image!!)            //对图像进行旋转(由于回调的相机数据是横着的因此需要旋转90度)            yuvFrame = yuvUtils.rotate(yuvFrame, 90)            //根据图像大小创建Bitmap            bitmap = Bitmap.createBitmap(yuvFrame.width, yuvFrame.height, Bitmap.Config.ARGB_8888)            //将图像转为Argb格式的并填充到Bitmap上            yuvUtils.yuv420ToArgb(yuvFrame,bitmap!!)            //利用GpuImage给图像添加滤镜            bitmap = gpuImage!!.getBitmapWithFilterApplied(bitmap)            //由于这不是UI线程因此需要在UI线程更新UI            img.post {                img.setImageBitmap(bitmap)                if(isTakePhoto){                    takePhoto()                }                //关闭ImageProxy,才会回调下一次的数据                image.close()            }        }else{            image.close()        }    } /**     * 拍照     */    private fun takePhoto() {        Thread{            val filePath = File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"${System.currentTimeMillis()}save.jpg")            ImageUtils.save(bitmap,filePath.absolutePath,Bitmap.CompressFormat.PNG)            ToastUtils.showShort("拍摄成功")            isTakePhoto = false        }.start()    }

效果如下

保存的图片在如下目录

保存的图片如下

感谢你能够认真阅读完这篇文章,希望小编分享的"Android CameraX如何结合LibYUV和GPUImage自定义相机滤镜"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

数据 相机 滤镜 图像 代码 图片 篇文章 线程 处理 效果 这不 大小 对象 工具 按钮 接口 方法 时候 格式 案例 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技名片 亿人帮互联网科技有限公司 互联网科技工作委员会主任 西安纸贵互联网科技有限公司 河南真二互联网科技有限公司 小马过河互联网科技 北京禾田雨橡互联网科技 广州凡科互联网科技 互联网和高科技公司 互联网科技公司需要的职位 阿里巴巴算科技企业还是互联网 创业天下互联网科技有限公司 成都互联网科技公司100强 厦门千工互联网科技有限公司 35岁以上互联网科技行业 普陀区互联网教育科技管理办法 互联网高科技行业有哪些企业 中国新注册互联网科技 互联网科技新闻 科技美学互联网 艺术 广州百单互联网科技有限公司 国智互联网科技 美国互联网保险保险科技 互联网最新的科技有限公司 北京互联网科技有限公司 互联网科技logo设计 小米互联网科技园设置 互联网经济与金融科技 移动互联网年度科技创新 扫呗互联网科技有限公司
0