2012-08-14 25 views
5

Làm cách nào để có được hiệu ứng mượt mà (độ cứng) như photoshop? Độ cứng của bàn chải iOS như Photoshop

nỗ lực của tôi:

CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSaveGState(context); 
CGContextSetLineCap(context, kCGLineCapRound); 
CGContextSetLineWidth(context, 30); 
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:0.5f].CGColor); 
CGContextSetShadowWithColor(context, CGSizeMake(0, 0), 20.0f, [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:1.0f].CGColor); 
CGContextAddPath(context, path); 
CGContextStrokePath(context); 
CGContextRestoreGState(context); 

tôi đã cố gắng điều chỉnh giá trị alpha, và yếu tố bóng mờ, nhưng không có kết quả thành công.

Có ai có giải pháp cho điều này không? Bất kỳ trợ giúp sẽ được đánh giá cao.

Trả lời

11

Trên hình ảnh này, bạn có thể thấy kết quả mã sau. Tôi tin rằng nó gần giống với những gì bạn muốn.

enter image description here

bóng Chỉ cần bên ngoài là không chỉ đủ để cung cấp cho rằng hiệu ứng mượt mà đó là lý do tại sao tôi thêm một số inner shadow để hình thành với màu trắng.

- (void)drawRect:(CGRect)rect { 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Shadows 
    UIColor* shadow = UIColor.redColor; 
    CGSize shadowOffset = CGSizeMake(0.1, -0.1); 
    CGFloat shadowBlurRadius = 11; 
    UIColor* shadow2 = UIColor.whiteColor; // Here you can adjust softness of inner shadow. 
    CGSize shadow2Offset = CGSizeMake(0.1, -0.1); 
    CGFloat shadow2BlurRadius = 9; 

    // Rectangle Drawing 
    UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRoundedRect: CGRectMake(59, 58, 439, 52) cornerRadius: 21]; 
    CGContextSaveGState(context); 
    CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, [shadow CGColor]); 
    [UIColor.redColor setFill]; 
    [rectanglePath fill]; 

    // Rectangle Inner Shadow 
    CGContextSaveGState(context); 
    UIRectClip(rectanglePath.bounds); 
    CGContextSetShadowWithColor(context, CGSizeZero, 0, NULL); 

    CGContextSetAlpha(context, CGColorGetAlpha([shadow2 CGColor])); 
    CGContextBeginTransparencyLayer(context, NULL); 
    { 
     UIColor* opaqueShadow = [shadow2 colorWithAlphaComponent: 1]; 
     CGContextSetShadowWithColor(context, shadow2Offset, shadow2BlurRadius, [opaqueShadow CGColor]); 
     CGContextSetBlendMode(context, kCGBlendModeSourceOut); 
     CGContextBeginTransparencyLayer(context, NULL); 

     [opaqueShadow setFill]; 
     [rectanglePath fill]; 

     CGContextEndTransparencyLayer(context); 
    } 
    CGContextEndTransparencyLayer(context); 
    CGContextRestoreGState(context); 

    CGContextRestoreGState(context); 
} 

Về kích thước hình dạng bạn phải điều chỉnh cả bán kính mờ trong và ngoài.

+0

có vẻ như bạn đang sử dụng hình chữ nhật? làm thế nào bạn sẽ làm điều này với một cơn đột quỵ? – ninjaneer

+0

@Ninja có nó là hình chữ nhật, bạn có muốn vẽ đường trong 'touchesMoved' và cùng ảnh hưởng không? – mohacs

+0

Tôi không chắc chắn điều đó sẽ ảnh hưởng như thế nào đến hiệu suất, nhưng nếu nó đạt được hiệu quả trên một đường nét thì sẽ ổn thôi. – ninjaneer

1

Đây có lẽ không phải là câu trả lời hoàn hảo, nhưng đó là điều tốt nhất tôi có thể làm cho các nhu cầu của mình.

Grab các FXBlurView: https://github.com/nicklockwood/FXBlurView

Bạn có thể vẽ đột quỵ của bạn trên một FXBlurView hoặc chuyển đổi UIView của bạn để UIImage sau khi bạn đã hoàn tất bản vẽ (sử dụng mã tôi lấy từ câu trả lời này https://stackoverflow.com/a/22494886/505259):

+ (UIImage *) imageWithView:(UIView *)view 
{ 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0f); 
    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO]; 
    UIImage * snapshotImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return snapshotImage; 
} 

