60 votes

Coins arrondis sur UIImage

Je suis en train de dessiner des images sur l'iPhone à l'aide avec des coins arrondis, un la les images des contacts dans l'application Contacts. J'ai un code qui fonctionne généralement, mais parfois il se bloque à l'intérieur de la UIImage dessin routines avec un EXEC_BAD_ACCESS - KERN_INVALID_ADDRESS. J'ai pensé que cela pourrait être lié à l' recadrage question , j'ai demandé il y a quelques semaines, mais je crois que je suis la mise en place du chemin de détourage correctement.

Voici le code que j'utilise - quand il ne plante pas, le résultat a l'air bien et quiconque cherche à obtenir un look similaire est libre d'emprunter le code.

- (UIImage *)borderedImageWithRect: (CGRect)dstRect radius:(CGFloat)radius {
    UIImage *maskedImage = nil;

    radius = MIN(radius, .5 * MIN(CGRectGetWidth(dstRect), CGRectGetHeight(dstRect)));
    CGRect interiorRect = CGRectInset(dstRect, radius, radius);

    UIGraphicsBeginImageContext(dstRect.size);
    CGContextRef maskedContextRef = UIGraphicsGetCurrentContext();
    CGContextSaveGState(maskedContextRef);

    CGMutablePathRef borderPath = CGPathCreateMutable();
    CGPathAddArc(borderPath, NULL, CGRectGetMinX(interiorRect), CGRectGetMinY(interiorRect), radius, PNDegreeToRadian(180), PNDegreeToRadian(270), NO);
    CGPathAddArc(borderPath, NULL, CGRectGetMaxX(interiorRect), CGRectGetMinY(interiorRect), radius, PNDegreeToRadian(270.0), PNDegreeToRadian(360.0), NO);
    CGPathAddArc(borderPath, NULL, CGRectGetMaxX(interiorRect), CGRectGetMaxY(interiorRect), radius, PNDegreeToRadian(0.0), PNDegreeToRadian(90.0), NO);
    CGPathAddArc(borderPath, NULL, CGRectGetMinX(interiorRect), CGRectGetMaxY(interiorRect), radius, PNDegreeToRadian(90.0), PNDegreeToRadian(180.0), NO);

    CGContextBeginPath(maskedContextRef);
    CGContextAddPath(maskedContextRef, borderPath);
    CGContextClosePath(maskedContextRef);
    CGContextClip(maskedContextRef);

    [self drawInRect: dstRect];

    maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    CGContextRestoreGState(maskedContextRef);
    UIGraphicsEndImageContext();

    return maskedImage;
}

et voici le rapport de crash. Il regarde la même chose à chaque fois que je reçois un de ces accidents

Type d'Exception: EXC_BAD_ACCESS (SIGSEGV)
Codes d'Exception: KERN_INVALID_ADDRESS à 0x6e2e6181
S'Est Écrasé Fil: 0

Thread 0 Écrasé:
0 com.apple.CoreGraphics 0x30fe56d8 CGGStateGetRenderingIntent + 4
1 libRIP.Un.dylib 0x33c4a7d8 ripc_RenderImage + 104
2 libRIP.Un.dylib 0x33c51868 ripc_DrawImage + 3860
3 com.apple.CoreGraphics 0x30fecad4 CGContextDelegateDrawImage + 80
4 com.apple.CoreGraphics 0x30feca40 CGContextDrawImage + 368
5 UIKit 0x30a6a708 -[UIImage drawInRect:blendMode:alpha:] + 1460
6 UIKit 0x30a66904 -[UIImage drawInRect:] + 72
7 MyApp 0x0003f8a8 -[UIImage(PNAdditions) borderedImageWithRect:rayon:] (UIImage+PNAdditions.m:187)

164voto

MagicSeth Points 2772

Voici une méthode encore plus simple disponible dans iPhone 3.0 et versions ultérieures. Chaque objet basé sur une vue est associé à une couche. Chaque couche peut avoir un rayon de coin défini, cela vous donnera exactement ce que vous voulez:

 UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * l = [roundedView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];

// You can even add a border
[l setBorderWidth:4.0];
[l setBorderColor:[[UIColor blueColor] CGColor]];
 

29voto

Jonny Points 2898

Je vais y aller et répondre à la question dans le titre.

Essayez cette catégorie.

UIImage + additions.h

 #import <UIKit/UIKit.h>

@interface UIImage (additions)
-(UIImage*)makeRoundCornersWithRadius:(const CGFloat)RADIUS;
@end
 

UIImage + additions.m

 #import "UIImage+additions.h"

@implementation UIImage (additions)
-(UIImage*)makeRoundCornersWithRadius:(const CGFloat)RADIUS {
    UIImage *image = self;

    // Begin a new image that will be the new image with the rounded corners
    // (here with the size of an UIImageView)
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);

    const CGRect RECT = CGRectMake(0, 0, image.size.width, image.size.height);
    // Add a clip before drawing anything, in the shape of an rounded rect
    [[UIBezierPath bezierPathWithRoundedRect:RECT cornerRadius:RADIUS] addClip];
    // Draw your image
    [image drawInRect:RECT];

    // Get the image, here setting the UIImageView image
    //imageView.image
    UIImage* imageNew = UIGraphicsGetImageFromCurrentImageContext();

    // Lets forget about that we were drawing
    UIGraphicsEndImageContext();

    return imageNew;
}
@end
 

22voto

acidscan Points 188

Si appIconImage est un UIImageView, alors:

 appIconImage.image = [UIImage imageWithContentsOfFile:@"image.png"]; 
appIconImage.layer.masksToBounds = YES;
appIconImage.layer.cornerRadius = 10.0;
appIconImage.layer.borderWidth = 1.0;
appIconImage.layer.borderColor = [[UIColor grayColor] CGColor];
 

Et rappelez-vous aussi:

 #import <QuartzCore/QuartzCore.h>
 

4voto

Lounges Points 3745

Je ne peux pas vous donner une idée de votre accident, mais je pensais pouvoir offrir une autre option pour arrondir les angles. J'ai eu un problème similaire dans une application sur laquelle je travaillais. Plutôt que d'écrire un code, je superpose une autre image qui masque les coins.

4voto

fjoachim Points 353

Si vous appelez votre méthode (borderedImageWithRect) dans un thread en arrière-plan, des blocages peuvent survenir car les fonctions UIGraphics ne sont pas thread-safe. Dans un tel cas, vous devez créer un contexte à l'aide de CGBitmapContextCreate () - voir l'exemple de code "Reflection" dans le SDK.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X