ios 如何在iOS中将方形图像屏蔽为带有圆角的图像?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/996292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:02:10  来源:igfitidea点击:

How to mask a square image into an image with round corners in iOS?

iosgraphicsuiimage

提问by erotsppa

How can you mask a square image into an image with round corners?

如何将方形图像屏蔽为带有圆角的图像?

回答by NilObject

You can use CoreGraphics to create a path for a round rectangle with this code snippet:

您可以使用 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);
}

And then call CGContextClip(context); to clip it to the rectangle path. Now any drawing done, including drawing an image, will be clipped to the round rectangle shape.

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

As an example, assuming "image" is a UIImage, and this is in a drawRect: method:

例如,假设“图像”是一个 UIImage,这是在 drawRect: 方法中:

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

回答by MagicSeth

Here is an even easier method that is available in iPhone 3.0 and up. Every View-based object has an associated layer. Each layer can have a corner radius set, this will give you just what you want:

这是一种更简单的方法,适用于 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]];

To use these methods you might need to add:

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

#import <QuartzCore/QuartzCore.h>

回答by algal

I realize this is old news but just to boil it down a bit:

我意识到这是旧消息,但只是将其归结为:

There are twopossible questions here: (1) how do I apply rounded corners to a UIView (such as a UIImageView), which will be displayed on screen, and (2) how do I mask a square image (that is, a UIImage) to produce a new image with rounded corners.

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

For (1), the easiest course is to use CoreAnimation and set the view.layer.cornerRadius property

对于(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;

For (2), the best way is to use the UIKit graphics operations:

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

What's tricky about problem (2) is that you might think you could do the whole operation using the view.layer.mask property in CoreAnimation. But you can't because the CALayer renderInContext:method, which you'd use to generate a UIImage from the masked layer, seems to ignore the mask. Worse, the documentation for renderInContext:doesn't mention this, and only alludes to the behavior for OSX 10.5.

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

Some further context: the above approach to (2) is using UIKit's wrappers around more basic CoreGraphics functionality. You can do the same thing using the CoreGraphics calls directly – that is what the chosen answer is doing -- but then you need build the rounded rect bezier path manually from curves and lines and you also need to compensate for the fact that CoreGraphics uses a drawing coordinate system which is flipped with respect to UIKit's.

一些进一步的背景:上述(2)的方法是使用 UIKit 的包装器围绕更基本的 CoreGraphics 功能。您可以直接使用 CoreGraphics 调用来做同样的事情——这就是所选择的答案正在做的事情——但是你需要从曲线和直线手动构建圆角矩形贝塞尔曲线,并且你还需要补偿 CoreGraphics 使用相对于 UIKit 翻转的绘图坐标系。

回答by GAL

See this Post - Very simple answer

看到这个帖子 - 非常简单的答案

How to set round corners in UI images in iphone

如何在iphone的UI图像中设置圆角

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

回答by Shahab Qureshi

Very simple. self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width / 2; self.profileImageView.clipsToBounds = YES;

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

For every view, there is a bundled layer property. So the first line of the above is to set the corner radius of the layer object (i.e. an instance of CALayer class). To make a circular image from a squared image, the radius is set to the half of the width of UIImageView. For instance, if the width of squared image is 100 pixels. The radius is set to 50 pixels. Secondly, you have to set the clipsToBounds property to YES in order to make the layer works.

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

回答by n8tr

Building off of algal, here are a couple methods that are nice to put in an UIImage category:

建立在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;
}

回答by Deepak G M

Both the methods work but the differences shows up depending on where you use it.

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

For Ex: If you have a table view with the cells showing an image along with other labels, etc., and you use layer to set the cornerRadius, the scrolling will take a big hit. It gets jerky.

例如:如果您有一个表格视图,其中的单元格显示图像以及其他标签等,并且您使用图层设置角半径,滚动将受到很大影响。它变得生涩。

I faced this issue when I was using Layer for an image in a table view cell and was trying to figure out the cause of that jerkiness only to find that CALayer was the culprit.

当我在表格视图单元格中将图层用于图像时,我遇到了这个问题,并试图找出这种颠簸的原因,却发现 CALayer 是罪魁祸首。

Used the first solution of doing the stuff in drawRect explained by NilObject. That works like a charm with scrolling being smooth as silk.

使用了 NilObject 解释的在 drawRect 中做东西的第一个解决方案。这就像一个魅力,滚动像丝绸一样光滑。

On the other hand, if you want to use this in static views like popover view, etc., layer is the easiest way to do it.

另一方面,如果您想在弹出视图等静态视图中使用它,图层是最简单的方法。

As I said, both the methods work well just that you need to decide based on where you want to use it.

正如我所说,这两种方法都可以很好地工作,只是您需要根据要使用它的位置来决定。

回答by Voda Ion

I use this method.

我用这个方法。

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