6
votes

I have a CATiledLayer into which I render content in the following method

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

I used the QuartzDemo code to draw a pattern. This works very well until I apply a rotation transform to the layer's parentLayer (a UIView):

Non-Rotated CATiledLayer

rotated:

Rotated CATiledLayer

These zigzag artefacts become worse when I start drawing lines and texts into the CATiledLayer.

I applied the transform as follows (I also tried using an affine transform on the view itself):

self.containerView.layer.transform = CATransform3DMakeRotation(angleRadians, 0.0f, 0.0f, 1.0f);

I transform the containerView rather than the layer itself, as I have several layers in that view that I would like to rotate at the same time without changing the relative positions.

I did not have problems when rotating UIImageViews in the past.

Is there a way that I can rotate the CATiledLayer without these problems?

Any help would be greatly appreciated.

Yours,

Felix

3

3 Answers

3
votes

The only way of fixing this issue I found was this:

  1. Draw the layer into a bitmap context
  2. Set the CGImageRef of that context as the layer contents
2
votes

Anti-aliasing in OpenGL is often expensive and thus is disabled for Core Animation on iOS since processing resources are limited. The keyword here is speed: Core Animation is optimized for speed of drawing which translates to smoothness of animation. If image quality is the priority, you should not use Core Animation with rotational transforms.

For some tasks in Core Animation, you can add a 1 px border around your layer content. Without anti-aliasing, edges will be jagged but when the content is not on an edge, it is not affected by this and will instead be smoothed out because of texture filtering.

1
votes

As Ryan Zachry has already pointed out, anti-aliasing will help you here. The effect you are experiencing here is the "stairs"-effect.

Pixels are square, so it is easy to draw straight lines (horizontally or vertically) without producing any artifacts. If you're drawing lines at an angle, you will need to rasterize your line. An algorithm for line drawing will need to make approximations when trying to map your line to the pixels. An example for such an algorithm is Bresenham's (very popular and easy to implement but does not feature anti-aliasing). Here's what it does:

From wikipedia

As you can see very clear in this picture, drawing a line at any angle results in the so-called stairs-effect. To avoid this effect you can use anti-aliasing. Anti-aliasing is actually a part of signal theory. It is the technique of minimizing the distortion artifacts known as aliasing when representing a high-resolution signal at a lower resolution. As you can see from the line example above, this applies very well to computer graphics.

Anti-aliasing is really complicated, but the idea is to enhance the picture by approximating the line not only on a per-pixel basis but also to use intelligent coloring to make the line appear at a certain location that is not pixel-exact.

From Wikipedia

To enable built-in anti-aliasing in Core Graphics, do the following before performing your rotation:

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

Note that anti-aliasing can be very expensive in terms of processing power, you should only use it when necessary.