当前位置: 首页 > news >正文

Android Bitmap 模糊效果实现 (二)

文章目录

  • Android Bitmap 模糊效果实现 (二)
      • 使用 Vukan 模糊
      • 使用 RenderEffect 模糊
      • 使用 GLSL 模糊
      • RS、Vukan、RenderEffect、GLSL 效率对比

Android Bitmap 模糊效果实现 (二)

本文首发地址 https://blog.csdn.net/CSqingchen/article/details/134656140
最新更新地址 https://gitee.com/chenjim/chenjimblog

通过 Android Bitmap 模糊效果实现 (一),我们知道可以使用 Toolkit 实现 Bitmap 模糊,还能达到不错的效果。本文主要讲解另外几种实现Bitmap模糊的方法并对比效率。

使用 Vukan 模糊

Vulkan 是一种低开销、跨平台的 API,用于高性能 3D 图形。
Android平台包含 Khronos Group 的 Vulkan API规范的特定实现。
Android Vulkan 使用可以参考:
https://developer.android.com/ndk/guides/graphics/getting-started

使用 Vukan 模糊的核心代码如下,可参考 ImageProcessor.cpp

bool ImageProcessor::blur(float radius, int outputIndex) {RET_CHECK(1.0f <= radius && radius <= 25.0f);// Calculate gaussian kernel, this is equivalent to ComputeGaussianWeights at// https://cs.android.com/android/platform/superproject/+/master:frameworks/rs/cpu_ref/rsCpuIntrinsicBlur.cpp;l=57constexpr float e = 2.718281828459045f;constexpr float pi = 3.1415926535897932f;float sigma = 0.4f * radius + 0.6f;float coeff1 = 1.0f / (std::sqrtf(2.0f * pi) * sigma);float coeff2 = -1.0f / (2.0f * sigma * sigma);int32_t iRadius = static_cast<int>(std::ceilf(radius));float normalizeFactor = 0.0f;for (int r = -iRadius; r <= iRadius; r++) {const float value = coeff1 * std::powf(e, coeff2 * static_cast<float>(r * r));mBlurData.kernel[r + iRadius] = value;normalizeFactor += value;}normalizeFactor = 1.0f / normalizeFactor;for (int r = -iRadius; r <= iRadius; r++) {mBlurData.kernel[r + iRadius] *= normalizeFactor;}RET_CHECK(mBlurUniformBuffer->copyFrom(&mBlurData));// Apply a two-pass blur algorithm: a horizontal blur kernel followed by a vertical// blur kernel. This is equivalent to, but more efficient than applying a 2D blur// filter in a single pass. The two-pass blur algorithm has two kernels, each of// time complexity O(iRadius), while the single-pass algorithm has only one kernel,// but the time complexity is O(iRadius^2).auto cmd = mCommandBuffer->handle();RET_CHECK(beginOneTimeCommandBuffer(cmd));// The temp image is used as an output storage image in the first pass.mTempImage->recordLayoutTransitionBarrier(cmd, VK_IMAGE_LAYOUT_GENERAL, /*preserveData=*/false);// First pass: apply a horizontal gaussian blur.mBlurHorizontalPipeline->recordComputeCommands(cmd, &iRadius, *mInputImage, *mTempImage,mBlurUniformBuffer.get());// The temp image is used as an input sampled image in the second pass,// and the staging image is used as an output storage image.mTempImage->recordLayoutTransitionBarrier(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);mStagingOutputImage->recordLayoutTransitionBarrier(cmd, VK_IMAGE_LAYOUT_GENERAL,/*preserveData=*/false);// Second pass: apply a vertical gaussian blur.mBlurVerticalPipeline->recordComputeCommands(cmd, &iRadius, *mTempImage, *mStagingOutputImage,mBlurUniformBuffer.get());// Prepare for image copying from the staging image to the output image.mStagingOutputImage->recordLayoutTransitionBarrier(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);// Copy staging image to output image.recordImageCopyingCommand(cmd, *mStagingOutputImage, *mOutputImages[outputIndex]);// Submit to queue.RET_CHECK(endAndSubmitCommandBuffer(cmd, mContext->queue()));return true;
}

Vukan 环境、资源、Pipeline 相关代码如下

https://github.com/android/renderscript-samples/tree/main/RenderScriptMigrationSample/app/src/main/cpp

上层接口参见 VulkanImageProcessor

这里需要用到 libVkLayer_khronos_validation.so, 可以在以下地址下载新版本
https://github.com/KhronosGroup/Vulkan-ValidationLayers

使用 RenderEffect 模糊

实现代码如下