và sử dụng loại FXBlurView về UIImage:

- (UIImage *)blurredImageWithRadius:(CGFloat)radius 
         iterations:(NSUInteger)iterations 
          tintColor:(UIColor *)tintColor; 

để làm mờ hình ảnh kết quả, cho nó một bàn chải mềm như Photoshop xuất hiện.

Tôi vẫn đang tìm kiếm câu trả lời thực sự. Tôi có một dự án OpenCV đòi hỏi một bản sao chính xác của công cụ bàn chải mềm của Photoshop.

0

Tôi đã làm việc để vẽ đường đi với ánh sáng bên trong và bằng cách nào đó đã thành công (ít nhất là theo sở thích của tôi).

Tôi đã triển khai mã vẽ trên đầu trang của levinunnick's Smooth-Line-View. Mã được MIT cấp phép, vì vậy bạn sẽ cần thêm mã đó vào dự án của mình.

Hiện tại, bạn có thể gán màu đường, chiều rộng và độ mịn cho dòng bạn muốn vẽ. Hãy cẩn thận với độ mượt, sử dụng một phao giữa 0 - 1. Tôi đã thay đổi các phương pháp cảm ứng khiến tôi cần truy cập các phương thức vẽ từ một chế độ xem khác. Kiểm tra mã ban đầu, nếu bạn muốn hoàn nguyên về phương thức chạm.

Tôi không tối ưu hóa mã, nếu bạn đã có ý tưởng hay hơn, chỉ cần chỉnh sửa câu trả lời này.

Dưới đây là file H:

@interface LineView : UIView 
- (instancetype)initWithFrame:(CGRect)frame andColor:(UIColor *)lineColor andWidth:(CGFloat)lineWidth andSmoothness:(CGFloat)lineSmooth;  
- (void)touchStartedWith:(CGPoint)location;  
- (void)touchMovedWith:(CGPoint)location; 
@end 

Đây là tập tin M:

#import "LineView.h" 

static const CGFloat kPointMinDistance = 0.05f; 
static const CGFloat kPointMinDistanceSquared = kPointMinDistance * kPointMinDistance; 

@interface LineView() 
@property (strong) UIColor *lineColor; 
@property (assign) CGFloat lineWidth; 
@property (assign) CGFloat lineSmooth; 

@property (assign) CGPoint currentPoint; 
@property (assign) CGPoint previousPoint; 
@property (assign) CGPoint previousPreviousPoint; 
@end 

@implementation LineView 
{ 
@private 
    CGMutablePathRef _path; 
} 

- (instancetype)initWithFrame:(CGRect)frame andColor:(UIColor *)lineColor andWidth:(CGFloat)lineWidth andSmoothness:(CGFloat)lineSmooth 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
    _path = CGPathCreateMutable(); 

    if (lineSmooth < 0) lineSmooth = 0; 
    if (lineSmooth > 1) lineSmooth = 1; 

    self.backgroundColor = [UIColor clearColor]; 
    self.lineColor = lineColor; 
    self.lineWidth = lineWidth; 
    self.lineSmooth = lineWidth * (lineSmooth/4); 
    self.opaque = NO; 
    } 
    return self; 
} 

