【问题标题】:Making a UIImage to a circle form将 UIImage 制作成圆形
【发布时间】:2011-11-15 23:50:57
【问题描述】:

我一直在尝试将 UIImage 遮盖成一个圆圈。 我现在在这里使用在其他答案中很流行的代码,但是虽然我确实得到了一个圆圈,但它的边缘非常锯齿并且不平滑。 任何人都可以帮忙吗?我能得到一个完美、光滑的圆圈吗?

我用来创建掩码的代码是:

  (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {

    CGImageRef imageNoAlpha = image.CGImage;

    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();

    CGFloat width = CGImageGetWidth(imageNoAlpha);
    CGFloat height = CGImageGetWidth(imageNoAlpha);

    CGContextRef ctxWithAlpha = CGBitmapContextCreate(nil, width, height, 8, 4*width, cs, kCGImageAlphaPremultipliedFirst);

    CGContextDrawImage(ctxWithAlpha, CGRectMake(0, 0, width, height), imageNoAlpha);

    CGImageRef imageWithAlpha = CGBitmapContextCreateImage(ctxWithAlpha);

    CGImageRef maskRef = maskImage.CGImage; 

    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                        CGImageGetHeight(maskRef),
                                        CGImageGetBitsPerComponent(maskRef),
                                        CGImageGetBitsPerPixel(maskRef),
                                        CGImageGetBytesPerRow(maskRef),
                                        CGImageGetDataProvider(maskRef), NULL, false);

    CGImageRef masked = CGImageCreateWithMask(imageWithAlpha, mask);

    UIImage* retImage= [UIImage imageWithCGImage:masked];
    UIImage* retImageFixed = [retImage transparentBorderImage:1];

    CGImageRelease(mask);
    CGImageRelease(masked);
    CGImageRelease(imageWithAlpha);
    CGContextRelease(ctxWithAlpha);
    CGColorSpaceRelease(cs);

    return retImageFixed;

提前谢谢...

【问题讨论】:

标签: iphone objective-c xcode uiimageview uiimage


【解决方案1】:

这可能会对您有所帮助,将角半径作为您要显示图像的参考视图的一半传递,或者您可以设置自定义矩形,

例如。在我的情况下,我想在 "imageView" 上显示图像,因此在这种情况下角半径将是 imageView.frame.size.width/2

- (void)displayImage
{
    imageView.image = [self getRoundedRectImageFromImage:@"Test.png" onReferenceView:imageView withCornerRadius: imageView.frame.size.width/2];
}



- (UIImage *)getRoundedRectImageFromImage :(UIImage *)image onReferenceView :(UIImageView*)imageView withCornerRadius :(float)cornerRadius
{
    UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);
    [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds
                                cornerRadius:cornerRadius] addClip];
    [image drawInRect:imageView.bounds];
    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return finalImage;
}

【讨论】:

  • UIGraphicsBeginImageContextWithOptions 中的第三个参数必须是 0.0 而不是 1.0。因为1.0画的很丑
  • @fnc12 谢谢!我想知道为什么结果模糊而丑陋。
【解决方案2】:

试试这个代码

yourImageView.layer.cornerRadius = yourImageView.frame.size.height /2;
yourImageView.layer.masksToBounds = YES;
yourImageView.layer.borderWidth = 0;

此显示图像类似于 ios 7 圆形图像,谢谢

【讨论】:

  • 仅供参考,此解决方案使表格视图中的滚动变慢。 @aToz 的解决方案效果很好。
  • 它在 tableView 滚动中完美运行,我看不出有任何问题,我的 tableView 包含 246 行,每行从服务器加载图像并且仍然完美运行
  • @aLFaRSi 你在运行什么类型的设备?表现不佳的代码并不总是一开始就表现出来。两种方法都可能有理论证明或基准。
  • @alFaRSi。你很幸运;)
  • 这是使用UIImageView,而主题开始者要求使用带有UIImage的圆圈。
【解决方案3】:

抱歉,格式很丑。 aToz 答案的更好版本。

@interface UIImage (CircleMask)

+ (UIImage *)roundedRectImageFromImage :(UIImage *)image
                                  size :(CGSize)imageSize
                      withCornerRadius :(float)cornerRadius;

@end

@implementation UIImage(CircleMask)

+(UIImage*)roundedRectImageFromImage:(UIImage *)image
                                size:(CGSize)imageSize
                    withCornerRadius:(float)cornerRadius
{
    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);   //  <= notice 0.0 as third scale parameter. It is important cause default draw scale ≠ 1.0. Try 1.0 - it will draw an ugly image..
    CGRect bounds = (CGRect){CGPointZero,imageSize};
    [[UIBezierPath bezierPathWithRoundedRect:bounds
                                cornerRadius:cornerRadius] addClip];
    [image drawInRect:bounds];
    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return finalImage;
}