override fun blur(radius: Float, outputIndex: Int): Bitmap {params?.let {val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,Shader.TileMode.MIRROR)return applyEffect(it, blurRenderEffect, outputIndex)}throw RuntimeException("Not configured!")
}
private fun applyEffect(it: Params, renderEffect: RenderEffect, outputIndex: Int): Bitmap {it.renderNode.setRenderEffect(renderEffect)val renderCanvas = it.renderNode.beginRecording()renderCanvas.drawBitmap(it.bitmap, 0f, 0f, null)it.renderNode.endRecording()it.hardwareRenderer.createRenderRequest().setWaitForPresent(true).syncAndDraw()val image = it.imageReader.acquireNextImage() ?: throw RuntimeException("No Image")val hardwareBuffer = image.hardwareBuffer ?: throw RuntimeException("No HardwareBuffer")val bitmap = Bitmap.wrapHardwareBuffer(hardwareBuffer, null)?: throw RuntimeException("Create Bitmap Failed")hardwareBuffer.close()image.close()return bitmap
}
inner class Params(val bitmap: Bitmap, numberOfOutputImages: Int) {@SuppressLint("WrongConstant")val imageReader = ImageReader.newInstance(bitmap.width, bitmap.height,PixelFormat.RGBA_8888, numberOfOutputImages,HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_GPU_COLOR_OUTPUT)val renderNode = RenderNode("RenderEffect")val hardwareRenderer = HardwareRenderer()init {hardwareRenderer.setSurface(imageReader.surface)hardwareRenderer.setContentRoot(renderNode)renderNode.setPosition(0, 0, imageReader.width, imageReader.height)}
}

完整实例参考
RenderEffectImageProcessor.kt

使用 GLSL 模糊

主要流程:

  • 将输入 Bitmap 转为纹理
    GLES31.glTexStorage2D( GLES31.GL_TEXTURE_2D, 1, GLES31.GL_RGBA8, mInputImage.width, mInputImage.height )
  • 通过 OpenGL 处理纹理

完整实例参考 GLSLImageProcessor.kt

RS、Vukan、RenderEffect、GLSL 效率对比

通过示例 RenderScriptMigrationSample 可以看到
他们之间效率对比结果如下


以上就是 Bitmap 模糊实现的方案二,希望对你有所帮助。
如果你在使用过程遇到问题,可以留言讨论。
如果你觉得本文写的还不错,欢迎点赞收藏。


相关文章
Android Bitmap 模糊效果实现 (一)
Android Bitmap 模糊效果实现 (二)

相关文章:

Android Bitmap 模糊效果实现 (二)

文章目录 Android Bitmap 模糊效果实现 (二)使用 Vukan 模糊使用 RenderEffect 模糊使用 GLSL 模糊RS、Vukan、RenderEffect、GLSL 效率对比 Android Bitmap 模糊效果实现 (二) 本文首发地址 https://blog.csdn.net/CSqingchen/article/details/134656140 最新更新地址 https:/…...

初识Java 18-4 泛型

目录 泛型存在的问题 在泛型中使用基本类型 实现参数化接口 类型转换和警告 无法实现的重载 基类会劫持接口 自限定类型 奇异递归类型 自限定 自限定提供的参数协变性 本笔记参考自&#xff1a; 《On Java 中文版》 泛型存在的问题 接下来讨论的&#xff0c;是在泛型…...

家政保洁预约小程序app开发特点有哪些?

家政预约服务小程序APP开发的特点介绍&#xff1b; 1. 低成本&#xff1a;用户通过手机APP下单&#xff0c;省去了中介费用&#xff0c;降低了雇主的雇佣成本。 2. 高收入&#xff1a;家政服务人员通过手机APP接单&#xff0c;省去了中介费用&#xff0c;从而提高了服务人员的…...

【JavaEE初阶】 HTTP响应报文

文章目录 &#x1f332;序言&#x1f38d;200 OK&#x1f340;404 Not Found&#x1f384;403 Forbidden&#x1f334;405 Method Not Allowed&#x1f38b;500 Internal Server Error&#x1f333;504 Gateway Timeout&#x1f332;302 Move temporarily&#x1f38d;301 Move…...

PTA: 螺旋矩阵

题目 所谓“螺旋矩阵”&#xff0c;是指对任意给定的N&#xff0c;将1到NN的数字从左上角第1个格子开始&#xff0c;按顺时针螺旋方向顺序填入NN的方阵里。本题要求构造这样的螺旋方阵。 格式 输入格式: 输入在一行中给出一个正整数N&#xff08;<10&#xff09;。 输出…...

SparkSQL远程调试(IDEA)

启动Intellij IDEA&#xff0c;打开spark源码项目&#xff0c;配置远程调试 Run->Edit Configuration 启动远程spark-sql spark-sql --verbose --driver-java-options "-Xdebug -Xrunjdwp:transportdt_socket,servery,suspendy,address5005"运行远程调试&#xf…...

Vue2 Vue3 响应式实现原理

Vue2 和 Vue3 的响应式实现原理有所不同。 Vue2 响应式实现原理&#xff1a; Vue2 使用 Object.defineProperty() 方法来实现数据劫持&#xff0c;从而实现数据的响应式更新。具体步骤如下&#xff1a; 首先&#xff0c;在初始化阶段&#xff0c;遍历 data 对象的所有属性&a…...

Android Tombstone 与Debuggerd 原理浅谈

