我尝试在UIImage上获得圆角,到目前为止我读到的,最简单的方法是使用蒙版图像。为此我使用了TheElements iPhone Example中的代码和我找到的一些图像大小调整代码。我的问题是resizedImage总是为nil而且我没有找到错误...
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize
{
CGSize imageSize = [self size];
float width = imageSize.width;
float height = imageSize.height;
// scaleFactor will be the fraction that we'll
// use to adjust the size. For example, if we shrink
// an image by half, scaleFactor will be 0.5. the
// scaledWidth and scaledHeight will be the original,
// multiplied by the scaleFactor.
//
// IMPORTANT: the "targetHeight" is the size of the space
// we're drawing into. The "scaledHeight" is the height that
// the image actually is drawn at, once we take into
// account the ideal of maintaining proportions
float scaleFactor = 0.0;
float scaledWidth = targetSize.width;
float scaledHeight = targetSize.height;
CGPoint thumbnailPoint = CGPointMake(0,0);
// since not all images are square, we want to scale
// proportionately. To do this, we find the longest
// edge and use that as a guide.
if ( CGSizeEqualToSize(imageSize, targetSize) == NO )
{
// use the longeset edge as a guide. if the
// image is wider than tall, we'll figure out
// the scale factor by dividing it by the
// intended width. Otherwise, we'll use the
// height.
float widthFactor = targetSize.width / width;
float heightFactor = targetSize.height / height;
if ( widthFactor < heightFactor )
scaleFactor = widthFactor;
else
scaleFactor = heightFactor;
// ex: 500 * 0.5 = 250 (newWidth)
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the thumbnail in the frame. if
// wider than tall, we need to adjust the
// vertical drawing point (y axis)
if ( widthFactor < heightFactor )
thumbnailPoint.y = (targetSize.height - scaledHeight) * 0.5;
else if ( widthFactor > heightFactor )
thumbnailPoint.x = (targetSize.width - scaledWidth) * 0.5;
}
CGContextRef mainViewContentContext;
CGColorSpaceRef colorSpace;
colorSpace = CGColorSpaceCreateDeviceRGB();
// create a bitmap graphics context the size of the image
mainViewContentContext = CGBitmapContextCreate (NULL, targetSize.width, targetSize.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
// free the rgb colorspace
CGColorSpaceRelease(colorSpace);
if (mainViewContentContext==NULL)
return NULL;
//CGContextSetFillColorWithColor(mainViewContentContext, [[UIColor whiteColor] CGColor]);
//CGContextFillRect(mainViewContentContext, CGRectMake(0, 0, targetSize.width, targetSize.height));
CGContextDrawImage(mainViewContentContext, CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledWidth, scaledHeight), self.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef mainViewContentBitmapContext = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
CGImageRef maskImage = [[UIImage imageNamed:@"Mask.png"] CGImage];
CGImageRef resizedImage = CGImageCreateWithMask(mainViewContentBitmapContext, maskImage);
CGImageRelease(mainViewContentBitmapContext);
// convert the finished resized image to a UIImage
UIImage *theImage = [UIImage imageWithCGImage:resizedImage];
// image is retained by the property setting above, so we can
// release the original
CGImageRelease(resizedImage);
// return the image
return theImage;
}
答案 0 :(得分:207)
如果您使用UIImageView显示图像,则只需执行以下操作:
imageView.layer.cornerRadius = 5.0;
imageView.layer.masksToBounds = YES;
并添加边框:
imageView.layer.borderColor = [UIColor lightGrayColor].CGColor;
imageView.layer.borderWidth = 1.0;
我相信您必须导入<QuartzCore/QuartzCore.h>
并链接它才能使上述代码生效。
答案 1 :(得分:86)
这些线怎么样......
// 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, 1.0);
// 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 :(得分:31)
我在swift中创建了UIImage
- 扩展程序,基于@ epatel的绝佳答案:
extension UIImage{
var roundedImage: UIImage {
let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: self.size)
UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
UIBezierPath(
roundedRect: rect,
cornerRadius: self.size.height
).addClip()
self.drawInRect(rect)
return UIGraphicsGetImageFromCurrentImageContext()
}
}
在故事板中测试:
答案 3 :(得分:14)
问题是使用CGImageCreateWithMask返回全黑图像。我找到的解决方案是使用CGContextClipToMask代替:
CGContextRef mainViewContentContext;
CGColorSpaceRef colorSpace;
colorSpace = CGColorSpaceCreateDeviceRGB();
// create a bitmap graphics context the size of the image
mainViewContentContext = CGBitmapContextCreate (NULL, targetSize.width, targetSize.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
// free the rgb colorspace
CGColorSpaceRelease(colorSpace);
if (mainViewContentContext==NULL)
return NULL;
CGImageRef maskImage = [[UIImage imageNamed:@"mask.png"] CGImage];
CGContextClipToMask(mainViewContentContext, CGRectMake(0, 0, targetSize.width, targetSize.height), maskImage);
CGContextDrawImage(mainViewContentContext, CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledWidth, scaledHeight), self.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef mainViewContentBitmapContext = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
// convert the finished resized image to a UIImage
UIImage *theImage = [UIImage imageWithCGImage:mainViewContentBitmapContext];
// image is retained by the property setting above, so we can
// release the original
CGImageRelease(mainViewContentBitmapContext);
// return the image
return theImage;
答案 4 :(得分:5)
除了缩放之外,你实际上并没有做任何其他事情。你需要做的是通过用CGPath剪切它来“掩盖”图像的角落。例如 -
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginTransparencyLayerWithRect(context, self.frame, NULL);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGFloat roundRadius = (radius) ? radius : 12.0;
CGFloat minx = CGRectGetMinX(self.frame), midx = CGRectGetMidX(self.frame), maxx = CGRectGetMaxX(self.frame);
CGFloat miny = CGRectGetMinY(self.frame), midy = CGRectGetMidY(self.frame), maxy = CGRectGetMaxY(self.frame);
// draw the arcs, handle paths
CGContextMoveToPoint(context, minx, midy);
CGContextAddArcToPoint(context, minx, miny, midx, miny, roundRadius);
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, roundRadius);
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, roundRadius);
CGContextAddArcToPoint(context, minx, maxy, minx, midy, roundRadius);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFill);
CGContextEndTransparencyLayer(context);
}
我建议查看Quartz 2D编程指南或其他一些样本。
答案 5 :(得分:5)
以正确的比例扩展Besi's excellent answer,以 Swift 4 :
extension UIImage {
public func rounded(radius: CGFloat) -> UIImage {
let rect = CGRect(origin: .zero, size: size)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
UIBezierPath(roundedRect: rect, cornerRadius: radius).addClip()
draw(in: rect)
return UIGraphicsGetImageFromCurrentImageContext()!
}
}
答案 6 :(得分:4)
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);
}
+ (UIImage *)imageWithRoundCorner:(UIImage*)img andCornerSize:(CGSize)size
{
UIImage * newImage = nil;
if( nil != img)
{
@autoreleasepool {
int w = img.size.width;
int h = img.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
addRoundedRectToPath(context, rect, size.width, size.height);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
[img release];
newImage = [[UIImage imageWithCGImage:imageMasked] retain];
CGImageRelease(imageMasked);
}
}
return newImage;
}
答案 7 :(得分:2)
大家好试试这段代码,
+ (UIImage *)roundedRectImageFromImage:(UIImage *)image withRadious:(CGFloat)radious {
if(radious == 0.0f)
return image;
if( image != nil) {
CGFloat imageWidth = image.size.width;
CGFloat imageHeight = image.size.height;
CGRect rect = CGRectMake(0.0f, 0.0f, imageWidth, imageHeight);
UIWindow *window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
const CGFloat scale = window.screen.scale;
UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginPath(context);
CGContextSaveGState(context);
CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM (context, radious, radious);
CGFloat rectWidth = CGRectGetWidth (rect)/radious;
CGFloat rectHeight = CGRectGetHeight (rect)/radious;
CGContextMoveToPoint(context, rectWidth, rectHeight/2.0f);
CGContextAddArcToPoint(context, rectWidth, rectHeight, rectWidth/2.0f, rectHeight, radious);
CGContextAddArcToPoint(context, 0.0f, rectHeight, 0.0f, rectHeight/2.0f, radious);
CGContextAddArcToPoint(context, 0.0f, 0.0f, rectWidth/2.0f, 0.0f, radious);
CGContextAddArcToPoint(context, rectWidth, 0.0f, rectWidth, rectHeight/2.0f, radious);
CGContextRestoreGState(context);
CGContextClosePath(context);
CGContextClip(context);
[image drawInRect:CGRectMake(0.0f, 0.0f, imageWidth, imageHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
return nil;
}
干杯!!!
答案 8 :(得分:1)
它与剪裁有关的原因,而不是掩盖,似乎是色彩空间。
Apple文档如下。
掩模 一张面具。如果蒙版是图像,则它必须位于DeviceGray颜色空间中,不得具有alpha分量,并且本身可能不会被图像蒙版或蒙版颜色遮罩。如果蒙版的大小与图像参数指定的图像大小不同,则Quartz会缩放蒙版以适合图像。
答案 9 :(得分:1)
使用图像尺寸时,创建圆形图像非常容易。
cell.messageImage.layer.cornerRadius = image.size.width / 2
cell.messageImage.layer.masksToBounds = true
答案 10 :(得分:1)
发现最好和最简单的方法如下(没有回答):
UIImageView *imageView;
imageView.layer.cornerRadius = imageView.frame.size.width/2.0f;
imageView.layer.masksToBounds = TRUE;
非常简单,做得很好。
答案 11 :(得分:0)
See here... 除非您绝对需要在代码中执行此操作,否则只需在顶部覆盖图像。
有些事情......
- (void)drawRect:(CGRect)rect
{
// Drawing code
[backgroundImage drawInRect:rect];
[buttonOverlay drawInRect:rect];
}
答案 12 :(得分:0)
对于创建圆角图像,我们可以使用quartzcore。
首先如何添加QuartzCore框架?
Click project -Targets
->project
->BuildPhase
->Link Binary with Libraries
->Then click + symbol finally select from list and add it
或者
Click project -Targets
->Targets
->general
->Linked Frameworks and Libraries
->Then click + symbol finally select from list and add the QuartzCore framework
现在导入
#import <QuartzCore/QuartzCore.h>
在ViewController中
然后在viewDidLoad方法
self.yourImageView.layer.cornerRadius = 5.0;
self.yourImageView.layer.borderWidth = 1.0f;
self.yourImageView.layer.borderColor = [UIColor blackColor].CGColor;
self.yourImageView.layer.masksToBounds = YES;
答案 13 :(得分:0)
我正在努力绕过故事板中UIImage框的角落。我有一个名为image的UIImage的IBOutlet。在这里阅读了一堆帖子之后,我简单地添加了3行,并且完美无缺。
import UIKit
然后在viewDidLoad中:
image.layer.cornerRadius = 20.0
image.layer.masksToBounds = true
这适用于Xcode 9中的iOS 11.1。
答案 14 :(得分:0)
我认为这可能非常相关: 在iOS 11中,有一种非常巧妙的方法来使(Image)View的每个角变圆。
let imageView = UIImageView(image: UIImage(named: "myImage"))
imageView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
imageView.layer.cornerRadius = 10.0
答案 15 :(得分:0)
我喜欢@samwize的答案,但是当与collectionView一起使用时,它导致我讨厌的内存泄漏。
要修复它,我发现UIGraphicsEndImageContext()
不见了
extension UIImage {
/**
Rounds corners of UIImage
- Parameter proportion: Proportion to minimum paramter (width or height)
in order to have the same look of corner radius independetly
from aspect ratio and actual size
*/
func roundCorners(proportion: CGFloat) -> UIImage {
let minValue = min(self.size.width, self.size.height)
let radius = minValue/proportion
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: self.size)
UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
UIBezierPath(roundedRect: rect, cornerRadius: radius).addClip()
self.draw(in: rect)
let image = UIGraphicsGetImageFromCurrentImageContext() ?? self
UIGraphicsEndImageContext()
return image
}
}
随意通过半径而不是比例。之所以使用proportion
是因为我有collectionView滚动并且图像的大小不同,因此,当使用恒定的半径时,实际上在属性方面看起来有所不同(例如:两张图像,一幅是1000x1000,另一幅是2000x2000 ,其中的角半径为30)。
因此,如果您image.roundCorners(proportion: 20)
,则所有图片看起来都具有相同的拐角半径。
此答案也是最新版本。