kotlin 二维码实现高斯模糊

Kotlin 复制代码
  /**
     * 核心方法:应用模糊效果
     * 兼容 Android 4.4 (API 19) 及以上版本
     */
    private fun applyBlurEffect() {
        // 获取当前 ImageView 里的 Bitmap
        val drawable = viewBinding.qrCodeImage.drawable ?: return
        val bitmap = when (drawable) {
            is android.graphics.drawable.BitmapDrawable -> drawable.bitmap
            else -> {
                // 将其他类型的 Drawable 转换为 Bitmap
                val width = drawable.intrinsicWidth.coerceAtLeast(1)
                val height = drawable.intrinsicHeight.coerceAtLeast(1)
                val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
                val canvas = Canvas(bmp)
                drawable.setBounds(0, 0, canvas.width, canvas.height)
                drawable.draw(canvas)
                bmp
            }
        } ?: return

        // 应用模糊效果
        val blurredBitmap = blurBitmap(bitmap, 15f)

        // 设置模糊后的 Bitmap
        viewBinding.qrCodeImage.setImageBitmap(blurredBitmap)
    }

    /**
     * 对 Bitmap 应用高斯模糊
     * 使用 RenderScript 实现,兼容 API 17+ (Android 4.2+)
     * 对于更低版本,使用简单的缩放模糊作为降级方案
     */
    private fun blurBitmap(bitmap: Bitmap, radius: Float): Bitmap {
        // 创建输出 Bitmap
        val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            // 使用 RenderScript (API 17+)
            try {
                val rs = RenderScript.create(this)
                val input = Allocation.createFromBitmap(rs, bitmap)
                val outputAlloc = Allocation.createFromBitmap(rs, output)

                val script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
                // RenderScript 要求 radius 在 0-25 之间
                val clampedRadius = radius.coerceIn(0f, 25f)
                script.setRadius(clampedRadius)
                script.setInput(input)
                script.forEach(outputAlloc)

                outputAlloc.copyTo(output)
                rs.destroy()
            } catch (e: Exception) {
                // RenderScript 失败时降级到缩放模糊
                applyScaleBlur(bitmap, output)
            }
        } else {
            // API 17 以下使用缩放模糊
            applyScaleBlur(bitmap, output)
        }

        return output
    }

    /**
     * 缩放模糊作为降级方案
     * 先缩小再放大,产生模糊效果
     */
    private fun applyScaleBlur(source: Bitmap, output: Bitmap) {
        val scale = 0.1f // 缩小到 10%
        val smallWidth = (source.width * scale).toInt().coerceAtLeast(1)
        val smallHeight = (source.height * scale).toInt().coerceAtLeast(1)

        // 先缩小
        val small = Bitmap.createScaledBitmap(source, smallWidth, smallHeight, false)

        // 再放大回原尺寸
        val canvas = Canvas(output)
        val scaled = Bitmap.createScaledBitmap(small, source.width, source.height, false)
        canvas.drawBitmap(scaled, 0f, 0f, null)

        // 回收临时 Bitmap
        if (small !== source) small.recycle()
        if (scaled !== small) scaled.recycle()
    }

精简的写法:

Kotlin 复制代码
  /**
     * 对当前 ImageView 中的二维码做模糊处理。
     * 通过多次缩小→放大的方式模拟高斯模糊,兼容所有 Android 版本(含 4.2/4.4 TV),
     * 不依赖 RenderScript 或第三方库。
     */
    private fun applyBlurEffect() {
        val drawable = viewBinding.qrCodeImage.drawable as? BitmapDrawable ?: return
        val src = drawable.bitmap
        val blurred = blurBitmap(src, 2)
        viewBinding.qrCodeImage.setImageBitmap(blurred)
    }

    /**
     * 快速模糊:每次迭代宽高缩小到 1/8 再放大回原尺寸。
     * 缩小倍数越大越模糊,2 次迭代足以让二维码无法识别/扫描。
     */
    private fun blurBitmap(src: Bitmap, passes: Int): Bitmap {
        var bitmap = src
        for (i in 0 until passes) {
            val w = (bitmap.width / 8).coerceAtLeast(1)
            val h = (bitmap.height / 8).coerceAtLeast(1)
            val small = Bitmap.createScaledBitmap(bitmap, w, h, true)
            val scaled = Bitmap.createScaledBitmap(small, bitmap.width, bitmap.height, true)
            small.recycle()
            if (bitmap !== src) {
                bitmap.recycle()
            }
            bitmap = scaled
        }
        return bitmap
    }
相关推荐
事圆则缓14 小时前
Kotlin 入门与面试:从空安全、扩展函数到协程
安全·面试·kotlin
传奇开心果编程15 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓17 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer
supabc12318 小时前
Celium:连接 Windows、Mac、Linux 与 Android,让远程访问和设备管理更简单
android·linux·windows·macos·远程访问·网络管理·celium
Dovis(誓平步青云)18 小时前
导览音频切换太快,旧讲解不能覆盖新展品
android·前端·javascript·ecmascript·音视频·宠物
熊猫钓鱼>_>1 天前
Kotlin Multiplatform for OpenHarmony 实战:为 Reaktive 实现响应式原语适配(完整版 · 含摘要目录与技术图表)
华为·kotlin·大模型·ai编程·harmonyos·适配·reaktive