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;
效果图

上下完全贴合
综上所述,如果某清情况下我们要分别对图片进行磨砂,并式两个图片完全贴合,则可以使用 这种磨砂方式
相关文章:
iOS 如何对整张图分别局部磨砂,并完全贴合
官方磨砂方式 - (UIVisualEffectView *)effectView{if(!_effectView){UIBlurEffect *blur [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];_effectView [[UIVisualEffectView alloc] initWithEffect:blur];}return _effectView; }使用这种方式对一张图的上半部分和…...
Packet_Tracer的使用
一、实验目的: 通过该实验了解Packet Tracer的使用方法,能够用Packet Tracer建立和模拟网络模型。 二、主要任务: 1.熟悉PT的界面,了解按键用途。 2.尝试自己建立一个小型网络,并测试连通性。 3.学习P…...
WPF如果未定义绑定的属性,程序如何处理
问题:wpf中,<Button IsEnabled"{Binding IsValid1}"></Button>,如果没定义绑定的属性IsValid1,可以正常用吗 解答:在 WPF 中,如果没有定义绑定的属性 IsValid1,会导致绑…...
韩国留学生生活之-租房篇,柯桥韩语培训留学韩语需要学到什么程度
对于计划在韩国留学的人来说,找到合适的租房是一个重要而且有挑战性的任务。 留学生遇到的常见租房类型为月付型、全税房。月付型就是我们常见的租房方式,一般都需要支付一个月或数个月月租的押金,按时间付房租即可,租期通常为一…...
论文笔记:基于概念漂移的在线类非平衡学习系统研究
0 摘要 论文:A Systematic Study of Online Class Imbalance Learning With Concept Drift 发表:2018年发表在TNNLS上 源代码:? 作为一个新兴的研究课题,在线类非平衡学习往往结合了类非平衡和概念漂移的挑战。它处理…...
ubuntu22.04下rv1109 rootfs编译问题处理
ubuntu22.04下rv1109 rootfs编译问题处理 buildroot编译出错记录问题一:c-stack.c的SIGSTKSZ错误解决办法问题二:libfakeroot.c的_STAT_VER报错解决办法问题三:fwriter_buffer重复定义解决办法问题四: qfloat16.h报错解决办法问题…...
Spring Boot Dubbo Zookeeper
文章目录 Spring Boot Dubbo Zookeeper简介DubboCommonProviderConsumer Zookeeper Spring Boot Dubbo Zookeeper 简介 Dubbo Common 公共依赖 <!-- Spring Boot Starter --> <dependency><groupId>org.springframework.boot</groupId><artifac…...
线程池的概念及实现原理
本篇是对前面线程池具体实现过程的补充,实现过程可参考 线程池的实现全过程v1.0版本(手把手创建,看完必掌握!!!)_竹烟淮雨的博客-CSDN博客 线程池的实现v2.0(可伸缩线程池…...
iOS App逆向之:iOS应用砸壳技术
在iOS逆向,有一项关键的技术叫做“iOS砸壳”(iOS App Decryption)。自iOS 5版本以来,苹果引入了应用程序加密机制,使得大部分应用都需要进行砸壳操作才能进行逆向分析。因此作为开发者、逆向工程师和安全研究人员都需要…...
【高性能计算】opencl安装及相关概念
目录 从异构计算讲起opencl安装的相关说明查看linux系统cpu及gpu型号方法安装opencl helloword程序运行 从异构计算讲起 异构计算是一种利用多种不同类型的计算资源来协同解决计算问题的方法。它的核心思想是将不同特性和能力的计算设备(例如CPU、GPU、FPGA等&…...
盛最多水的容器——力扣11
int maxArea(vector<int>& height) {int l=0, r=height.size()...
2023年高教社杯数学建模思路 - 复盘:校园消费行为分析
文章目录 0 赛题思路1 赛题背景2 分析目标3 数据说明4 数据预处理5 数据分析5.1 食堂就餐行为分析5.2 学生消费行为分析 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 赛题背景 校园一卡通是集…...
Flink_state 的优化与 remote_state 的探索
摘要:本文整理自 bilibili 资深开发工程师张杨,在 Flink Forward Asia 2022 核心技术专场的分享。本篇内容主要分为四个部分: 相关背景state 压缩优化Remote state 探索未来规划 点击查看原文视频 & 演讲PPT 一、相关背景 1.1 业务概况 从…...
Kdab QML (part9)自由缩放时钟
文章目录 Kdab QML (part9)自由缩放时钟代码详细解释运行截图 Kdab QML (part9)自由缩放时钟 代码 import QtQuick 2.15 import QtQuick.Window 2.15Window {id: rootwidth: 500height: 500visible: truecolor: "lightgrey"title: qsTr("Hello World")It…...
Java网络编程(二)经典案例[粘包拆包]
粘包拆包 概述 TCP是面向流的协议,TCP在网络上传输的数据就是一连串的数据,完全没有分界线。 TCP协议的底层并不了解上层业务的具体定义,它会根据TCP缓冲区的实际情况进行包的划分。 在业务层面认为一个完整的包可能会被TCP拆分成多个小包进行发送,也可能把多个小的包封装成一…...
无分布式锁的ID生成
起因 TEAM GARDEN 本来ID是自增的,后面发现自增ID比较麻烦,有问题: 不可控的间隔: 如果你在插入数据时,中途删除了一些行,导致自增的ID出现间隔,那么新插入的行会填充这些间隔,可能…...
X2000 Linux UVC
参考文档:\doc\开发使用说明\USB使用说明文档\设备\USB_UVC\xburst2\USB_UVC.pdf 一、内核添加USB UVC功能 1、确定所用dts文件 进入到/tools/iconfigtool/IConfigToolApp/路径下,执行./IConfigTool 选择config文件,查看kernel默认配置 配…...
HCIP-OpenStack组件之neutron
neutron(ovs、ovn) OVS OVS(Open vSwitch)是虚拟交换机,遵循SDN(Software Defined Network,软件定义网络)架构来管理的。 OVS介绍参考:https://mp.weixin.qq.com/s?__bizMzAwMDQyOTcwOA&mid2247485088&idx1…...
数学建模-常见算法(3)
KMP算法(Knuth-Morris-Pratt算法) KMP算法是一种用于字符串匹配的算法,它的时间复杂度为O(mn)。该算法的核心思想是在匹配失败时,利用已经匹配的信息,减少下一次匹配的起始位置。 def kmp(text, pattern): n len(…...
缓存的设计方式
问题情况: 当有大量的请求到内部系统时,若每一个请求都需要我们操作数据库,例如查询操作,那么对于那种数据基本不怎么变动的数据来说,每一次都去数据库里面查询,是很消耗我们的性能 尤其是对于在海量数据…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
STM32标准库-ADC数模转换器
文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”:输入模块(GPIO、温度、V_REFINT)1.4.2 信号 “调度站”:多路开关1.4.3 信号 “加工厂”:ADC 转换器(规则组 注入…...
从零手写Java版本的LSM Tree (一):LSM Tree 概述
🔥 推荐一个高质量的Java LSM Tree开源项目! https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree,专为高并发写入场景设计。 核心亮点: ⚡ 极致性能:写入速度超…...
MLP实战二:MLP 实现图像数字多分类
任务 实战(二):MLP 实现图像多分类 基于 mnist 数据集,建立 mlp 模型,实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入,可视化图形数字; 2、完成数据预处理:图像数据维度转换与…...
[QMT量化交易小白入门]-六十二、ETF轮动中简单的评分算法如何获取历史年化收益32.7%
本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。 QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。 文章目录 相关阅读1. 策略概述2. 趋势评分模块3 代码解析4 木头…...
【Linux】使用1Panel 面板让服务器定时自动执行任务
服务器就是一台24小时开机的主机,相比自己家中不定时开关机的主机更适合完成定时任务,例如下载资源、备份上传,或者登录某个网站执行一些操作,只需要编写 脚本,然后让服务器定时来执行这个脚本就可以。 有很多方法实现…...
