22

I have read several posts already. And almost everyone suggest using QuartzCore/QuartzCore.h with layer.cornerRadius

I have tried this method and some more methods.

Well, everything works fine when an image doesn't move.

But in my project I always move my images. If I add corner radius or a shadow the image movement is no longer smooth. And it looks aweful!

That is the way I resize my image:

CGSize newSize = CGSizeMake(200*height/image.size.height, 280);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(nil, newSize.width, newSize.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGContextClearRect(context, CGRectMake(0, 0, newSize.width, newSize.height));
CGContextDrawImage(context, CGRectMake(0, 0, newSize.width, newSize.height), image.CGImage);
CGImageRef scaledImage = CGBitmapContextCreateImage(context);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
UIImage *newImage = [UIImage imageWithCGImage: scaledImage];
CGImageRelease(scaledImage);

I would like to know a good way to resize my image, add shadow, corner radius and still have smooth movement of my image.

iWheelBuy
  • 5,470
  • 2
  • 37
  • 71

7 Answers7

72
// Get your image somehow
UIImage *image = [UIImage imageNamed:@"image.jpg"];

// Begin a new image that will be the new image with the rounded corners 
// (here with the size of an UIImageView)
 UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, [UIScreen mainScreen].scale);

 // Add a clip before drawing anything, in the shape of an rounded rect
  [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds 
                        cornerRadius:10.0] addClip];
 // Draw your image
[image drawInRect:imageView.bounds];

 // Get the image, here setting the UIImageView image
  imageView.image = UIGraphicsGetImageFromCurrentImageContext();

 // Lets forget about that we were drawing
  UIGraphicsEndImageContext();

Try moving with this code, as far as I can remember I used this a while back that makes an image with rounded corners that you can move around into the targets. But it seemed to scale fine...

James Kuang
  • 10,710
  • 4
  • 28
  • 38
MCKapur
  • 9,127
  • 9
  • 58
  • 101
  • 2
    Great job! Rounded + smooth movement! Thanks a lot! – iWheelBuy May 12 '12 at 13:32
  • 1
    Wow - i've looked all over and this is the simplest solution i've found which is still very very performant. I've even used it in a UITableViewCell image without stuttering. Brilliant. – PapillonUK Aug 22 '12 at 21:56
  • Hi, thanks for the code. It works great except that on retina screen my pictures get a bad quality. Do you have any clue why? Thanks! – Spearfisher Sep 12 '13 at 10:24
  • 3
    @ArnaudDrizard: Instead of `UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);` you can use `UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, [UIScreen mainScreen].scale);`. This should fix your problem! – kleo Oct 05 '13 at 19:23
  • 2
    @kleo You are quite correct, and your suggested edit at http://stackoverflow.com/review/suggested-edits/3073006 should not have been rejected. I've just implemented the change (actually in a slightly different way, but it achieves the same result). Sorry that you didn't get the 2 rep you deserved. – Mark Amery Oct 05 '13 at 20:00
  • @kleo Huh, sorry it was rejected, that wasn't me. I'll edit it now. – MCKapur Oct 06 '13 at 00:24
  • Great answer, thanks so much! I had to massage it a little bit to get it working in Swift. This gist contains the code I used to get it working: https://gist.github.com/bitops/11c0d7c1a5546473c7c7 – bitops Jul 19 '14 at 06:32
13

Rohan's answer is a great one. If anyone is having any probs refactoring it to work in their projects here is a neat refactor that might hopefully help some newer programmers:

+ (UIImage *)imageWithRoundedCornersSize:(float)cornerRadius usingImage:(UIImage *)original
{    
    UIImageView *imageView = [[UIImageView alloc] initWithImage:original];

    // Begin a new image that will be the new image with the rounded corners
    // (here with the size of an UIImageView)
    UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);

    // Add a clip before drawing anything, in the shape of an rounded rect
    [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds
                            cornerRadius:cornerRadius] addClip];
    // Draw your image
    [original drawInRect:imageView.bounds];

    // Get the image, here setting the UIImageView image
    imageView.image = UIGraphicsGetImageFromCurrentImageContext();

    // Lets forget about that we were drawing
    UIGraphicsEndImageContext();

    return imageView.image;
}
Charlie S
  • 4,366
  • 6
  • 59
  • 97
  • I prefer to add this as an instance method on UIImage, but rewriting it was only a matter of seconds. Thanks! – manmal Oct 01 '13 at 15:59
  • This is good, but you can avoid the corner radius and make it completely round using bezierPathWithOvalInRect. – mobilemonkey Jan 21 '14 at 19:31
  • manmal - do you mean you create a subclass of UIImage and then have an instance method that makes self into a circle? If so, really like that idea :-) – Charlie S Jan 22 '14 at 22:12
  • Note that the use of a `UIImageView` is actually not necessary as all you're doing with it is using it for its bounds. You can easily replace this with `CGRect bounds = CGRectMake(0,0,original.size.width,original.size.height);`. – devios1 Aug 19 '14 at 20:39
10

There is more optimized memory version of solution of Charlie Seligman. You do not need use UIImageView for this purpose.

+ (UIImage *)imageWithRoundedCornersSize:(float)cornerRadius usingImage:(UIImage *)original
{
    CGRect frame = CGRectMake(0, 0, original.size.width, original.size.height);

    // Begin a new image that will be the new image with the rounded corners
    // (here with the size of an UIImageView)
    UIGraphicsBeginImageContextWithOptions(original.size, NO, original.scale);

    // Add a clip before drawing anything, in the shape of an rounded rect
    [[UIBezierPath bezierPathWithRoundedRect:frame
                                cornerRadius:cornerRadius] addClip];
    // Draw your image
    [original drawInRect:frame];

    // Get the image, here setting the UIImageView image
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    // Lets forget about that we were drawing
    UIGraphicsEndImageContext();

    return image;
}

You can get the round image by specifying cornerRadius equal increased image size twice (image.size.width * 2).

alexmorhun
  • 1,903
  • 2
  • 18
  • 23
  • 1
    I think it's more correct to use `UIGraphicsBeginImageContextWithOptions(original.size, NO, original.scale);` no? – hyperspasm Dec 01 '14 at 03:42
2

try bellow code after import the file #import in your .m file

  yourImageView.layer.shadowColor=[[UIColor grayColor] CGColor];
  yourImageView.layer.cornerRadius = 8;
  yourImageView.layer.shadowOffset=CGSizeMake(2, 2);
  yourImageView.layer.shadowOpacity=1.0;
  yourImageView.layer.shadowRadius=1.0;

Hope ,this help you....

Paras Joshi
  • 20,427
  • 11
  • 57
  • 70
1

If perfomance is bad when animating the image position, it's probably because it's having to render the image with the corner radius every frame. This is inevitable if behind the image there's not a solid color (the "blending" is different in each frame, and thus has to be calculated). If this is not the case, and you can get the background to be of a solid color, make sure you set the UIView.backgroundColor to something other than clearColor, with an alpha 1.0. Also rasterizing the layer might help you (it will store the a cached version of the rendered layer in memory and use that throughout the animation. But again, won't help if the layer is not opaque).

This is how you do this:

UIView *yourView;
CALayer *yourLayer = yourView.layer;

yourLayer.shouldRasterize = YES;
yourLayer.rasterizationScale = [UIScreen mainScreen].scale;
Javier Soto
  • 4,840
  • 4
  • 26
  • 46
1

Set rounded corners on an image in Objective-C:

yourImageView.layer.cornerRadius = yourRadius;                                   

yourImageView.clipsToBounds = YES;                                 
JAL
  • 41,701
  • 23
  • 172
  • 300
0

Yes, it is possible.

Import the QuartzCore (#import ) header and play with the layer property of the UIImageView.

ImageView.layer.cornerRadius = Radius;
ImageView.clipsToBounds = YES;
Dixit Patel
  • 205
  • 2
  • 16