一、前言 Android系统类问题主要有stability、performance、power、security。tombstoned是android平台的一个守护进程&#xff0c;它注册成3个socket服务端&#xff0c;客户端封装在crash_dump和debuggerd_client。 crash_dump用于跟踪定位C crash&#xff0c; debuggerd_cli…...

Matlab 三维电力线重建

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 之前曾经讨论过关于悬链线方程的曲线拟合点云最小二乘法拟合曲线,在这篇博客中其实拟合的是悬链线的一种近似形式,但对于大多数情况下已经够用了。方程如下所示: z = A ( x 2 + y 2 ) +...

GoLang Filepath.Walk遍历优化

原生标准库在文件量过大时效率和内存均表现不好 1400万文件遍历Filepath.Walk 1400万文件重写直接调用windows api并处理细节 结论 1400万文件遍历时对比 对比条目filepath.walkwindows api并触发黑科技运行时间710秒22秒内存占用480M38M 关键代码 //超级快的文件遍历 fun…...

Java面向对象第7天

精华笔记&#xff1a; 成员内部类&#xff1a;了解&#xff0c;应用率不高 类中套类&#xff0c;外面的称为外部类&#xff0c;里面的称为内部类 内部类只服务于外部类&#xff0c;对外不具备可见性 内部类对象通常在外部类中创建 内部类中可以直接访问外部类的成员(包括私有…...

网络安全如何自学?

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…...

Flink-时间窗口

在流数据处理应用中&#xff0c;一个很重要、也很常见的操作就是窗口计算。所谓的“窗口”&#xff0c;一 般就是划定的一段时间范围&#xff0c;也就是“时间窗”&#xff1b;对在这范围内的数据进行处理&#xff0c;就是所谓的 窗口计算。所以窗口和时间往往是分不开的。 时…...

软件设计模式原则(三)单一职责原则

单一职责原则&#xff08;SRP&#xff09;又称单一功能原则。它规定一个类应该只有一个发生变化的原因。所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变&#xff0c;那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原…...

使用Postman创建Mock Server

这篇文章将教会大家如何利用 Postman&#xff0c;通过 Mock 的方式测试我们的 API。 什么是 Mock Mock 是一项特殊的测试技巧&#xff0c;可以在没有依赖项的情况下进行单元测试。通常情况下&#xff0c;Mock 与其他方法的主要区别就是&#xff0c;用于取代代码依赖项的模拟对…...

【古月居《ros入门21讲》学习笔记】15_ROS中的坐标系管理系统

目录 说明&#xff1a; 1. 机器人中的坐标变换 tf功能包能干什么&#xff1f; tf坐标变换如何实现 2. 小海龟跟随实验 安装 ros-melodic-turtle-tf 实验命令 运行效果 说明&#xff1a; 1. 本系列学习笔记基于B站&#xff1a;古月居《ROS入门21讲》课程&#xff0c;且使…...

初始linux:文件操作

目录 提示&#xff1a;以下指令均在Xshell 7 中进行 linux的理念 一、echo echo "字符串" 二、输出重定向 > > [文件] echo "字符串" > [文件] echo "字符串" > > [文件] 制作大文件 三、< 输入重定向与ca…...

iOS上传ipa使用可视化工具Transporter

文章目录 前言一、Transporter二、Appuploader三、iTMSTransporter总结 前言 最近为了让非开发人员上传IPA文件&#xff0c;特意找了一些方法&#xff0c;至于以前的ApplicationUploader已经不能用了&#xff0c;下面介绍两个工具可以上传IPA包。 一、Transporter 1、操作简单…...

解读《陆奇最新演讲实录—我的大模型世界观》

腾讯科技频道记者张小珺一篇《陆奇最新演讲实录—我的大模型世界观》刷爆朋友圈。文章知识点丰富、字里行间处处流淌着创业方法论和AI应用商机&#xff0c;含金量极高&#xff01; PS&#xff1a;一家之言、不求苟同。如有不爽之处&#xff0c;欢迎来 找我。 腾讯新闻原文&am…...

ChatGPT到底是如何运作?

自从2022年11月30日发布以来&#xff0c;ChatGPT一直占据着科技届的头条位置&#xff0c;随着苹果的创新能力下降&#xff0c;ChatGPT不断给大家带来震撼&#xff0c;2023年11月7日&#xff0c;首届OpenAI开发者大会在洛杉矶举行&#xff0c;业界普遍认为&#xff0c;OpenAI的开…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

CMS内容管理系统的设计与实现:多站点模式的实现

在一套内容管理系统中&#xff0c;其实有很多站点&#xff0c;比如企业门户网站&#xff0c;产品手册&#xff0c;知识帮助手册等&#xff0c;因此会需要多个站点&#xff0c;甚至PC、mobile、ipad各有一个站点。 每个站点关联的有站点所在目录及所属的域名。 一、站点表设计…...

智警杯备赛--excel模块

数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中&#xff0c;点击确定 这是最终结果&#xff0c;但是由于环境启不了&#xff0c;这里用的是自己的excel&#xff0c;真实的环境中的excel根据实训…...