iPhone - Jagged Edges when applying perspective to

2019-02-07 04:51发布

问题:

I have a CALayer that I apply a perspective to using a CGTransform3D and specifying the m14 property. When the perspective is applied, the layer has jagged edges. I've heard people mention that adding a 1px transparent border around the layer will help with this. I don't know how to do that. I have tried using the border and borderWidth properties of a CALayer but the jagged edges are still there. I also tried to reduce the rect that is drawn by 1px on all sides, but it doesn't help either.

Any help would be great! Thanks!

回答1:

By "I've heard people mention," I assume you mean the discussion on this question. What was suggested there was to actually draw the content in your CALayer so that it has a one-pixel transparent border outside of the core content, using the code

CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

within your Quartz drawing for that layer.

There's also the edgeAntialiasingMask property on CALayer, but I've seen no impact when using code like the following:

layer.edgeAntialiasingMask = kCALayerLeftEdge | kCALayerRightEdge | kCALayerBottomEdge | kCALayerTopEdge;

on the antialiasing of transformed layer edges. See also this question for discussion of this, as well as how they solved their problem using one-pixel transparent borders around their images.



回答2:

The best solution I found for this issue was to set shouldRasterize to YES and set the rasterization scale to the scale of the device's screen.

myLayer.shouldRasterize = YES;
myLayer.rasterizationScale = UIScreen.mainScreen().scale // iOS
myLayer.rasterizationScale = NSScreen.mainScreen()!.backingScaleFactor // OSX

That will in turn smooth out the edges for you.



回答3:

Give your CALayer a mask that's inset 0.5 px from each edge:

UIView *aliasedView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];

CALayer *maskLayer = [[CALayer alloc] init];
maskLayer.frame = CGRectMake(0.5, 0.5, width-1, height-1);
maskLayer.backgroundColor = [UIColor whiteColor].CGColor;

aliasedView.layer.mask = maskLayer;


回答4:

A one pixel border smooths the edges of the content (!) of a layer:

- (UIImage *)drawAntiAliased:(UIImage *)image
{
    const int B = 1; // Border width (anti-aliasing)

    // Size of the output image
    CGSize newImageSize = CGSizeMake(image.size.width + 2 * B, image.size.height + 2 * B);

    UIGraphicsBeginImageContextWithOptions(newImageSize, NO, 0);

    // Draw image with edge anti-aliasing
    [image drawInRect:(CGRect){B, B, image.size}];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

If you want to use the border properties of the layer, this does no longer work, because the border is not part of the contents of the layer and is not affected by the smoothing.

Setting shouldRasterize on the other hand affects both the content and the borders.



回答5:

In Swift 3.0:

context.setAllowsAntialiasing(true)
context.setShouldAntialias(true)