UIImage cantos arredondados

Eu tento obter cantos arredondados em um UIImage, o que eu li até agora, a maneira mais fácil é usar uma máscara de imagens. Para isso, usei o código do TheElements iPhone Example e alguns códigos de redimensionamento de imagem que encontrei. Meu problema é que resizedImage é sempre nulo e não encontro o erro …

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

Se você estiver usando um UIImageView para exibir a imagem, basta fazer o seguinte:

 imageView.layer.cornerRadius = 5.0; imageView.layer.masksToBounds = YES; 

E para adicionar uma borda:

 imageView.layer.borderColor = [UIColor lightGrayColor].CGColor; imageView.layer.borderWidth = 1.0; 

Eu acredito que você terá que importar e linkar para que o código acima funcione.

Como sobre essas linhas …

 // 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(); 

Eu criei uma UIImage rápida, com base na grande resposta do @ 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() } } 

Testado em um storyboard:

storyboard

O problema foi o uso de CGImageCreateWithMask que retornou uma imagem toda preta. A solução que encontrei foi usar 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; 

Você não está realmente fazendo nada além de escalar lá. O que você precisa fazer é “mascarar” os cantos da imagem cortando-a com um CGPath. Por exemplo –

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

Eu sugiro verificar o guia de programação 2D Quartz ou algumas outras amostras.

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

Oi pessoal, tente esse código

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

Felicidades !!!

O motivo pelo qual ele trabalhou com recorte, não com mascaramento, parece ser o espaço de colors.

Documentação da Apple abaixo.

máscara Uma máscara. Se a máscara for uma imagem, ela deve estar no espaço de colors DeviceGray, não deve ter um componente alfa e não pode ser mascarada por uma máscara de imagem ou uma cor de máscara. Se a máscara não for do mesmo tamanho que a imagem especificada pelo parâmetro de imagem, o Quartz dimensionará a máscara para ajustá-la à imagem.

Descobri que a melhor e mais simples maneira de fazê-lo é a seguinte (sem resposta):

 UIImageView *imageView; imageView.layer.cornerRadius = imageView.frame.size.width/2.0f; imageView.layer.masksToBounds = TRUE; 

Muito simples e feito isso direito.

Veja aqui … IMO, a menos que você realmente precise fazer isso no código, basta sobrepor uma imagem na parte superior.

Algo ao longo das linhas de …

 - (void)drawRect:(CGRect)rect { // Drawing code [backgroundImage drawInRect:rect]; [buttonOverlay drawInRect:rect]; } 

Para criar uma imagem Round Corner, podemos usar o quartzcore.

Primeiro Como adicionar o framework QuartzCore?

 Click project -Targets ->project ->BuildPhase ->Link Binary with Libraries ->Then click + symbol finally select from list and add it 

se não

 Click project -Targets ->Targets ->general ->Linked Frameworks and Libraries ->Then click + symbol finally select from list and add the QuartzCore framework 

Agora importe

 #import  

no seu ViewController

Então, no método 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; 

É muito fácil criar uma imagem arredondada quando você usa a dimensão da imagem.

 cell.messageImage.layer.cornerRadius = image.size.width / 2 cell.messageImage.layer.masksToBounds = true 

Eu estava lutando para contornar os cantos de uma checkbox de UIImage no meu storyboard. Eu tinha um IBOutlet para minha imagem chamada UIImage. Depois de ler um monte de posts aqui, eu simplesmente adicionei 3 linhas e isso funcionou perfeitamente.

 import UIKit 

Então, em viewDidLoad:

 image.layer.cornerRadius = 20.0 image.layer.masksToBounds = true 

Isto é para o iOS 11.1 no Xcode 9.

Estendendo a excelente resposta de Besi , com escala correta, no Swift 4 :

 extension UIImage { public func rounded(radius: CGFloat) -> UIImage { let rect = CGRect(origin: .zero, size: size) UIGraphicsBeginImageContextWithOptions(size, false, scale) UIBezierPath(roundedRect: rect, cornerRadius: radius).addClip() draw(in: rect) return UIGraphicsGetImageFromCurrentImageContext()! } }