UIBezierPath正在绘制的视图的屏幕截图 [英] Blurred Screenshot of a view being drawn by UIBezierPath

查看:68
本文介绍了UIBezierPath正在绘制的视图的屏幕截图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm drawing my graph view using UIBezierPathmethods and coretext. I use addQuadCurveToPoint:controlPoint: method to draw curves on graph. I also use CATiledLayer for the purpose of rendering graph with large data set on x axis. I draw my whole graph in an image context and in drawrect: method of my view I draw this image in my whole view. Following is my code.

- (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];
}

但是在屏幕截图中,两点之间的曲线并不平滑。我还在我的信息列表中将抗锯齿渲染设置为是。请看截图。

However in screenshot the curves drawn between two points are not smooth. I've also set the Render with Antialiasing to YES in my info plist. Please see screenshot.

推荐答案

我们必须看看如何构造 UIBezierPath ,但是以我的经验,对于平滑曲线,关键问题是坡度曲线的控制点和该曲线的特定段的端点之间的直线的角度等于曲线的下一个线段的起点与其控制点之间的斜率。我发现使用 addCurveToPoint 而不是 addQuadCurveToPoint 绘制一般平滑曲线比较容易,这样我就可以调整起点和终点控制点可以更普遍地满足此条件。

We'd have to see how you construct the UIBezierPath, but in my experience, for smooth curves, the key issue is whether the slope of the line between a curve's control point and the end point of that particular segment of the curve is equal to the slope between the next segment of the curve's start point and its control point. I find that easier to draw general smoooth curves using addCurveToPoint rather than addQuadCurveToPoint, so that I can adjust the starting and ending control points to satisfy this criterion more generally.

为了说明这一点,我通常绘制 UIBezierPath 曲线的方式是在曲线上具有一系列点,以及曲线在该点处应采取的角度,然后是 addCurveToPoint 控制点的权重(即,距离出控制点应该是)。因此,我使用这些参数来指定 UIBezierPath 的第二个控制点和 UIBezierPath 。因此,例如:

To illustrate this point, the way I usually draw UIBezierPath curves is to have an array of points on the curve, and the angle that the curve should take at that point, and then the "weight" of the addCurveToPoint control points (i.e. how far out the control points should be). Thus, I use those parameters to dictate the second control point of a UIBezierPath and the first controlPoint of the next segment of the UIBezierPath. So, for example:

@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 渲染的图像与通过同时按下物理设备上的电源和主页按钮使用屏幕快照手动捕获的图像进行比较。)


When I render this into a UIImage (using the code below), I don't see any softening of the image, but admittedly the images are not identical. (I'm comparing the image rendered by capture against that which I capture manually with a screen snapshot by pressing power and home buttons on my physical device at the same time.)

如果您看到有所减弱,建议使用 renderInContext (如下所示)。我想知道您是否将图像写为JPG(有损)。

If you're seeing some softening, I would suggest renderInContext (as shown below). I wonder if you writing the image as JPG (which is lossy). Maybe try PNG, if you used JPG.

- (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];
}

这篇关于UIBezierPath正在绘制的视图的屏幕截图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