iOS图片处理之背景虚化原理解析

本文介绍了一种通过图层叠加实现背景虚化的方法,利用径向渐变和线性渐变遮罩层来达到焦点区域清晰而外围逐渐模糊的效果,并提供了具体的Swift代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >




背景虚化就是焦点中心区域清晰,中心到外部逐渐虚化的一种效果。

实现原理,由上到下分三层,最下面一层为原图

3- 遮罩层(径向渐变)

2- 原图高斯模糊后的效果图

1- 原图

根据遮罩原理,图层2的alpha值取自图层3遮罩层的alpha,遮罩层通过径向渐变的绘制,可实现中心区域透明度为1,中心到外部透明度逐渐降为0的效果。

遮罩层绘制代码如下:

override func drawRect(rect: CGRect)
    {
        //print("drawRect: context", radius, rect)
        guard let context = UIGraphicsGetCurrentContext() else{
            return
        }
        
        var gradient: CGGradientRef?
        var colorSpace: CGColorSpaceRef?
        
        let red:CGFloat = 1
        let green:CGFloat = 1
        let blue:CGFloat = 1
        
        
        let locations: [CGFloat] = [0.0, innerRadius / radius, (innerRadius + gradientWidth) / radius, 1.0]
        let numberOfLocation: size_t = locations.count
        let components: [CGFloat] = [
                                     red,   green,  blue,   0.0,
                                     red,   green,  blue,   0.0,
                                     red,   green,  blue,   1.0,
                                     red,   green,  blue,   1.0]
        
        colorSpace = CGColorSpaceCreateDeviceRGB()
        gradient = CGGradientCreateWithColorComponents(colorSpace,
                                                       components,
                                                       locations,
                                                       numberOfLocation)
        //定义起始点和终止点
        let startPoint: CGPoint = CGPointMake(radius, radius)
        let endPoint: CGPoint = CGPointMake(radius, radius)
        
        CGContextDrawRadialGradient(context,
                                    gradient,
                                    startPoint,
                                    0,
                                    endPoint,
                                    radius,
                                    CGGradientDrawingOptions(rawValue: 0))
    }


线性渐变遮罩层代码如下:

override func drawRect(rect: CGRect)
    {
        
        guard let context = UIGraphicsGetCurrentContext() else{
            return
        }
        
        var gradient: CGGradientRef?
        var colorSpace: CGColorSpaceRef?
        
        let red:CGFloat = 1
        let green:CGFloat = 1
        let blue:CGFloat = 1
        
        let frameWidth:CGFloat = _originSize.width
        let p1 = (frameWidth * 0.5 - innerWidth * 0.5 - gradientWidth) / frameWidth
        let p2 = (frameWidth * 0.5 - innerWidth * 0.5) / frameWidth
        let p3 = (frameWidth * 0.5 + innerWidth * 0.5) / frameWidth
        let p4 = (frameWidth * 0.5 + innerWidth * 0.5 + gradientWidth) / frameWidth
        let locations: [CGFloat] = [0.0, p1, p2, p3, p4, 1.0]
        let numberOfLocation: size_t = locations.count
        let components: [CGFloat] = [
            red,   green,  blue,   1.0,
            red,   green,  blue,   1.0,
            red,   green,  blue,   0.0,
            red,   green,  blue,   0.0,
            red,   green,  blue,   1.0,
            red,   green,  blue,   1.0
            ]
        
        colorSpace = CGColorSpaceCreateDeviceRGB()
        gradient = CGGradientCreateWithColorComponents(colorSpace,
                                                       components,
                                                       locations,
                                                       numberOfLocation)

        let startPoint: CGPoint = CGPointMake(0, 0)
        let endPoint: CGPoint = CGPointMake(0, frameWidth)
        
        
        CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, CGGradientDrawingOptions(rawValue: 0))
        
    }



遮罩层的移动、缩放、旋转手势需要同时运行

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool
    {
        return true
    }

另外为了避免遮罩层缩放、旋转过程中的卡顿,因此需要将遮罩层重绘异步执行

xxx.layer.drawsAsynchronously = true








评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值