Josh Bernfeld
Josh Bernfeld

Reputation: 4426

Draw a border and shadow onto a UIImage

I have been able to redraw a UIImage with a border successfully, but not with a border + shadow. The code below successfully draws the image with a white border, but I cannot figure out how to include a drop shadow under the border. Help is greatly appreciated!

- (UIImage *)generatePhotoFrameWithImage:(UIImage *)image {
    CGSize newSize = CGSizeMake(image.size.width + 50, image.size.height + 60);
    UIGraphicsBeginImageContext(newSize);
    CGRect rect = CGRectMake(25, 35, image.size.width, image.size.height);
    [image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
    CGContextStrokeRectWithWidth(context, CGRectMake(25, 35, image.size.width, image.size.height), 50);
    
    //CGContextSetShadowWithColor(context, CGSizeMake(0, -60), 5, [UIColor blackColor].CGColor);
    
    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

PS: I am not using a UIImageView because I need to preserve the full image quality.

Upvotes: 0

Views: 6486

Answers (2)

Josh Bernfeld
Josh Bernfeld

Reputation: 4426

Thank you Rob for pointing me the right direction. This is the final code which draws a white border around an image, and then a light grey shadow around the outside of the border

- (UIImage *)generatePhotoStackWithImage:(UIImage *)image {
    CGSize newSize = CGSizeMake(image.size.width + 70, image.size.height + 70);
    CGRect rect = CGRectMake(25, 25, image.size.width, image.size.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, image.scale); {
    CGContextRef context = UIGraphicsGetCurrentContext();
        //Shadow
        CGContextSetShadowWithColor(context, CGSizeMake(0, 0), 10, [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f].CGColor);

        CGContextBeginTransparencyLayer (context, NULL);
        //Draw
        [image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
        CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
        CGContextStrokeRectWithWidth(context, rect, 40);
        CGContextEndTransparencyLayer(context);
    }

    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

Upvotes: 4

rob mayoff
rob mayoff

Reputation: 385590

You need to call CGContextSetShadowWithColor before you stroke the border, so the border will cast a shadow.

If you don't want the border to cast a shadow onto the image, you need to set up a transparency layer in which you draw both the image and the border. You can read about transparency layers in the Quartz 2D Programming Guide.

If you want to preserve image quality, you need to use UIGraphicsBeginImageContextWithOptions and pass in the scale of the original image.

- (UIImage *)generatePhotoFrameWithImage:(UIImage *)image {
    CGSize newSize = CGSizeMake(image.size.width + 50, image.size.height + 60);
    CGRect rect = CGRectMake(25, 35, image.size.width, image.size.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, image.scale); {
        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextBeginTransparencyLayer(context, NULL); {
            [image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];

            CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
            CGContextSetShadowWithColor(context, CGSizeMake(0, 5), 5, [UIColor blackColor].CGColor);
            CGContextStrokeRectWithWidth(context, CGRectMake(25, 35, image.size.width, image.size.height), 50);
        } CGContextEndTransparencyLayer(context);
    }
    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

Upvotes: 9

Related Questions