web-dev-qa-db-fra.com

UIImage coins arrondis

J'essaie d'obtenir des angles arrondis sur UIImage. Ce que j'ai lu jusqu'à présent, le plus simple est d'utiliser un masque d'images Pour cela, j'ai utilisé le code de TheElements iPhone Example et du code de redimensionnement d'image que j'ai trouvé. Mon problème est que resizedImage est toujours nul et je ne trouve pas l'erreur ...

- (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;
}
57
catlan

Le problème était l'utilisation de CGImageCreateWithMask qui renvoyait une image entièrement noire. La solution que j'ai trouvée consistait à utiliser CGContextClipToMask à la place:

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;
14
catlan

Si vous utilisez UIImageView pour afficher l'image, vous pouvez simplement procéder comme suit:

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

Et pour ajouter une bordure:

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

Je crois que vous devrez importer <QuartzCore/QuartzCore.h> et y faire un lien pour que le code ci-dessus fonctionne.

203
jessecurry

Que diriez-vous de ces lignes ...

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

J'ai créé une extension UIImage- dans Swift, basée sur l'excellente réponse de @ 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()
    }
}

Testé dans un storyboard:

 storyboard

27
Besi

En réalité, vous ne faites rien d’autre que d’y mettre à l’échelle. Ce que vous devez faire est de "masquer" les coins de l'image en la découpant avec un CGPath. Par exemple - 

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

Je suggère de consulter le guide de programmation Quartz 2D ou d’autres exemples.

5
wisequark
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;
}
4
Voda Ion

Salut les gars essayer ce code,

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

À votre santé !!!

2
Augustine P A

Étendre l'excellente réponse de Besi , avec la bonne échelle, dans 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()!
    }

}
1
samwize

Voici le moyen le plus simple et le plus simple de le faire:

UIImageView *imageView;

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

Assez simple et fait ce droit.

1
Idan

Il est très facile de créer une image arrondie lorsque vous utilisez la dimension de l'image.

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

La raison pour laquelle cela a fonctionné avec le découpage, pas avec le masquage, semble être l'espace de couleur. 

Documentation Apple ci-dessous.

masque Un masque. Si le masque est une image, il doit figurer dans l'espace colorimétrique DeviceGray, ne pas avoir de composant alpha et ne peut pas être lui-même masqué par un masque d'image ou une couleur de masquage. Si le masque n'a pas la même taille que l'image spécifiée par le paramètre image, Quartz adapte le masque à la taille de l'image.

1
sang

J'avais du mal à contourner les coins d'une boîte UIImage dans mon story-board. J'ai eu un IBOutlet pour mon UIImage appelé image. Après avoir lu de nombreux articles sur ce site, j’ai simplement ajouté 3 lignes et cela a parfaitement fonctionné. 

import UIKit

Puis dans viewDidLoad:

image.layer.cornerRadius = 20.0

image.layer.masksToBounds = true

Ceci est pour iOS 11.1 dans Xcode 9.

0
Donsb

Voir ici ... IMO sauf si vous devez absolument le faire en code, superposez simplement une image.

Quelque chose dans le sens de ...

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

Je pense que cela pourrait être très lié: Dans iOS 11, il existe un moyen très élégant d’arrondir chaque coin d’une vue (Image).

let imageView = UIImageView(image: UIImage(named: "myImage"))    
imageView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
imageView.layer.cornerRadius = 10.0
0
scrat84

Pour créer une image de coin arrondi, nous pouvons utiliser du quartzcore.

Tout d'abord, comment ajouter le framework QuartzCore?

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

ou sinon

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

Maintenant importer 

#import <QuartzCore/QuartzCore.h> 

dans votre ViewController

Puis dans la méthode 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;
0
user3182143