iOS 如何对整张图分别局部磨砂,并完全贴合

官方磨砂方式

- (UIVisualEffectView *)effectView{if(!_effectView){UIBlurEffect *blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];_effectView = [[UIVisualEffectView alloc] initWithEffect:blur];}return _effectView;
}

使用这种方式对一张图的上半部分和下半部分分别磨砂,并进行拼接,然后发现效果是这样的,请添加图片描述

即两个部分有明显的界限,无法完全贴合

自己生成新的磨砂图片

给UIImage添加一个分类,添加如下方法


- (UIImage *)applyLightEffect
{UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
}- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
{// Check pre-conditions.if (self.size.width < 1 || self.size.height < 1) {TPLOG (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);return nil;}if (!self.CGImage) {TPLOG (@"*** error: image must be backed by a CGImage: %@", self);return nil;}if (maskImage && !maskImage.CGImage) {TPLOG (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);return nil;}CGRect imageRect = { CGPointZero, self.size };UIImage *effectImage = self;BOOL hasBlur = blurRadius > __FLT_EPSILON__;BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;if (hasBlur || hasSaturationChange) {UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);CGContextRef effectInContext = UIGraphicsGetCurrentContext();CGContextScaleCTM(effectInContext, 1.0, -1.0);CGContextTranslateCTM(effectInContext, 0, -self.size.height);CGContextDrawImage(effectInContext, imageRect, self.CGImage);vImage_Buffer effectInBuffer;effectInBuffer.data     = CGBitmapContextGetData(effectInContext);effectInBuffer.width    = CGBitmapContextGetWidth(effectInContext);effectInBuffer.height   = CGBitmapContextGetHeight(effectInContext);effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);CGContextRef effectOutContext = UIGraphicsGetCurrentContext();vImage_Buffer effectOutBuffer;effectOutBuffer.data     = CGBitmapContextGetData(effectOutContext);effectOutBuffer.width    = CGBitmapContextGetWidth(effectOutContext);effectOutBuffer.height   = CGBitmapContextGetHeight(effectOutContext);effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);if (hasBlur) {// A description of how to compute the box kernel width from the Gaussian// radius (aka standard deviation) appears in the SVG spec:// http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement//// For larger values of 's' (s >= 2.0), an approximation can be used: Three// successive box-blurs build a piece-wise quadratic convolution kernel, which// approximates the Gaussian kernel to within roughly 3%.//// let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)//// ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.//CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];int radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);if (radius % 2 != 1) {radius += 1; // force radius to be odd so that the three box-blur methodology works.}vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0,radius, radius, 0, kvImageEdgeExtend);vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);}BOOL effectImageBuffersAreSwapped = NO;if (hasSaturationChange) {CGFloat s = saturationDeltaFactor;CGFloat floatingPointSaturationMatrix[] = {0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,0,                    0,                    0,  1,};const int32_t divisor = 256;NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);int16_t saturationMatrix[matrixSize];for (NSUInteger i = 0; i < matrixSize; ++i) {saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);}if (hasBlur) {vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);effectImageBuffersAreSwapped = YES;}else {vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);}}if (!effectImageBuffersAreSwapped)effectImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();if (effectImageBuffersAreSwapped)effectImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();}// Set up output context.UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);CGContextRef outputContext = UIGraphicsGetCurrentContext();CGContextScaleCTM(outputContext, 1.0, -1.0);CGContextTranslateCTM(outputContext, 0, -self.size.height);// Draw base image.CGContextDrawImage(outputContext, imageRect, self.CGImage);// Draw effect image.if (hasBlur) {CGContextSaveGState(outputContext);if (maskImage) {CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);}CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);CGContextRestoreGState(outputContext);}// Add in color tint.if (tintColor) {CGContextSaveGState(outputContext);CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);CGContextFillRect(outputContext, imageRect);CGContextRestoreGState(outputContext);}// Output image is ready.UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();return outputImage;
}

