70 votes

UIImage coins arrondis

J'essaie d'obtenir des coins arrondis sur une image UIImage, ce que j'ai lu jusqu'à présent, la façon la plus simple est d'utiliser un masque d'images. Pour cela, j'ai utilisé le code de TheElements iPhone Example et un 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;
}

0 votes

Un code rapide ?

215voto

jessecurry Points 12114

Si vous utilisez un 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 créer un lien avec lui pour que le code ci-dessus fonctionne.

1 votes

Importer et lier contre quoi ?

3 votes

Désolé #import <QuartzCore/QuartzCore.h>

0 votes

Il s'avère qu'il était là, mais qu'il ne s'est pas affiché à cause de la règle "moins que/plus grand que".

92voto

epatel Points 32451

Que pensez-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();

15voto

catlan Points 9896

Le problème était l'utilisation de CGImageCreateWithMask qui retournait une image entièrement noire. La solution que j'ai trouvée est d'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;

4voto

wisequark Points 2748

Vous ne faites rien d'autre que de changer d'échelle ici. Ce qu'il faut faire, c'est "masquer" les coins de l'image en la 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 vous suggère de consulter le guide de programmation de Quartz 2D ou d'autres échantillons.

0 votes

La première partie de mon code est mise à l'échelle, mais la deuxième partie essaie de masquer l'image avec CGImageCreateWithMask. Le problème est que CGImageCreateWithMask retourne null et je ne sais pas pourquoi...

4voto

vadeara Points 115
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;
}

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