解决相机库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博客

相关推荐
黄林晴16 小时前
如何判断手机是否是纯血鸿蒙系统
android
火柴就是我16 小时前
flutter 之真手势冲突处理
android·flutter
法的空间16 小时前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
循环不息优化不止16 小时前
深入解析安卓 Handle 机制
android
恋猫de小郭17 小时前
Android 将强制应用使用主题图标,你怎么看?
android·前端·flutter
jctech17 小时前
这才是2025年的插件化!ComboLite 2.0:为Compose开发者带来极致“爽”感
android·开源
用户20187928316717 小时前
为何Handler的postDelayed不适合精准定时任务?
android
叽哥17 小时前
Kotlin学习第 8 课:Kotlin 进阶特性:简化代码与提升效率
android·java·kotlin
Cui晨17 小时前
Android RecyclerView展示List<View> Adapter的数据源使用View
android
氦客17 小时前
Android Doze低电耗休眠模式 与 WorkManager
android·suspend·休眠模式·workmanager·doze·低功耗模式·state_doze