外面使用

    UIImage *blurImage = [image applyLightEffect];self.bannerView.image = blurImage;

效果图
请添加图片描述
上下完全贴合
综上所述,如果某清情况下我们要分别对图片进行磨砂,并式两个图片完全贴合,则可以使用 这种磨砂方式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/55802.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nacos 注册中心的使用(单体)

环境 springboot springcloud Nacos注册中心服务端 下载windows版或Linux版&#xff1a;https://nacos.io/zh-cn 目录结构&#xff1a; 配置文件./config/application.properties 启动文件./bin/startup.cmd&#xff1a; cmd命令启动单机服务startup.cmd -m standalone 父…

【C++】初谈迭代器

文章目录 前言一、什么是迭代器二、迭代器的分类三、迭代器的用法总结 前言 迭代器是一种可以访问和遍历容器中元素的对象&#xff0c;它类似于指针&#xff0c;但是具有更多的功能和灵活性。本文将介绍C迭代器的基本概念、分类、用法和注意事项。 一、什么是迭代器 迭代器&a…

dig批量域名逆向查询ip

dig批量域名逆向查询ip dig nocmd noall answer -f iplist.txtiplist.txt中内容 效果图&#xff1a; dig其他选项参数&#xff1a; dig www.baidu.com A # 查询A记录&#xff0c;如果域名后面不加任何参数&#xff0c;默认查询A记录 dig www.baidu.com MX # 查询MX记…

云服务器 宝塔(每次更新)

su root 输入密码 使用 root 权限 /etc/init.d/bt default 获取宝塔登录 位置和账号密码。进入宝塔 删除数据库 删除php前端站点 删除PM2后端项目 前端更改完配置打包dist文件 后端更改完配置项目打包 数据库结构导出 导入数据库 配置 PM2 后端 安装依赖

言有三新书出版,《深度学习之图像识别(全彩版)》上市发行,配套超详细的原理讲解与丰富的实战案例!...

各位同学&#xff0c;今天有三来发布新书了&#xff0c;名为《深度学习之图像识别&#xff1a;核心算法与实战案例&#xff08;全彩版&#xff09;》&#xff0c;本次书籍为我写作并出版的第6本书籍。 前言 2019年5月份我写作了《深度学习之图像识别&#xff1a;核心技术与案例…

【Go 基础篇】Go语言循环结构:实现重复执行与迭代控制

介绍 循环结构是编程中的重要概念&#xff0c;它允许我们重复执行一段代码块&#xff0c;或者按照一定的条件进行迭代控制。Go语言提供了多种循环结构&#xff0c;包括for、while和do-while等&#xff0c;用于不同的场景下实现循环操作。本篇博客将深入探讨Go语言中的循环结构…

Spring框架

一.简介 Spring 是 2003 年兴起,通过使用IOC 和 AOP 组成的轻量级的为解决企业级开发的Java开发框架 官网:Spring | Home 特点: 1.轻量级:资源jar包少,运行时框架占用资源少,效率更高 2.IOC(Inversion of Control),由Spring容器来对对象实行管理 3.AOP(面相切面的编程)是…

华为eNSP模拟器中,路由器如何添加serial接口

在ensp模拟器中新建拓扑后&#xff0c;添加2个路由器。 在路由器图标上单击鼠标右键&#xff0c;选择设置选项。 在【视图】选项卡的【eNSP支持的接口卡】窗口查找serial接口卡。 选择2SA接口卡&#xff0c;将其拖动到路由器空置的卡槽位。 如上图所示&#xff0c;已经完成路由…

【C++】map的奇葩用法:和函数结合

2023年8月26日&#xff0c;周六下午 今天才发现map居然还能这样用... #include <iostream> #include <map> #include <functional>void printOne() {std::cout << "已经打印出1" << std::endl; }void printTwo() {std::cout <<…

9. 优化器

