如何在iOS中将方形图像蒙版成圆角图像?

时间:2009-06-15 14:02:20

标签: ios graphics uiimage

如何将方形图像蒙版成圆角图像?

8 个答案:

答案 0 :(得分:67)

您可以使用CoreGraphics为此代码段创建圆角矩形的路径:

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
{
    float fw, fh;
    if (ovalWidth == 0 || ovalHeight == 0) {
        CGContextAddRect(context, rect);
        return;
    }
    CGContextSaveGState(context);
    CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
    CGContextScaleCTM (context, ovalWidth, ovalHeight);
    fw = CGRectGetWidth (rect) / ovalWidth;
    fh = CGRectGetHeight (rect) / ovalHeight;
    CGContextMoveToPoint(context, fw, fh/2);
    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
    CGContextClosePath(context);
    CGContextRestoreGState(context);
}

然后调用CGContextClip(context);将其剪辑到矩形路径。现在,任何完成的绘图(包括绘制图像)都将被剪裁为圆角矩形。

举个例子,假设“image”是一个UIImage,这是在drawRect:方法:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
addRoundedRectToPath(context, self.frame, 10, 10);
CGContextClip(context);
[image drawInRect:self.frame];
CGContextRestoreGState(context);

答案 1 :(得分:34)

这是iPhone 3.0及更高版本中提供的更简单的方法。每个基于视图的对象都有一个关联的图层。每个图层都可以设置一个圆角半径,这将为您提供所需的内容:

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * layer = [roundedView layer];
[layer setMasksToBounds:YES];
[layer setCornerRadius:10.0];

// You can even add a border
[layer setBorderWidth:4.0];
[layer setBorderColor:[[UIColor blueColor] CGColor]];

要使用这些方法,您可能需要添加:

#import <QuartzCore/QuartzCore.h>

答案 2 :(得分:15)

我意识到这是旧闻,但只是把它煮了一点:

这里有两个可能的问题:(1)如何将圆角应用于将在屏幕上显示的UIView(例如UIImageView),以及(2)我如何掩盖正方形图像(即UIImage)以生成带圆角的新图像。

对于(1),最简单的方法是使用CoreAnimation并设置view.layer.cornerRadius属性

 // Because we're using CoreAnimation, we must include QuartzCore.h
 // and link QuartzCore.framework in a build phases 
 #import <QuartzCore/QuartzCore.h> 

 // start with an image 
 UIImage * fooImage = [UIImage imageNamed:@"foo.png"];
 // put it in a UIImageView
 UIView * view = [UIImageView alloc] initWithImage:fooImage];
 // round its corners. This mask now applies to the view's layer's *background*
 view.layer.cornerRadius = 10.f
 // enable masksToBounds, so the mask applies to its foreground, the image
 view.layer.masksToBounds = YES;

对于(2),最好的方法是使用UIKit图形操作:

// start with an image 
UIImage * fooImage = [UIImage imageNamed:@"foo.png"];
CGRect imageRect = CGRectMake(0, 0, fooImage.size.width, fooImage.size.height);
// set the implicit graphics context ("canvas") to a bitmap context for images
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0);
// create a bezier path defining rounded corners
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:10.f];
// use this path for clipping in the implicit context
[path addClip];
// draw the image into the implicit context
[fooImage drawInRect:imageRect];
// save the clipped image from the implicit context into an image 
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
// cleanup
UIGraphicsEndImageContext();

问题(2)的棘手之处在于您可能认为可以使用CoreAnimation中的view.layer.mask属性执行整个操作。但是你不能因为CALayer renderInContext:方法,你用来从被遮罩的层生成UIImage,似乎忽略了掩码。更糟糕的是,renderInContext:的文档没有提到这一点,只暗示了OSX 10.5的行为。

进一步的上下文:(2)的上述方法是使用UIKit围绕更基本的CoreGraphics功能的包装器。您可以直接使用CoreGraphics调用执行相同的操作 - 这就是所选答案正在执行的操作 - 但是您需要从曲线和线手动构建圆角rect bezier路径,并且还需要补偿CoreGraphics使用的事实绘制坐标系统,相对于UIKit的翻转。

答案 3 :(得分:2)

查看此帖 - 非常简单的答案

How to set round corners in UI images in iphone

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * l = [roundedView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];

答案 4 :(得分:1)

很简单。     self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width / 2;     self.profileImageView.clipsToBounds = YES;

对于每个视图,都有一个捆绑的图层属性。所以上面的第一行是设置图层对象的角半径(即CALayer类的一个实例)。要从平方图像制作圆形图像,半径设置为UIImageView宽度的一半。例如,如果平方图像的宽度是100像素。半径设置为50像素。其次,您必须将clipsToBounds属性设置为YES才能使图层正常工作。

答案 5 :(得分:0)

两种方法都有效,但差异显示取决于您使用它的位置。

对于Ex:如果您有一个表格视图,其中单元格显示图像以及其他标签等,并且您使用图层来设置cornerRadius,则滚动会受到很大影响。它变得生涩。

当我在表格视图单元格中使用Layer作为图像时,我遇到了这个问题,并且试图找出这种急躁的原因,却发现CALayer是罪魁祸首。

在NilObject解释的drawRect中使用了第一个解决问题的方法。这就像一个滚动光滑如丝的魅力。

另一方面,如果你想在popover视图等静态视图中使用它,那么layer是最简单的方法。

正如我所说,这两种方法都很有效,只需根据你想要使用它的位置来决定。

答案 6 :(得分:0)

我使用这种方法。

+ (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size;
    {
      UIImage *img = nil;


        CGRect rect = CGRectMake(0, 0, size.width, size.height);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context,
                                     color.CGColor);
        CGContextFillRect(context, rect);
        img = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();


      return img;
    }

答案 7 :(得分:0)

建立algal,这里有几个方法很适合放入UIImage类:


- (UIImage *) roundedCornerImageWithRadius:(CGFloat)radius
{
    CGRect imageRect = CGRectMake(0, 0, self.size.width, self.size.height);
    UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0); //scale 0 yields better results

    //create a bezier path defining rounded corners and use it for clippping
    UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:radius];
    [path addClip];

    // draw the image into the implicit context
    [self drawInRect:imageRect];

    // get image and cleanup
    UIImage *roundedCornerImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return roundedCornerImage;
}

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size andCornerRadius:(CGFloat)radius
{
    UIImage *image = nil;
    if (size.width == 0 || size.height == 0) {
        size = CGSizeMake(1.0, 1.0);
    }
    CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
    UIGraphicsBeginImageContextWithOptions(rect.size,NO,0.0); //yields sharper results than UIGraphicsBeginImageContext(rect.size)
    CGContextRef context = UIGraphicsGetCurrentContext();
    if (context)
    {
        CGContextSetFillColorWithColor(context, [color CGColor]);
        if (radius > 0.0) {
            //create a bezier path defining rounded corners and use it for clippping
            UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
            [path addClip];
            CGContextAddPath(context, path.CGPath);
        }
        CGContextFillRect(context, rect);
        image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }
    return image;
}