我正在画一个圆圈,我正在填充一个块颜色,但理想情况下我想要复制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);
}
答案 0 :(得分: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 sample code(需要付费开发者订阅)并下载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_ARGB8888
的vImage high-performance image processing framework。
WWDC 2013视频Implementing Engaging UI on iOS中说明了这种技术。