9.1 优化器 ① 损失函数调用backward方法&#xff0c;就可以调用损失函数的反向传播方法&#xff0c;就可以求出我们需要调节的梯度&#xff0c;我们就可以利用我们的优化器就可以根据梯度对参数进行调整&#xff0c;达到整体误差降低的目的。 ② 梯度要清零&#xff0c;如果梯…

2023年03月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题:最佳路径 如下所示的由正整数数字构成的三角形: 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。你的任务就是求出最佳路径上的数字之和。 注意:路径上的每一步…

Go语言入门记录:从基础到变量、函数、控制语句、包引用、interface、panic、go协程、Channel、sync下的waitGroup和Once等

程序入口文件的包名必须是main&#xff0c;但主程序文件所在文件夹名称不必须是main&#xff0c;即我们下图hello_world.go在main中&#xff0c;所以感觉package main写顺理成章&#xff0c;但是如果我们把main目录名称改成随便的名字如filename也是可以运行的&#xff0c;所以…

AI创作助手:介绍 TensorFlow 的基本概念和使用场景

目录 背景 环境测试 入门示例 背景 TensorFlow 是一个强大的开源框架&#xff0c;用于实现深度学习和人工智能模型。它最初由 Google 开发&#xff0c;现在已经成为广泛使用的机器学习框架之一。 TensorFlow 简单来说就是一个用于创建和运行机器学习模型的库。它的核心概念…

Vue2向Vue3过度核心技术路由

目录 1 路由介绍1.思考2.路由的介绍3.总结 2 路由的基本使用1.目标2.作用3.说明4.官网5.VueRouter的使用&#xff08;52&#xff09;6.代码示例7.两个核心步骤8.总结 3 组件的存放目录问题1.组件分类2.存放目录3.总结 4 路由的封装抽离5 Vue路由-重定向1.问题2.解决方案3.语法4…

(vue)el-table 怎么把表格列中相同的数据 合并为一行

(vue)el-table 怎么把表格列中相同的数据 合并为一行 效果&#xff1a; 文档解释&#xff1a; 写法&#xff1a; <el-table:data"tableData"size"mini"class"table-class"borderstyle"width:100%"max-height"760":span-…

【集合学习ConcurrentHashMap】ConcurrentHashMap集合学习

ConcurrentHashMap集合学习 一、JDK1.7 和 1.8 版本ConcurrenHashMap对比分析 JDK 1.7版本 在JDK 1.7版本ConcurrentHashMap使用了分段锁的方式&#xff08;对Segment进行加锁&#xff09;&#xff0c;其实际结构为&#xff1a;Segment数组 HashEntry数组 链表。由很多个 …

Shiro认证框架

目录 概述 认证授权及鉴权 Shiro框架的核心组件 基本流程 spring bootshiromybatisPlus...实现用户登录 step1:准备工作 (1)坐标 (2)连接数据库 (3)JavaBean (4)dao数据访问层 (5)密码工具类 DigestsUtil (6)配置类 step2&#xff1a;认证功能 step3:授权鉴权 概述…

一文1500字从0到1搭建 Jenkins 自动化测试平台

Jenkins 自动化测试平台的作用 自动化构建平台的执行流程&#xff08;目标&#xff09;是&#xff1a; 我们将代码提交到代码托管工具上&#xff0c;如github、gitlab、gitee等。 1、Jenkins要能够检测到我们的提交。 2、Jenkins检测到提交后&#xff0c;要自动拉取代码&#x…

Uniapp笔记(七)uniapp打包

一、项目打包 1、h5打包 登录dcloud账户&#xff0c;在manifest.json的基础配置选项中&#xff0c;点击重新获取uniapp应用标识APPID 在manifest.json的Web配置选项的运行的基础路径中输入./ 在菜单栏的发行栏目&#xff0c;点击网站-PC或手机H5 输入网站标题和网站域名&am…

leetcode.105 从前序和中序遍历序列构造二叉树

题目描述&#xff1a; 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一 棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 题目要求&#xff1a; 1 < preorder.length < 3000inorder.length…