代码创建的圆角纯色图像模糊

The rounded pure color image created by code is blur

在 objective-c 中,我通过以下代码以编程方式制作了一个圆形:

+(UIImage *)makeRoundedImage:(CGSize) size backgroundColor:(UIColor *) backgroundColor cornerRadius:(int) cornerRadius
{
    UIImage* bgImage = [self imageWithColor:backgroundColor andSize:size];;

    CALayer *imageLayer = [CALayer layer];
    imageLayer.frame = CGRectMake(0, 0, size.width, size.height);
    imageLayer.contents = (id) bgImage.CGImage;

    imageLayer.masksToBounds = YES;
    imageLayer.cornerRadius = cornerRadius;

    UIGraphicsBeginImageContext(bgImage.size);
    [imageLayer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return roundedImage;
}

imageWithColor方法如下:

+(UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size
{
    //quick fix, or pop up  CG invalid context 0x0 bug
    if(size.width == 0) size.width = 1;
    if(size.height == 0) size.height = 1;
    //---quick fix

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

然后我用它制作了一个纯色的圆形图像,但是我发现圆形图像不是完美的圆角。例如,请看下面的代码:

CGSize size = CGSizeMake(diameter, diameter);
int r = ceil((float)diameter/2.0);
UIImage *imageNormal = [self makeRoundedImage:size backgroundColor:backgroundColor cornerRadius:r];
[slider setThumbImage:imageNormal forState:UIControlStateNormal];

首先我创建了一个圆形图像,然后我将图像设置为 UISlider 的缩略图。但是显示的是如下图所示:

你可以看到这个圆不是一个精确的圆。我在想可能是屏幕分辨率问题引起的?因为如果我使用缩略图的图像资源,我需要添加@2x。有人知道原因吗?提前致谢。


2015 年 8 月 8 日更新。

根据这个问题和@Noah Witherspoon 的回答,我发现边缘模糊的问题已经解决。但仍然,圆圈看起来像被切割了。我使用的代码如下:

CGRect rect = CGRectMake(0.0f, 0.0f, radius*2.0f, radius*2.0f);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);     
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillEllipseInRect(context, rect);
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;

圆圈看起来像:

可以看到边缘被切掉了

我修改了如下代码:

CGRect rect = CGRectMake(0.0f, 0.0f, radius*2.0f+4, radius*2.0f+4);
CGRect rectmin = CGRectMake(2.0f, 2.0f, radius*2, radius*2);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillEllipseInRect(context, rectmin);
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;

你可以看到圆形看起来更好(顶部边缘和底部边缘):

我缩小了填充矩形的尺寸,边缘看起来更好,但我认为这不是一个好的解决方案。不过,有人知道为什么会这样吗?

如果你想每次都得到一个圆圈,试试这个:

- (UIImage *)makeCircularImage:(CGSize)size backgroundColor:(UIColor *)backgroundColor {
    CGSize squareSize = CGSizeMake((size.width > size.height) ? size.width : size.height,
                                   (size.width > size.height) ? size.width : size.height);

    UIView *circleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, squareSize.width, squareSize.height)];
    circleView.layer.cornerRadius = circleView.frame.size.height * 0.5f;
    circleView.backgroundColor = backgroundColor;
    circleView.opaque = NO;

    UIGraphicsBeginImageContextWithOptions(circleView.bounds.size, circleView.opaque, 0.0);
    [circleView.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return img;
}

从你的屏幕截图来看,你确实有一张圆形图片,但它的比例是错误的——它不是 Retina——所以它看起来很模糊而且不是圆形的。关键是不要使用默认比例为 1.0 的 UIGraphicsBeginImageContext(与屏幕比例为 2.0 或 3.0 相比),您应该使用 UIGraphicsBeginImageContextWithOptions。此外,您无需创建图层或视图即可在图像上下文中绘制圆圈。

+ (UIImage *)makeCircleImageWithDiameter:(CGFloat)diameter color:(UIColor *)color {
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), NO, 0 /* scale (0 means “use the current screen’s scale”) */);
    [color setFill];
    CGContextFillEllipseInRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, diameter, diameter));
    UIImage *image = UIGraphicsGetImageFromCurrentContext();
    UIGraphicsEndImageContext();
    return image;
}