带圆角的UIImage

22

我已经阅读了几篇文章,几乎每个人都建议使用QuartzCore/QuartzCore.hlayer.cornerRadius

我尝试过这种方法以及其他一些方法。

当图像不移动时,所有东西都很好用。

但是在我的项目中,我总是会移动我的图像。 如果我添加圆角或阴影,图像的移动就不再流畅。而且看起来很糟糕!

这是我调整图像大小的方法:

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);

我想知道一种良好的方法来调整图像大小、添加阴影、圆角,并仍然使我的图像移动平滑。

7个回答

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();

试着运行这段代码,就我记得,我曾经使用过这个代码来制作一个带有圆角的图片,你可以将它移动到目标位置。但是它似乎可以很好地缩放...


2
做得好!移动流畅又圆润!非常感谢! - iWheelBuy
1
哇 - 我找了很多地方,这是我找到的最简单的解决方案,而且性能非常好。我甚至在UITableViewCell图像中使用它,也没有卡顿。太棒了。 - PapillonUK
嗨,谢谢你的代码。它运行得很好,除了在视网膜屏幕上我的图片质量很差。你有什么线索吗?谢谢! - Spearfisher
3
@ArnaudDrizard 提到,你可以使用 UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, [UIScreen mainScreen].scale); 替代 UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);。这应该可以解决你的问题! - kleo
2
@kleo,你说得很对,你在http://stackoverflow.com/review/suggested-edits/3073006建议的编辑不应该被拒绝。我刚刚实现了这个改变(实际上略有不同,但达到了相同的效果)。很抱歉你没有得到你应得的2点声望。 - Mark Amery
显示剩余2条评论

13

Rohan的回答非常好。如果有人在重构它以使其在他们的项目中起作用时遇到任何问题,这里有一个整洁的重构版本,希望能帮助一些新手程序员:

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

我更喜欢将其作为UIImage的实例方法添加,但重写只需要几秒钟。谢谢! - manmal
这很不错,但是您可以使用bezierPathWithOvalInRect避免圆角,使其完全圆形化。 - mobilemonkey
manmal - 你的意思是创建一个UIImage的子类,然后有一个实例方法将自己变成圆形吗?如果是这样,我真的很喜欢这个想法 :-) - Charlie S
请注意,实际上并不需要使用 UIImageView,因为你所做的只是利用它的边界。你可以轻松地将其替换为 CGRect bounds = CGRectMake(0,0,original.size.width,original.size.height); - devios1

10

有一种更优化的内存版本的 Charlie Seligman 解决方案。您无需使用 UIImageView 来达到此目的。

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

通过将cornerRadius指定为图像大小的两倍(image.size.width * 2),您可以获得圆形图像。


1
我认为使用UIGraphicsBeginImageContextWithOptions(original.size, NO, original.scale);更正确,不是吗? - hyperspasm

2
在您的 .m 文件中导入 #import 后,请尝试以下代码:
  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;

希望这能对您有所帮助...


1

在Objective-C中为图像设置圆角:

yourImageView.layer.cornerRadius = yourRadius;                                   

yourImageView.clipsToBounds = YES;                                 

1
如果在动画图像位置时性能不佳,可能是因为每帧都必须渲染带有圆角的图像。如果图像后面没有实心颜色(每帧的“混合”不同,因此必须计算),这是不可避免的。如果不是这种情况,并且您可以使背景成为实心颜色,请确保将UIView.backgroundColor设置为除clearColor以外的其他颜色,并将alpha设置为1.0。 另外,光栅化图层可能会对您有所帮助(它将在内存中存储已呈现图层的缓存版本,并在整个动画过程中使用该版本。但是,如果图层不是不透明的,则无法帮助)。
以下是如何操作:
UIView *yourView;
CALayer *yourLayer = yourView.layer;

yourLayer.shouldRasterize = YES;
yourLayer.rasterizationScale = [UIScreen mainScreen].scale;

0

是的,这是可能的。

导入QuartzCore(#import)头文件并使用UIImageView的layer属性进行操作。

ImageView.layer.cornerRadius = Radius;
ImageView.clipsToBounds = YES;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接