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

Android Bitmap 使用Vukan、RenderEffect、GLSL实现模糊

文章目录

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

Android Bitmap 使用Vukan、RenderEffect、GLSL实现模糊

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

通过 Android Bitmap 使用 ScriptIntrinsicBlur、Toolkit 实现模糊,我们已经知道两种实现模糊方法。
本文主要讲解另外几种高效实现Bitmap模糊的方法。

使用 RenderEffect 模糊

RenderEffect 是 Android 中一种用于实现图像特效的类,**最低 API 要求 31 ** 。
它允许开发者在不修改原始图像数据的情况下,对图像进行各种处理,例如模糊、光晕、阴影等
对 Bitmap 模糊及注释代码如下

fun blur(bitmap:Bitmap, radius: Float, outputIndex: Int): Bitmap {// 配置跟 bitmap 同样大小的 ImageReaderval 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()// 将 ImageReader 的surface 设置到 HardwareRenderer 中hardwareRenderer.setSurface(imageReader.surface)hardwareRenderer.setContentRoot(renderNode)renderNode.setPosition(0, 0, imageReader.width, imageReader.height)// 使用 RenderEffect 配置模糊效果,并设置到 RenderNode 中。  val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,Shader.TileMode.MIRROR)renderNode.setRenderEffect(renderEffect)// 通过 RenderNode 的 RenderCanvas 绘制 Bitmap。   val renderCanvas = renderNode.beginRecording()renderCanvas.drawBitmap(bitmap, 0f, 0f, null)renderNode.endRecording()// 通过 HardwareRenderer 创建 Render 异步请求。   hardwareRenderer.createRenderRequest().setWaitForPresent(true).syncAndDraw()// 通过 ImageReader 获取模糊后的 Image 。val image = imageReader.acquireNextImage() ?: throw RuntimeException("No Image")// 将 Image 的 HardwareBuffer 包装为 Bitmap , 也就是模糊后的。   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
}

完整实例参考 RenderEffectImageProcessor.kt
还可以通过设置 RenderEffect 的其他属性,如 setColorFilter( )方法,为模糊后的 Bitmap 添加颜色滤镜。

使用 Vukan 模糊

Vulkan 是一种低开销、跨平台的 API,用于高性能 3D 图形。
Android平台包含 Khronos Group 的 Vulkan API规范的特定实现。
使用 Vukan 模糊的核心代码如下,可参考 ImageProcessor.cpp

bool ImageProcessor::blur(float radius, int outputIndex) {RET_CHECK(1.0f <= radius && radius <= 25.0f);//高斯模糊配置,在后文 GLSL 同样 适用constexpr 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));// 应用两阶段模糊算法:一个水平模糊核,然后是一个垂直模糊核。// 比单遍应用一个2D模糊滤镜更高效。// 两遍模糊算法有两个核,每个核的时间复杂度为O(半径),// 而单遍模糊算法只有一个核,但时间复杂度为O(半径^2)。auto cmd = mCommandBuffer->handle();RET_CHECK(beginOneTimeCommandBuffer(cmd));// 临时映像在第一遍中用作输出存储映像mTempImage->recordLayoutTransitionBarrier(cmd, VK_IMAGE_LAYOUT_GENERAL, /*preserveData=*/false);// 水平方向高斯模糊mBlurHorizontalPipeline->recordComputeCommands(cmd, &iRadius, *mInputImage, *mTempImage,mBlurUniformBuffer.get());// 临时图像在第二遍中用作输入采样图像,// 过渡图像用作输出存储映像。mTempImage->recordLayoutTransitionBarrier(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);mStagingOutputImage->recordLayoutTransitionBarrier(cmd, VK_IMAGE_LAYOUT_GENERAL,/*preserveData=*/false);// 数值方向高斯模糊mBlurVerticalPipeline->recordComputeCommands(cmd, &iRadius, *mTempImage, *mStagingOutputImage,mBlurUniformBuffer.get());// 准备将图像从过渡图像复制到输出图像。mStagingOutputImage->recordLayoutTransitionBarrier(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);// 复制暂存图像到输出图像。recordImageCopyingCommand(cmd, *mStagingOutputImage, *mOutputImages[outputIndex]);// 提交到队列。RET_CHECK(endAndSubmitCommandBuffer(cmd, mContext->queue()));return true;
}

VulkanContext.cpp 主要是一些初始化

VulkanResources.cpp 主要是 Buffer 和 Image 的一些封装方法

