解决相机库CameraView多滤镜拍照错乱的BUG (一) : 复现BUG

1. 前言

这段时间,在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。

由于CameraView封装的比较到位,在项目前期,的确为我们节省了不少时间。

但随着项目持续深入,对于CameraView的使用进入深水区,逐渐出现满足不了我们需求的情况。
Github中的issues中,有些BUG作者一直没有修复。

那要怎么办呢 ? 项目迫切地需要实现相关功能,只能自己硬着头皮去看它的源码,去解决这些问题。

而这篇文章是其中关于CameraView在使用多滤镜MultiFilter的时候哦度会遇到拍照错乱的BUG。

以下源码解析基于CameraView 2.7.2

kotlin 复制代码
implementation("com.otaliastudios:cameraview:2.7.2")

为了在博客上更好的展示,本文贴出的代码进行了部分精简

2. 复现BUG

2.1 添加权限

在AndroidManifest.xml中添加权限

xml 复制代码
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

别忘了申请权限

kotlin 复制代码
ActivityCompat.requestPermissions(
    this,
    arrayOf(
        android.Manifest.permission.CAMERA,
        android.Manifest.permission.RECORD_AUDIO,
        android.Manifest.permission.WRITE_EXTERNAL_STORAGE
    ),
    1
)

2.2 在XML中添加布局

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    android:orientation="vertical"
    tools:context=".MyMainActivity">

    <com.otaliastudios.cameraview.CameraView
        android:id="@+id/camera_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cameraFacing="back"
        app:cameraEngine="camera2"
        app:cameraExperimental="true"
        app:cameraMode="picture" />

    <Button
        android:id="@+id/btn_take_picture"
        android:layout_gravity="right|bottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="拍照" />

</FrameLayout>

2.3 实现Activity

在Activity中添加如下代码

kotlin 复制代码
class CameraActivity : AppCompatActivity() {
    private lateinit var binding: ActivityTest2Binding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityTest2Binding.inflate(layoutInflater)
        setContentView(binding.root)

        //TODO 申请权限,这里略过,详见上文

        binding.btnTakePicture.setOnClickListener {
            //调用带滤镜拍照
            binding.cameraView.takePictureSnapshot()
        }

        binding.cameraView.addCameraListener(object : CameraListener() {
            override fun onPictureTaken(result: PictureResult) {
                super.onPictureTaken(result)
                //拍照回调
                val res = BitmapFactory.decodeByteArray(result.data, 0, result.data.size)
                res?.also {
                    val file = getNewImageFile()
                    ImageUtils.save(it, file, Bitmap.CompressFormat.JPEG)
                }
            }
        })
        //初始化CameraView
        binding.cameraView.setLifecycleOwner(this)
        val multiFilter = MultiFilter()
        val crossProcess = Filters.CROSS_PROCESS.newInstance()
        multiFilter.addFilter(crossProcess)
        //设置滤镜
        binding.cameraView.filter = multiFilter
    }
}

2.4 运行项目

接着运行项目,预览时正常的,点击拍照,可以发现,带滤镜拍出来的图片是正常的。

2.5 使用两个滤镜

然后我们改成使用两个滤镜

kotlin 复制代码
//初始化CameraView
binding.cameraView.setLifecycleOwner(this)
val multiFilter = MultiFilter()
val crossProcess = Filters.CROSS_PROCESS.newInstance()
multiFilter.addFilter(crossProcess)
val vignette = Filters.VIGNETTE.newInstance()
multiFilter.addFilter(vignette)
//设置滤镜
binding.cameraView.filter = multiFilter

默认情况下,CameraView会使用摄像头支持的最大像素进行拍照,我这个手机CameraView最终选用的摄像头分辨率是3072x4096,而我的手机屏幕分辨率是1080*2412(也就是CameraView的分辨率),预览时候是正常的,拍出来的照片居然放大了 ?

2.6 使用1080P

我们再将CameraView拍照的分辨率强制指定为1920*1080,而我的手机屏幕分辨率是1080*2412,预览也是正常的,这个时候拍出来的照片却是比实际尺寸缩小的。

3. BUG小结

至此,我们可以总结这个BUG,是跟CameraView的尺寸和摄像头选取的分辨率匹配有关。

  • 使用单个滤镜
    • 一切正常
  • 使用多个滤镜,预览正常,但是
    • 手机选用的摄像头分辨率比CameraView分辨率高 : 照片得到的画面会放大
    • 手机选用的摄像头分辨率比CameraView分辨率低 : 拍照得到的画面会缩小,会有黑边

那这到底是为什么呢 ? 又该怎么解决呢 ?

我们在下一篇文章中做详细分析 : 解决相机库CameraView多滤镜拍照错乱的BUG (二) : 解决BUG

4. 其他

4.1 CameraView源码解析系列

Android 相机库CameraView源码解析 (一) : 预览-CSDN博客
Android 相机库CameraView源码解析 (二) : 拍照-CSDN博客
Android 相机库CameraView源码解析 (三) : 滤镜相关类说明-CSDN博客
Android 相机库CameraView源码解析 (四) : 带滤镜预览-CSDN博客
Android 相机库CameraView源码解析 (五) : 带滤镜拍照-CSDN博客
Android 相机库CameraView源码解析 (六) : 保存滤镜效果-CSDN博客

相关推荐
hai_android4 小时前
Android 嵌套滑动冲突:内部拦截 vs 外部拦截实战
android·android studio·android jetpack
木子欢儿6 小时前
Zabbix 7.4 Alpine 版 Docker Compose 部署
android·运维·docker·容器·zabbix
素师良码7 小时前
第9篇:Android驱动踩坑实录:DSI RX FIFO前置脏0、数据错位复盘
android
夜雪一千7 小时前
如何在MySQL中实现字段级加密
android·数据库·mysql
夜雪一千7 小时前
MySQL 如何存储经纬度坐标:选型、建表、空间查询实战
android·mysql·adb
JMchen7 小时前
集成第三方 C/C++ 库到 Android NDK 项目:OpenCV 与 FFmpeg 实战指南
android·opencv·cmake
有毒的教程9 小时前
Dev-C++ 使用扩展库两种方式:DevPak一键安装 / 手动配置(重点)
android·c++·adb
mmsx9 小时前
Android 测绘数值基础:测量单位系统与七四参数、高程拟合
android
郑州光合科技余经理9 小时前
出海外卖平台:支付对接为什么要和下单收款分开
android·java·开发语言·前端·后端·php·ai编程
夜雪一千9 小时前
MySQL 如何提高查询速度:从索引、SQL、表结构到实战调优
android·sql·mysql