0

我正在画一个圆圈,如下所示,我用块色填充,但理想情况下我想复制 iOS7 风格的模糊,尤其是当它位于照片顶部时。

我已经研究了执行此操作的各种方法,但它们都涉及 UIImage 而这是我正在绘制的圆圈。有什么办法可以做到这一点?

    - (void)drawCenter:(CGContextRef)contextRef withViewSize:(CGSize)viewSize andCenter:(CGPoint)center
{
    int innerDiameter = viewSize.width - self.thickness;
    float innerRadius = innerDiameter / 2;

    CGContextSetLineWidth(contextRef, self.thickness);
    CGRect innerCircle = CGRectMake(center.x - innerRadius, center.y - innerRadius,
                                    innerDiameter, innerDiameter);
    CGContextAddEllipseInRect(contextRef, innerCircle);
    CGContextClip(contextRef);
    CGContextClearRect(contextRef, innerCircle);
    CGContextSetFillColorWithColor(contextRef, self.centerColor.CGColor);
    CGContextFillRect(contextRef, innerCircle);
}
4

1 回答 1

2

您可以只进行模糊处理,但将结果(例如使用 )剪辑CGContextClip到圆圈绘制的路径中。以下代码模糊图像中的圆圈,将其亮度增加 10%:

UIImage *original = [UIImage imageNamed:@"image.png"];

UIImage *imageWithBlurredCircle = [original imageWithBlurredCircleWithCenter:CGPointMake(x, y)
                                                                      radius:75
                                                                        blur:10
                                                                  luminosity:0.1];

显然,如果您不想更改亮度,0请通过luminosity调整。或者如果你想降低 10% 的亮度,通过-0.1

反正下面这个UIImage类渲染出来的最终图片如下:

#import "UIImage+Blur.h"
#import <CoreImage/CoreImage.h>

@implementation UIImage (Blur)

- (UIImage *)imageWithBlurredCircleWithCenter:(CGPoint)center radius:(CGFloat)circleRadius blur:(CGFloat)blurRadius luminosity:(CGFloat)luminosity
{
    UIImage *blurredImage = [self imageWithBlur:blurRadius luminosity:luminosity];
    CGRect frame = CGRectMake(0, 0, self.size.width, self.size.height);

    UIGraphicsBeginImageContext(self.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // if you don't want to include the original image, exclude the next five lines

    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0.0f, self.size.height);
    CGContextScaleCTM(context, 1.0f, -1.0f);
    CGContextDrawImage(context, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage);
    CGContextRestoreGState(context);

    // clip the drawing to the blurred circle

    CGContextSaveGState(context);
    CGContextAddArc(context, center.x, center.y, circleRadius, 0, M_PI * 2.0, YES);
    CGContextClosePath(context);
    CGContextClip(context);
    CGContextTranslateCTM(context, 0.0f, self.size.height);
    CGContextScaleCTM(context, 1.0f, -1.0f);
    CGContextDrawImage(context, frame, blurredImage.CGImage);
    CGContextRestoreGState(context);

    // now save the image

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

- (UIImage *)imageWithBlur:(CGFloat)radius luminosity:(CGFloat)luminosity
{
    CIImage *inputImage  = [CIImage imageWithCGImage:self.CGImage]; // self.CIImage;
    CIContext *context   = [CIContext contextWithOptions:nil];

    CIImage *blurImage   = [self blurCIImage:inputImage radius:radius];
    CIImage *outputImage = [self changeLuminosityOfCIImage:blurImage luminosity:luminosity];

    // note, adjust rect because blur changed size of image

    CGRect rect          = [outputImage extent];
    rect.origin.x        += (rect.size.width  - self.size.width ) / 2;
    rect.origin.y        += (rect.size.height - self.size.height) / 2;
    rect.size            = self.size;

    CGImageRef cgimg = [context createCGImage:outputImage fromRect:rect];
    UIImage *image = [UIImage imageWithCGImage:cgimg];

    CGImageRelease(cgimg);

    return image;
}

- (CIImage *)blurCIImage:(CIImage *)inputImage radius:(CGFloat)radius
{
    if (radius == 0)
        return inputImage;

    CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [blurFilter setDefaults];
    [blurFilter setValue:inputImage forKey:kCIInputImageKey];
    [blurFilter setValue:@(radius) forKey:kCIInputRadiusKey];

    return [blurFilter outputImage];
}

- (CIImage *)changeLuminosityOfCIImage:(CIImage *)inputImage luminosity:(CGFloat)luminosity
{
    if (luminosity == 0)
        return inputImage;

    NSParameterAssert(luminosity >= -1.0 && luminosity <= 1.0);

    CIFilter *toneCurveFilter = [CIFilter filterWithName:@"CIToneCurve"];
    [toneCurveFilter setDefaults];
    [toneCurveFilter setValue:inputImage forKey:kCIInputImageKey];

    if (luminosity > 0)
    {
        [toneCurveFilter setValue:[CIVector vectorWithX:0.0  Y:luminosity]                           forKey:@"inputPoint0"];
        [toneCurveFilter setValue:[CIVector vectorWithX:0.25 Y:luminosity + 0.25 * (1 - luminosity)] forKey:@"inputPoint1"];
        [toneCurveFilter setValue:[CIVector vectorWithX:0.50 Y:luminosity + 0.50 * (1 - luminosity)] forKey:@"inputPoint2"];
        [toneCurveFilter setValue:[CIVector vectorWithX:0.75 Y:luminosity + 0.75 * (1 - luminosity)] forKey:@"inputPoint3"];
        [toneCurveFilter setValue:[CIVector vectorWithX:1.0  Y:1.0]                                  forKey:@"inputPoint4"];
    }
    else
    {
        [toneCurveFilter setValue:[CIVector vectorWithX:0.0  Y:0.0]                     forKey:@"inputPoint0"];
        [toneCurveFilter setValue:[CIVector vectorWithX:0.25 Y:0.25 * (1 + luminosity)] forKey:@"inputPoint1"];
        [toneCurveFilter setValue:[CIVector vectorWithX:0.50 Y:0.50 * (1 + luminosity)] forKey:@"inputPoint2"];
        [toneCurveFilter setValue:[CIVector vectorWithX:0.75 Y:0.75 * (1 + luminosity)] forKey:@"inputPoint3"];
        [toneCurveFilter setValue:[CIVector vectorWithX:1.0  Y:1 + luminosity]          forKey:@"inputPoint4"];
    }

    return [toneCurveFilter outputImage];
}

@end

或者,如果您前往WWDC 2013 示例代码(需要付费开发者订阅)并下载iOS_UIImageEffects,然后您可以获取该UIImage+ImageEffects类别。这提供了一些新方法:

- (UIImage *)applyLightEffect;
- (UIImage *)applyExtraLightEffect;
- (UIImage *)applyDarkEffect;
- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;
- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;

因此,要模糊和成像并使其变亮(给出“毛玻璃”效果),您可以执行以下操作:

UIImage *newImage = [image applyLightEffect];

有趣的是,Apple 的代码并没有使用CIFilter,而是调用vImageBoxConvolve_ARGB8888vImage 高性能图像处理框架

这种技术在 WWDC 2013 视频Implementation Engaging UI on iOS中有说明。

于 2013-10-12T19:03:08.740 回答