I've got a UIImageView (full frame and rectangular) that i'm rotating with a CGAffineTransform. The UIImage of the UIImageView fills the entire frame. When the image is rotated and drawn the edges appear noticeably jagged. Is there anything I can do to make it look better? It's clearly not being anti-aliased with the background.

- 95,783
- 15
- 211
- 370

- 37,979
- 50
- 195
- 293
-
Is the image being internally anti-aliased -- is it just the edges that are jagged or the whole thing? BTW I would recommend using a CALayer if possible. – hatfinch Jul 16 '09 at 09:32
-
It's for the iPhone so I believe it's already CALayer backed. – Meltemi Jul 16 '09 at 17:27
-
Indeed, but why carry all the UIView/UIResponder baggage if you don't need to? – hatfinch Jul 16 '09 at 21:27
-
well, in my case they need to views need to register touches – Meltemi Jul 23 '09 at 00:21
-
and only the edges are jagged... image itself is anti-aliasing just fine. – Meltemi Jul 23 '09 at 01:56
-
Check out Johan Kool's answer... very simple, and worked like a charm! – Alex Zak Jan 02 '12 at 23:16
8 Answers
The edges of CoreAnimation layers aren't antialiased by default on iOS. However, there is a key that you can set in Info.plist that enables antialiasing of the edges: UIViewEdgeAntialiasing.
If you don't want the performance overhead of enabling this option, a work-around is to add a 1px transparent border around the edge of the image. This means that the 'edges' of the image are no longer on the edge, so don't need special treatment!

- 37,241
- 25
- 195
- 267

- 15,637
- 8
- 64
- 81
-
2
-
1
-
-
@MathieuGodart Not tested myself, as it functioned well enough for me where I needed it. Use Instruments to figure out how much it impacts performance for you. Of course, Apple turns this off by default for a reason. – Johan Kool Apr 27 '12 at 15:56
-
I noticed that setting UIViewEdgeAntialiasing to YES in the Info.plist file is messing with all `UIAlertView`'s corners. – Kevin Hirsch Nov 19 '15 at 11:02
New API – iOS 6/7
Also works for iOS 6, as noted by @Chris, but wasn't made public until iOS 7.
Since iOS 7, CALayer has a new property allowsEdgeAntialiasing
which does exactly what you want in this case, without incurring the overhead of enabling it for all views in your application! This is a property of CALayer, so to enable this for a UIView you use myView.layer.allowsEdgeAntialiasing = YES
.

- 7,317
- 3
- 39
- 39
-
This is a great API. Note that it also works on iOS 6 (though apparently was only added/enabled in the iOS 7 SDK). – Chris Mar 04 '14 at 01:41
-
just add 1px transparent border to your image
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0.0);
[image drawInRect:CGRectMake(1,1,image.size.width-2,image.size.height-2)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
-
works great here too. fyi: simpler inset calc: CGRectInset(imageRect, 1.0, 1.0) – mattorb May 10 '13 at 14:22
Remember to set the appropriate anti-alias options:
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

- 15,481
- 4
- 49
- 55
-
I'm not seeing any difference when adding these Antialiasing lines to enclosing the UIImageView's drawRect...as well as the enclosing superview's. Even tried: CGContextSetInterpolationQuality(context, kCGInterpolationHigh); to no avail... When the UIImageView rect gets transformed (rotated) the edges are always jaggy.. – Meltemi Nov 04 '09 at 09:03
-
5Best way to solve that problem is by adding a 1px transparent border to your image prior to rotation. – Nathan de Vries Nov 04 '09 at 11:48
-
How would you add the transparent border? I'm have the same issue while rotating a CALayer with perspective. – Brian Apr 23 '10 at 18:01
-
2Could someone provide a tip on this 1px transparent border trick? I've set a UIView's layer.borderColor and layer.borderWidth, but it does not fix it for me. – akaru Feb 08 '11 at 06:07
-
My image was coming via glReadPixels (OpenGL ES frame buffer capture) so I was able to set alpha on the RGBA memory buffer directly. For those also in this situation make sure you don't use premultiplied in your CGImageCreate call (ie I supplied kCGImageAlphaLast | kCGBitmapByteOrder32Big for CGBitmapInfo). – Quintin Willison Jul 21 '11 at 15:36
-
Explanation why the 1px transparent pixel fixes the problem: the jagged line is the edge of the polygon that Cocoa draws there and since your texture has colors to the edge it can't be anti-aliased. The image inside the edges is anti-aliased though. – Dimitris Sep 15 '11 at 14:33
-
This is besides the problem. The problem is in CALayer space, and not CGContext drawing space. – monkeydom May 16 '12 at 09:42
-
just add "Renders with edge antialiasing" with YES in plist and it will work.

- 5,020
- 4
- 49
- 75
I would totally recommend the following library.
http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/
It contains lots of useful extensions to UIImage that solve this problem and also include code for generating thumbnails etc.
Enjoy!

- 1,647
- 3
- 16
- 19
The best way I've found to have smooth edges and a sharp image is to do this:
CGRect imageRect = CGRectMake(0, 0, self.photo.image.size.width, self.photo.image.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0.0);
[self.photo.image drawInRect:CGRectMake(1, 1, self.photo.image.size.width - 2, self.photo.image.size.height - 2)];
self.photo.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Adding the Info.plist key like some people describe has a big hit on performance and if you use that then you're basically applying it to everything instead of just the one place you need it.
Also, don't just use UIGraphicsBeginImageContext(imageRect.size);
otherwise the layer will be blurry. You have to use UIGraphicsBeginImageContextWithOptions
like I've shown.

- 46,496
- 21
- 150
- 195
-
1This is a great point regarding **UIGraphicsBeginImageContextWithOptions** .. usually you have to set the **opaque option to NO**. I was drawing lines (ie, lines on a transparent bg), and then using renderInContext to draw the image of the lines, into, an existing photo. **Of course, it's critical to use opaque "NO".** So, this was very obvious to me - after iWasRobbed told me about it :) Thanks, robbed! :) – Fattie Dec 18 '13 at 10:21
I found this solution from here, and it's perfect:
+ (UIImage *)renderImageFromView:(UIView *)view withRect:(CGRect)frame transparentInsets:(UIEdgeInsets)insets {
CGSize imageSizeWithBorder = CGSizeMake(frame.size.width + insets.left + insets.right, frame.size.height + insets.top + insets.bottom);
// Create a new context of the desired size to render the image
UIGraphicsBeginImageContextWithOptions(imageSizeWithBorder, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
// Clip the context to the portion of the view we will draw
CGContextClipToRect(context, (CGRect){{insets.left, insets.top}, frame.size});
// Translate it, to the desired position
CGContextTranslateCTM(context, -frame.origin.x + insets.left, -frame.origin.y + insets.top);
// Render the view as image
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
// Fetch the image
UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
// Cleanup
UIGraphicsEndImageContext();
return renderedImage;
}
usage:
UIImage *image = [UIImage renderImageFromView:view withRect:view.bounds transparentInsets:UIEdgeInsetsZero];

- 582
- 7
- 8