objective-c - UIBezierPath 绘制的 View 的模糊屏幕截图

标签 objective-c ios uiimage core-graphics uibezierpath

我正在使用 UIBezierPath 方法和 coretext 绘制图 TableView 。我使用 addQuadCurveToPoint:controlPoint: 方法在图形上绘制曲线。我还使用 CATiledLayer 来渲染 x 轴上具有大数据集的图形。我在图像上下文中绘制整个图形,并在 View 的 drawrect: 方法中在整个 View 中绘制此图像。以下是我的代码。

- (void)drawImage{

        UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);

        // Draw Curves 
        [self drawDiagonal];

        UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
        [screenshot retain];
        UIGraphicsEndImageContext();
}
- (void)drawRect:(CGRect)rect{

    NSLog(@"Draw iN rect with Bounds: %@",NSStringFromCGRect(rect));
    [screenshot drawInRect:self.frame];
}

但是在屏幕截图中,两点之间绘制的曲线并不平滑。我还在我的信息列表中将 Render with Antialiasing 设置为 YES。请看截图。 enter image description here

最佳答案

我们必须看看你是如何构造 UIBezierPath 的,但根据我的经验,对于平滑曲线,关键问题是曲线的控制点和终点之间的线的斜率是否该特定曲线段的斜率等于曲线的下一段起点与其控制点之间的斜率。我发现使用 addCurveToPoint 而不是 addQuadCurveToPoint 更容易绘制一般平滑曲线,因此我可以调整开始和结束控制点以更普遍地满足此标准。

为了说明这一点,我通常绘制UIBezierPath曲线的方式是在曲线上有一个点数组,以及曲线在该点应采取的角度,然后是“权重” "addCurveToPoint 控制点(即控制点应该有多远)。因此,我使用这些参数来指示 UIBezierPath 的第二个控制点和 UIBezierPath 下一段的第一个控制点。所以,例如:

@interface BezierPoint : NSObject
@property CGPoint point;
@property CGFloat angle;
@property CGFloat weight;
@end

@implementation BezierPoint

- (id)initWithPoint:(CGPoint)point angle:(CGFloat)angle weight:(CGFloat)weight
{
    self = [super init];

    if (self)
    {
        self.point  = point;
        self.angle  = angle;
        self.weight = weight;
    }

    return self;
}

@end

然后是我如何使用它的示例:

- (void)loadBezierPointsArray
{
    // clearly, you'd do whatever is appropriate for your chart.
    // this is just a unclosed loop. But it illustrates the idea.

    CGPoint startPoint = CGPointMake(self.view.frame.size.width / 2.0, 50);

    _bezierPoints = [NSMutableArray arrayWithObjects:
            [[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x, startPoint.y) 
                                         angle:M_PI_2 * 0.05
                                        weight:100.0 / 1.7],
            [[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x + 100.0, startPoint.y + 70.0) 
                                         angle:M_PI_2
                                        weight:70.0 / 1.7],
            [[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x, startPoint.y + 140.0)
                                         angle:M_PI
                                        weight:100.0 / 1.7],
            [[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x - 100.0, startPoint.y + 70.0)
                                         angle:M_PI_2 * 3.0
                                        weight:70.0 / 1.7],
            [[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x + 10.0, startPoint.y + 10)
                                         angle:0.0
                                        weight:100.0 / 1.7],
            nil];
}

- (CGPoint)calculateForwardControlPoint:(NSUInteger)index
{
    BezierPoint *bezierPoint = _bezierPoints[index];

    return CGPointMake(bezierPoint.point.x + cosf(bezierPoint.angle) * bezierPoint.weight,  
                       bezierPoint.point.y + sinf(bezierPoint.angle) * bezierPoint.weight);
}

- (CGPoint)calculateReverseControlPoint:(NSUInteger)index
{
    BezierPoint *bezierPoint = _bezierPoints[index];

    return CGPointMake(bezierPoint.point.x - cosf(bezierPoint.angle) * bezierPoint.weight,  
                       bezierPoint.point.y - sinf(bezierPoint.angle) * bezierPoint.weight);
}

- (UIBezierPath *)bezierPath
{
    UIBezierPath *path = [UIBezierPath bezierPath];
    BezierPoint *bezierPoint = _bezierPoints[0];

    [path moveToPoint:bezierPoint.point];

    for (NSInteger i = 1; i < [_bezierPoints count]; i++)
    {
        bezierPoint = _bezierPoints[i];

        [path addCurveToPoint:bezierPoint.point
                controlPoint1:[self calculateForwardControlPoint:i - 1] 
                controlPoint2:[self calculateReverseControlPoint:i]];
    }

    return path;
}

当我将其渲染成 UIImage(使用下面的代码)时,我没有看到图像有任何柔化,但不可否认图像并不相同。 (我正在将 capture 呈现的图像与我通过同时按下物理设备上的电源和主页按钮使用屏幕快照手动捕获的图像进行比较。)

如果您看到一些软化,我会建议 renderInContext(如下所示)。我想知道您是否将图像写为 JPG(有损)。如果您使用的是 JPG,也许可以试试 PNG。

- (void)drawBezier
{
    UIBezierPath *path = [self bezierPath];

    CAShapeLayer *oval = [[CAShapeLayer alloc] init];
    oval.path = path.CGPath;
    oval.strokeColor = [UIColor redColor].CGColor;
    oval.fillColor = [UIColor clearColor].CGColor;
    oval.lineWidth = 5.0;
    oval.strokeStart = 0.0;
    oval.strokeEnd = 1.0;
    [self.view.layer addSublayer:oval];
}

- (void)capture
{
    UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.view.layer renderInContext:context];
    UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // save the image

    NSData *data = UIImagePNGRepresentation(screenshot);
    NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    NSString *imagePath = [documentsPath stringByAppendingPathComponent:@"image.png"];
    [data writeToFile:imagePath atomically:YES];

    // send it to myself so I can look at the file

    NSURL *url = [NSURL fileURLWithPath:imagePath];
    UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:@[url]
                                                                         applicationActivities:nil];
    [self presentViewController:controller animated:YES completion:nil];
}

关于objective-c - UIBezierPath 绘制的 View 的模糊屏幕截图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14021883/

相关文章:

ios - 如何使用 UIBezierPath 创建 UIImage

ios - 使用 avcapture session 拉伸(stretch)捕获图像

ios - 将 UIView 渲染为比屏幕上大的 UIImage

ios - iphone 6 及更高版本的 Xcode 约束和大小类

iphone - 在iphone中从多个数组中添加数组中的对象

ios - 如何在 UIButton 上设置一个不可见的标题?

ios - CBPeripheral,获取本地外设标识符

ios - 为不同的 Controller 重用 View 的最佳方式

objective-c - NSCell 上的 NSAttributedString

ios - ARKit 电平测量