@end

在 Swift 中也是如此:

extension UIImage{

    class func roundedRectImageFromImage(image:UIImage,imageSize:CGSize,cornerRadius:CGFloat)->UIImage{
        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0.0)
        let bounds = CGRect(origin: CGPointZero, size: imageSize)
        UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).addClip()
        image.drawInRect(bounds)
        let finalImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return finalImage
    }
    
}

【讨论】:

  • CGPointZero 已弃用,请改用:CGRect(origin: .zero, size: imageSize)。
【解决方案4】:

如果您使用的是UIImageView,并且希望在保持圆角的同时为图像大小设置动画,您可以应用如下变换:

Objective-C

// Our UIImageView reference
@property (weak, nonatomic) IBOutlet UIImageView *myImageView;

- (void)viewDidLoad {
    [super viewDidLoad];

     myImageView.layer.cornerRadius = myImageView.frame.size.width / 2.0f;
     myImageView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.4f, 0.4f);
}

- (void)viewDidAppear:(BOOL)animated {
    [UIView animateWithDuration:1.0 animations:^{
        myImageView.transform = CGAffineTransformIdentity;
    }];
}

斯威夫特

// Our UIImageView reference
@IBOutlet weak var myImageView:UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()

    myImageView.layer.cornerRadius = myImageView.frame.size.width / 2;
    myImageView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.4, 0.4)
}

override func viewDidAppear(animated: Bool) {
    UIView.animateWithDuration(1.0) {
        myImageView.transform = CGAffineTransformIdentity;
    }
}

注意:这也将维护任何 AutoLayout constraints

【讨论】:

    【解决方案5】:

    aToz 和 fnc12 答案的更好版本(在 Swift 中):

    extension UIImage
    {
        func roundImage() -> UIImage
        {
            let newImage = self.copy() as! UIImage
            let cornerRadius = self.size.height/2
            UIGraphicsBeginImageContextWithOptions(self.size, false, 1.0)
            let bounds = CGRect(origin: CGPointZero, size: self.size)
            UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).addClip()
            newImage.drawInRect(bounds)
            let finalImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return finalImage
        }
    }
    

    用法:

    self.userImageView.image = image.roundedImage()
    

    【讨论】:

    • 我们可以对非方形图像进行裁剪和舍入吗?
    【解决方案6】:

    我用 UIBezierPath

    解决了我的问题
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:yourImageView.bounds];
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.path = path.CGPath;
    yourImageView.layer.mask = maskLayer;
    

    【讨论】:

      【解决方案7】:

      如何从 UIImageView 获得帮助

      + (UIImage *)circularImage:(UIImage *)image withDiameter:(NSUInteger)diameter
      {
          CGRect frame = CGRectMake(0.0f, 0.0f, diameter, diameter);
          UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
          imageView.contentMode = UIViewContentModeScaleAspectFill;
          imageView.clipsToBounds = YES;
          imageView.image = image;
          CALayer *layer = imageView.layer;
      
      
          layer.masksToBounds = YES;
      
          layer.cornerRadius =MAX( imageView.frame.size.height,imageView.frame.size.width)/2;
      
          UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,NO, [UIScreen mainScreen].scale);
          CGContextRef context = UIGraphicsGetCurrentContext();
          [layer renderInContext:context];
      
      
          UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
      
          return roundedImage;
      }
      

      【讨论】:

        【解决方案8】:

        如果您使用的是 Swift,您可以导入“AlamofireImage”,并使用它的一种功能。对于带圆圈的图像:

        let roundImage = UIImage(named: "myImage")!.af_imageRoundedIntoCircle()
        

        【讨论】:

          【解决方案9】:

          试试这个

          UIImageView *circleImageview=[[UIImageView alloc]init];
          circleImageview.frame=CGRectMake(0,10, 80, 80)]; 
          circleImageview.layer.cornerRadius=circleimagview.frame.size.height/2;
           circleImageview.userInteractionEnabled=YES;
           [self.view addSubview:circleImageview];
          

          注意:确保该视图的高度和宽度相同。

          【讨论】:

            【解决方案10】:

            觉得我应该把帽子扔进擂台。一个有效、紧凑的 Swift 5 解决方案:

            extension UIImage {
            
                var rounded: UIImage? {
                    UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
                    defer { UIGraphicsEndImageContext() }
                    let bounds = CGRect(origin: .zero, size: size)
                    UIBezierPath(roundedRect: bounds, cornerRadius: size.height/2.0).addClip()
                    draw(in: bounds)
                    return UIGraphicsGetImageFromCurrentImageContext()
                }
            
            }
            
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-02-14
              • 2014-07-02
              • 2020-05-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-10-17
              • 2011-09-25
              相关资源
              最近更新 更多