1
- (UIImage *)roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize {
    // If the image does not have an alpha layer, add one
    UIImage *image = [self imageWithAlpha];

    // Build a context that's the same dimensions as the new size
    CGBitmapInfo info = CGImageGetBitmapInfo(image.CGImage);
    CGContextRef context = CGBitmapContextCreate(NULL,
                                             image.size.width,
                                             image.size.height,
                                             CGImageGetBitsPerComponent(image.CGImage),
                                             0,
                                             CGImageGetColorSpace(image.CGImage),
                                             CGImageGetBitmapInfo(image.CGImage));

    // Create a clipping path with rounded corners
    CGContextBeginPath(context);
    [self addRoundedRectToPath:CGRectMake(borderSize, borderSize, image.size.width - borderSize * 2, image.size.height - borderSize * 2)
                   context:context
                 ovalWidth:cornerSize
                ovalHeight:cornerSize];
    CGContextClosePath(context);
    CGContextClip(context);

    // Draw the image to the context; the clipping path will make anything outside the rounded rect transparent
    CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);

    // Create a CGImage from the context
    CGImageRef clippedImage = CGBitmapContextCreateImage(context);
    CGContextRelease(context);

    // Create a UIImage from the CGImage
    UIImage *roundedImage = [UIImage imageWithCGImage:clippedImage];
    CGImageRelease(clippedImage);

    return roundedImage;
}

I have the method above and am adding rounded corners to Twitter profile images. For most of the images this works awesome. There are a few that cause the following error to occur:

: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component color space; kCGImageAlphaLast; 96 bytes/row.

I have done some debugging and it looks like the only difference from the images causing errors and the ones that are not is the parameter, CGImageGetBitmapInfo(image.CGImage), when creating the context. This throws the error and results in the context being null. I tried setting the last parameter to kCGImageAlphaPremultipliedLast to no avail either. The image is drawn this time but with much less quality. Is there a way to get a higher quality image on par with the rest of them? The path to the image is via Twitter so not sure if they have different ones you can pull.

I have seen the other questions regarding this error too. None of have solved this issue. I saw this post but the errored images are completely blurry after that. And casting the width and height to NSInteger also didn't work. Below is a screenshot of the two profile images and their quality as well. The first one is causing the error.

Here is a screenshot of the two images and their quality

Does anyone have any idea what the issue is here?

Thanks a ton. This has been killing me.

Community
  • 1
  • 1
kschins
  • 1,054
  • 1
  • 13
  • 26
  • Does the original image returned by `imageWithAlpha` have a `scale` value other than 1.0? – rob mayoff Mar 01 '12 at 04:41
  • The blurry image, or the image that errors, has a scale value of 2.0 whereas the others have a scale value of 1.0. Hopefully this helps... – kschins Mar 01 '12 at 04:59

1 Answers1

4

iOS does not support kCGImageAlphaLast. You need to use kCGImageAlphaPremultipliedLast.

You also need to handle the scale of your initial image. Your current code doesn't, so it downsamples the image if its scale is 2.0.

You can write the entire function more simply by using UIKit functions and classes. UIKit will take care of the scale for you; you just have to pass in the original image's scale when you ask it to create the graphics context.

- (UIImage *)roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize {
    // If the image does not have an alpha layer, add one
    UIImage *image = [self imageWithAlpha];

    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale); {
        CGRect imageRect = (CGRect){ CGPointZero, image.size };
        CGRect borderRect = CGRectInset(imageRect, borderSize, borderSize);
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:borderRect
            byRoundingCorners:UIRectCornerAllCorners
            cornerRadii:CGSizeMake(cornerSize, cornerSize)];
        [path addClip];
        [image drawAtPoint:CGPointZero];
    }
    UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return roundedImage;
}

If your imageWithAlpha method itself creates a UIImage from another UIImage, it needs to propagate the scale also.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • The image is still blurry. I get the image I'm getting from Twitter is half the size of the others. Is there a way to get a higher res, or bigger, image? Or how can I handle the quality of it? – kschins Mar 01 '12 at 01:34
  • The only issue with this is the rounded corners have double the corner radius for the image.scale that's double. I'll take care of this. Thanks again. – kschins Mar 01 '12 at 05:30
  • Thanks so much! "iOS does not support kCGImageAlphaLast" - not documented in the headers, not documented in the official docs (CG programming guide) as of August 2013. Someone at Apple screwed up when porting this one, and not documenting the features they'd removed. NB: on iOS6, you get an incorrect error message on console from Apple :( – Adam Sep 02 '13 at 22:11