Eya*_*yal 30 core-graphics objective-c ios
我正在构建一个照片过滤器应用程序(如Instagram,Camera +以及更多......),可能主屏幕是UIImageView向用户呈现图像,以及带有一些过滤器和其他选项的底栏.
其中一个选项是模糊,用户可以用手指捏住或移动表示非模糊部分(半径和位置)的圆圈 - 此圆圈外的所有像素都将模糊.
当用户触摸屏幕时,我想在我的图像上方添加一个代表模糊部分的半透明层,其中一个完全透明的圆圈代表非模糊部分.
所以我的问题是,我该如何添加这一层?我想我需要在我的图像视图上面使用一些视图,并使用一些蒙版来获得我的圆形?我真的很感激这里的好建议.
还有一件事
我需要圆圈不会直线切割,但会有一种渐变淡化.像Instagram这样的东西:
而且非常重要的是要以良好的性能获得这种效果,我会成功获得这种效果,drawRect:但旧设备(iphone 4,iPod)的性能非常糟糕
Ell*_*rry 97
每当你想要绘制一个由一个形状(或一系列形状)组成的路径作为另一个形状的洞时,该键几乎总是使用"偶数奇怪的缠绕规则".
绕线规则只是一种算法,它跟踪构成路径整体填充区域的每个连续区域的信息.从给定区域内的点到路径边界外的任何点绘制光线.然后使用确定是否应填充区域的规则来解释交叉路径线的总数(包括隐含线)和每个路径线的方向.
我很欣赏如果没有规则作为上下文和图表来使描述更容易理解,那么描述就没有用,所以我建议你阅读我上面提供的链接.为了创建我们的圆形遮罩层,下面的图表描绘了一个奇怪的缠绕规则允许我们完成的事情:


现在,只需使用CAShapeLayer创建半透明蒙版,可以通过用户迭代重新定位和扩展和收缩.
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (strong) CAShapeLayer *blurFilterMask;
@property (assign) CGPoint blurFilterOrigin;
@property (assign) CGFloat blurFilterDiameter;
@end
@implementation ViewController
// begin the blur masking operation.
- (void)beginBlurMasking
{
self.blurFilterOrigin = self.imageView.center;
self.blurFilterDiameter = MIN(CGRectGetWidth(self.imageView.bounds), CGRectGetHeight(self.imageView.bounds));
CAShapeLayer *blurFilterMask = [CAShapeLayer layer];
// Disable implicit animations for the blur filter mask's path property.
blurFilterMask.actions = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"path", nil];
blurFilterMask.fillColor = [UIColor blackColor].CGColor;
blurFilterMask.fillRule = kCAFillRuleEvenOdd;
blurFilterMask.frame = self.imageView.bounds;
blurFilterMask.opacity = 0.5f;
self.blurFilterMask = blurFilterMask;
[self refreshBlurMask];
[self.imageView.layer addSublayer:blurFilterMask];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[self.imageView addGestureRecognizer:tapGesture];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
[self.imageView addGestureRecognizer:pinchGesture];
}
// Move the origin of the blur mask to the location of the tap.
- (void)handleTap:(UITapGestureRecognizer *)sender
{
self.blurFilterOrigin = [sender locationInView:self.imageView];
[self refreshBlurMask];
}
// Expand and contract the clear region of the blur mask.
- (void)handlePinch:(UIPinchGestureRecognizer *)sender
{
// Use some combination of sender.scale and sender.velocity to determine the rate at which you want the circle to expand/contract.
self.blurFilterDiameter += sender.velocity;
[self refreshBlurMask];
}
// Update the blur mask within the UI.
- (void)refreshBlurMask
{
CGFloat blurFilterRadius = self.blurFilterDiameter * 0.5f;
CGMutablePathRef blurRegionPath = CGPathCreateMutable();
CGPathAddRect(blurRegionPath, NULL, self.imageView.bounds);
CGPathAddEllipseInRect(blurRegionPath, NULL, CGRectMake(self.blurFilterOrigin.x - blurFilterRadius, self.blurFilterOrigin.y - blurFilterRadius, self.blurFilterDiameter, self.blurFilterDiameter));
self.blurFilterMask.path = blurRegionPath;
CGPathRelease(blurRegionPath);
}
...
Run Code Online (Sandbox Code Playgroud)