- (void)drawRect:(CGRect)rect 
{ 
    [self.backgroundColor set]; 
    UIRectFill(rect); 

    @autoreleasepool { 

    CGColorRef theColor = self.lineColor.CGColor; 
    UIColor *theClearOpaque = [[UIColor whiteColor] colorWithAlphaComponent:1]; 

    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextAddPath(context, _path); 
    CGContextSetLineCap(context, kCGLineCapRound); 
    CGContextSetLineWidth(context, self.lineWidth); 
    CGContextSetStrokeColorWithColor(context, theColor); 

    // Outer shadow 
    CGSize shadowOffset = CGSizeMake(0.1f, -0.1f); 
    CGFloat shadowBlurRadius = self.lineSmooth; 
    CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, theColor); 

    CGContextStrokePath(context); 

    if (self.lineSmooth > 0) { 
     // Inner shadow 
     CGRect bounds = CGPathGetBoundingBox(_path); 
     CGRect drawBox = CGRectInset(bounds, -2.0f * self.lineWidth, -2.0f * self.lineWidth); 

     CGContextSaveGState(context); 
     UIRectClip(drawBox); 
     CGContextSetShadowWithColor(context, CGSizeZero, 0, NULL); 

     CGContextSetAlpha(context, CGColorGetAlpha(theClearOpaque.CGColor)); 
     CGContextBeginTransparencyLayer(context, NULL); 
     { 
     // Outer shadow 
     UIColor *oShadow = [theClearOpaque colorWithAlphaComponent:1]; 
     CGContextSetShadowWithColor(context, CGSizeMake(0.1f, -0.1f), self.lineWidth/64 * self.lineSmooth, oShadow.CGColor); 
     CGContextSetBlendMode(context, kCGBlendModeSourceOut); 
     CGContextBeginTransparencyLayer(context, NULL); 

     [oShadow setFill]; 

     // Draw the line again 
     CGContextAddPath(context, _path); 
     CGContextSetLineCap(context, kCGLineCapRound); 
     CGContextSetLineWidth(context, self.lineWidth); 
     CGContextSetStrokeColorWithColor(context, oShadow.CGColor); 
     CGContextStrokePath(context); 

     CGContextEndTransparencyLayer(context); 
     } 
     CGContextEndTransparencyLayer(context); 
     CGContextRestoreGState(context); 
    } 
    } 
} 

- (void)touchStartedWith:(CGPoint)location 
{ 
    self.previousPoint = location; 
    self.previousPreviousPoint = location; 
    self.currentPoint = location; 

    [self touchMovedWith:location]; 
} 

- (void)touchMovedWith:(CGPoint)location 
{ 
    CGRect drawBox; 

    @autoreleasepool { 
    CGFloat dx = location.x - self.currentPoint.x; 
    CGFloat dy = location.y - self.currentPoint.y; 

    if ((dx * dx + dy * dy) < kPointMinDistanceSquared) { 
     return; 
    } 

    self.previousPreviousPoint = self.previousPoint; 
    self.previousPoint = self.currentPoint; 
    self.currentPoint = location; 

    CGPoint mid1 = midPoint(self.previousPoint, self.previousPreviousPoint); 
    CGPoint mid2 = midPoint(self.currentPoint, self.previousPoint); 

    CGMutablePathRef subpath = CGPathCreateMutable(); 
    CGPathMoveToPoint(subpath, NULL, mid1.x, mid1.y); 
    CGPathAddQuadCurveToPoint(subpath, NULL, self.previousPoint.x, self.previousPoint.y, mid2.x, mid2.y); 

    CGRect bounds = CGPathGetBoundingBox(subpath); 
    drawBox = CGRectInset(bounds, -2.0f * self.lineWidth, -2.0f * self.lineWidth); 

    CGPathAddPath(_path, NULL, subpath); 
    CGPathRelease(subpath); 
    } 

    [self setNeedsDisplayInRect:drawBox]; 
} 

- (void)dealloc 
{ 
    CGPathRelease(_path); 
    _path = NULL; 
} 
@end 
3

Bạn có thể nhận được một hiệu ứng tương tự với những gì bạn đang cố gắng để đạt được bằng cách kết hợp bóng của bạn với bạn stroke

CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextAddPath(context, path); 
CGContextSetLineCap(context, kCGLineCapRound); 
CGContextSetLineWidth(context, self.lineWidth); 
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor); 
CGContextSetShadowWithColor(context, CGSizeMake(0.f, 0.f), self.lineWidth/4, [self.lineColor CGColor]); 
CGContextSetBlendMode(context, kCGBlendModeMultiply); 
CGContextSetAlpha(context, self.lineAlpha); 
CGContextStrokePath(context); 

Với chế độ hòa trộn Multiply, sử dụng màu trắng làm màu nét và đặt màu sắc của bút vẽ bạn muốn cái bóng, bạn sẽ có được kết quả sau:

enter image description here

Tôi đã kết nối các chức năng vẽ để sự kiện touchesMoved, vì vậy cách mà các con tôi làm để vẽ nên một phần của hình ảnh, các khó hơn các " Brush "vẽ (xem đường màu đen).

Các vấn đề liên quan