上层接口参见 VulkanImageProcessor.kt

使用 GLSL 模糊

主要流程:

  • 将输入 Bitmap 转为纹理
    GLES31.glTexStorage2D(GLES31.GL_TEXTURE_2D, 1, GLES31.GL_RGBA8, mInputImage.width, mInputImage.height )
    GLUtils.texImage2D(GLES31.GL_TEXTURE_2D, 0, mInputImage, 0)
  • 通过 OpenGL 处理纹理,同样有水平、竖直模糊,即 mBlurHorizontalProgram 和 mBlurVerticalProgram
  • 将纹理转换为 Bitmap ,即 copyPixelsToHardwareBuffer ,这里也是耗时最多的

完整实例参考 GLSLImageProcessor.kt

libVkLayer_khronos_validation.so 主要是调试用,
ImageProcessor::create(/*enableDebug=*/false, assetManager) 传入 false 可以不需要
可以在以下地址下载新版本
https://github.com/KhronosGroup/Vulkan-ValidationLayers

RS、Vukan、RenderEffect、GLSL 效率对比

上文完整源码及对比示例地址
https://gitee.com/chenjim/android-blur/blob/blur/RenderScriptMigrationSample

他们之间效率对比结果如下

虽然 GLSL 看起来会差一些,主要是因为 openGL 纹理转 Bitmap 耗时较大。
如果纯GL场景使用,跟 Vukan 和 RenderEffect 相差无几。


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


相关文章
Android Bitmap 使用ScriptIntrinsicBlur、Toolkit 实现模糊
Android Bitmap 使用Vukan、RenderEffect、GLSL实现模糊)

相关文章:

Android Bitmap 使用Vukan、RenderEffect、GLSL实现模糊

文章目录 Android Bitmap 使用Vukan、RenderEffect、GLSL实现模糊使用 RenderEffect 模糊使用 Vukan 模糊使用 GLSL 模糊RS、Vukan、RenderEffect、GLSL 效率对比 Android Bitmap 使用Vukan、RenderEffect、GLSL实现模糊 本文首发地址 https://blog.csdn.net/CSqingchen/articl…...

Vue H5页面长按保存为图片

安装依赖&#xff1a;npm install html2canvas -d <template><div class"index"><div id"captureId" class"capture" v-show"firstFlag"><ul><li>1</li><li>2</li><li>3<…...

【Web】UUCTF 2022 新生赛 个人复现

目录 ①websign ②ez_rce ③ez_upload ④ez_unser ⑤ezsql ⑥ezpop ⑦funmd5 ⑧phonecode ⑨ezrce ①websign 右键打不开&#xff0c;直接抓包发包看源码 ②ez_rce “反引号” 在PHP中会被当作SHELL命令执行 ?codeprintf(l\s /); ?codeprintf(ta\c /ffffffffffl…...

设置python下载包代理

使用场景 正常网络情况下我们安装如果比较多的python包时&#xff0c;会选择使用pip install -r requirements.txt -i https://pypi.douban.com/simple --trusted-hostpypi.douban.com这种国内的镜像来加快下载速度。 但是&#xff0c;当这台被限制上网时&#xff08;公司安全…...

nginx 配置前端项目添加https