(此图可能有助于理解代码中的命名约定)
Apple的Quartz 2D Programming Guide的Gradients部分详细介绍了如何绘制径向渐变,我们可以使用它来创建带有羽毛边缘的蒙版.这可以直接通过子类化或实现其绘图委托来绘制CALayer的内容.在这里,我们将其子类化为封装与其相关的数据,即原点和直径.
BlurFilterMask.h
#import <QuartzCore/QuartzCore.h>
@interface BlurFilterMask : CALayer
@property (assign) CGPoint origin; // The centre of the blur filter mask.
@property (assign) CGFloat diameter; // the diameter of the clear region of the blur filter mask.
@end
Run Code Online (Sandbox Code Playgroud)
BlurFilterMask.m
#import "BlurFilterMask.h"
// The width in points the gradated region of the blur filter mask will span over.
CGFloat const GRADIENT_WIDTH = 50.0f;
@implementation BlurFilterMask
- (void)drawInContext:(CGContextRef)context
{
CGFloat clearRegionRadius = self.diameter * 0.5f;
CGFloat blurRegionRadius = clearRegionRadius + GRADIENT_WIDTH;
CGColorSpaceRef baseColorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat colours[8] = { 0.0f, 0.0f, 0.0f, 0.0f, // Clear region colour.
0.0f, 0.0f, 0.0f, 0.5f }; // Blur region colour.
CGFloat colourLocations[2] = { 0.0f, 0.4f };
CGGradientRef gradient = CGGradientCreateWithColorComponents (baseColorSpace, colours, colourLocations, 2);
CGContextDrawRadialGradient(context, gradient, self.origin, clearRegionRadius, self.origin, blurRegionRadius, kCGGradientDrawsAfterEndLocation);
CGColorSpaceRelease(baseColorSpace);
CGGradientRelease(gradient);
}
@end
Run Code Online (Sandbox Code Playgroud)
ViewController.m(无论您在何处实现模糊文件管理器屏蔽功能)
#import "ViewController.h"
#import "BlurFilterMask.h"
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (strong) BlurFilterMask *blurFilterMask;
@end
@implementation ViewController
// Begin the blur filter masking operation.
- (void)beginBlurMasking
{
BlurFilterMask *blurFilterMask = [BlurFilterMask layer];
blurFilterMask.diameter = MIN(CGRectGetWidth(self.imageView.bounds), CGRectGetHeight(self.imageView.bounds));
blurFilterMask.frame = self.imageView.bounds;
blurFilterMask.origin = self.imageView.center;
blurFilterMask.shouldRasterize = YES;
[self.imageView.layer addSublayer:blurFilterMask];
[blurFilterMask setNeedsDisplay];
self.blurFilterMask = blurFilterMask;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[self.imageView addGestureRecognizer:tapGesture];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
[self.imageView addGestureRecognizer:pinchGesture];
}
// Move the origin of the blur mask to the location of the tap.
- (void)handleTap:(UITapGestureRecognizer *)sender
{
self.blurFilterMask.origin = [sender locationInView:self.imageView];
[self.blurFilterMask setNeedsDisplay];
}
// Expand and contract the clear region of the blur mask.
- (void)handlePinch:(UIPinchGestureRecognizer *)sender
{
// Use some combination of sender.scale and sender.velocity to determine the rate at which you want the mask to expand/contract.
self.blurFilterMask.diameter += sender.velocity;
[self.blurFilterMask setNeedsDisplay];
}
...
Run Code Online (Sandbox Code Playgroud)

(此图可能有助于理解代码中的命名约定)
确保托管图像的multipleTouchEnabled属性UIImageView设置为YES/ true:

为了清楚地回答OP问题,这个答案继续使用最初使用的命名约定.这可能会对其他人产生一些误导."掩码"这个上下文并不是指图像蒙版,而是更一般意义上的掩模.此答案不使用任何图像屏蔽操作.
| 归档时间: |
|
| 查看次数: |
15426 次 |
| 最近记录: |