可申请阿里云免费证书 步骤省略… nginx 配置 server {listen 8050; #默认80端口 如果需要所有访问地址都是https 需要注释listen 8443 ssl; #https 访问的端口 &#xff0c;默认443server_name 192.168.128.XX; #域名 或 ip# 增加ssl#填写证书文件…...

人群计数CSRNet的pytorch实现

本文中对CSRNet: Dilated Convolutional Neural Networks for Understanding the Highly Congested Scenes&#xff08;CVPR 2018&#xff09;中的模型进行pytorch实现 import torch;import torch.nn as nn from torchvision.models import vgg16 vggvgg16(pretrained1)import…...

【HTTP协议】简述HTTP协议的概念和特点

&#x1f38a;专栏【网络编程】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出小吉的问题 文章目录 &#x1f33a;概念&#x1f33a;特点&#x1f384;请求协议&#x1f384;响应协议…...

经典神经网络——AlexNet模型论文详解及代码复现

一、背景 AlexNet是在2012年由Alex Krizhevsky等人提出的&#xff0c;该网络在2012年的ImageNet大赛上夺得了冠军&#xff0c;并且错误率比第二名高了很多。Alexnet共有8层结构&#xff0c;前5层为卷积层&#xff0c;后三层为全连接层。 论文地址&#xff1a;ImageNet Classif…...

flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级

flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级 在之前的开发过程中&#xff0c;需要实现卡片轮播效果&#xff0c;但是卡片轮播需要中间大、两边小一些的效果&#xff0c;这里就使用到了Swiper。具体效果如视频所示 添加链接描述 这里需要的效果是中间大、两边…...

【Flutter】graphic图表实现自定义tooltip

renderer graphic中tooltip的TooltipGuide类提供了renderer方法&#xff0c;接收三个参数Size类型&#xff0c;Offset类型&#xff0c;Map<int, Tuple>类型。可查到的文档是真的少&#xff0c;所以只能在源码中扒拉例子&#xff0c;做符合需求的修改。 官方github示例 …...

手机上的记事本怎么打开?安卓手机通用的记事本APP

有不少上班族发现&#xff0c;自己想要在电脑上随手记录一些工作文字内容&#xff0c;直接使用电脑上的记事本工具来编辑文字是比较便捷的。但是如果想要在手机上记录文字内容&#xff0c;就找不到手机上的记事本了。那么手机上的记事本怎么打开&#xff1f;安卓手机通用的记事…...

一起学docker系列之十五深入了解 Docker Network:构建容器间通信的桥梁

目录 1 前言2 什么是 Docker Network3 Docker Network 的不同模式3.1 桥接模式&#xff08;Bridge&#xff09;3.2 Host 模式3.3 无网络模式&#xff08;None&#xff09;3.4 容器模式&#xff08;Container&#xff09; 4 Docker Network 命令及用法4.1 docker network ls4.2 …...

前端OFD文件预览(vue案例cafe-ofd)

0、提示 下面只有vue的使用示例demo &#xff0c;官文档参考 cafe-ofd - npm 其他平台可以参考 ofd - npm 官方线上demo: ofd 1、安装包 npm install cafe-ofd --save 2、引入 import cafeOfd from cafe-ofd import cafe-ofd/package/index.css Vue.use(cafeOfd) 3、使…...

Java[list/set]通用遍历方法之Iterator

需求&#xff1a;输入一个字符串 将其拆解成单个汉字 然后一行一个输出 这里要求使用到Arraylist集合实现方法Itrator遍历的原理import java.util.ArrayList; import java.util.Collection; import java.util.Iterator;public class Main{public static void main(String[] arg…...

ubuntu/vscode下的c/c++开发之-CMake语法与练习

Cmake学习 1 语法特性介绍 基本语法格式&#xff1a;指令(参数 1 参数 2...) 参数使用括弧括起参数之间使用空格或分号分开 指令是大小写无关的&#xff0c;参数和变量是大小写相关的 set(HELLO hello.cpp) add_executable(hello main.cpp hello.cpp) ADD_EXECUTABLE(hello ma…...

Java(119):ExcelUtil工具类(org.apache.poi读取和写入Excel)

ExcelUtil工具类(XSSFWorkbook读取和写入Excel),入参和出参都是:List<Map<String,Object>> 一、读取Excel testdata.xlsx 1、new XSSFWorkbook对象 File file = new File(filePath); FileInputStream fis = new FileInputStream(file);…...

Kong处理web服务跨域

前言 好久没写文章了&#xff0c;大概有半年多了&#xff0c;这半年故事太多&#xff0c;本文写不下&#xff0c;就写写文章标题问题&#xff01; 问题描述 关于跨域的本质问题我这里不过多介绍&#xff0c;详细请看历史文章 跨域产生的原因以及常见的解决方案。 我这边是新…...

Kotlin学习——kt里的作用域函数scope function,let,run,with,apply,also

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…...

informer辅助笔记:utils/timefeatures.py

定义了一套与时间特征相关的类和函数&#xff0c;旨在从时间序列数据中提取有用的时间特征&#xff0c;以支持各种时间序列分析和预测任务 from typing import Listimport numpy as np import pandas as pd from pandas.tseries import offsets from pandas.tseries.frequenc…...

[Verilog语法]:===和!==运算符使用注意事项

[Verilog语法]&#xff1a;和!运算符使用注意事项 1&#xff0c; 和 !运算符使用注意事项2&#xff0c;3&#xff0c; 1&#xff0c; 和 !运算符使用注意事项 参考文献&#xff1a; 1&#xff0c;[SystemVerilog语法拾遗] 和!运算符使用注意事项 2&#xff0c; 3&#xff0c;...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...