Create UIImage from shadowed view while retaining alpha?

I have a somewhat unusual problem. In my app, I am shadowing a UIImageView using basic Quartz2d layer shadowing. Here’s my code:

imageView.layer.shadowOpacity = 1.0; // Pretty self explanatory
imageView.layer.shadowRadius = 8.0; // My softness
imageView.layer.shadowColor = [UIColor blackColor].CGColor; // Color of the shadow
imageView.layer.shadowOffset = CGSizeMake(0.0, 0.0); // Offset of the shadow

This produces a nice blur behind the image view. However, I am doing some animation with this view, and the constant recalculation of the shadowing during the transitions causes a very choppy transition. What I’d like to be able to do is create a UIImage or .png file out of the image view with the blur and its alpha intact. Here’s what I’ve already tried:

  • Directory not found for option '-L/Users/…/TestFlightSDK1.1'
  • Parallax effect with UIScrollView subviews
  • using sks file with SKScene subclass
  • How to Impliment Search bar in Table view for Contacts in ios
  • sqlite ios : attempt to write a readonly database
  • Create csv file using javascript
  • UIGraphicsBeginImageContext(CGSizeMake(320, 396)); 
    [imageView.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
    

    Since I have a shadow which “grows outside” of the image view, I can’t just pass his size in the UIGraphicsBeginImageContext function. I set the correct size, but the resulting image doesn’t save my alpha, instead it places a white background behind the shadow, which won’t work for me because my real background is a wood texture. Also, the view isn’t centered in the resulting file.

    I’m pretty good with UIKit, but I’m a real noobie with Quartz 2d graphics, so if there’s an obvious answer to this, send it anyway. 🙂

    3 Solutions Collect From Internet About “Create UIImage from shadowed view while retaining alpha?”

    Try setting your UIImageView‘s backgroundColor to [UIColor clearColor] – this may enable your current solution to work.

    imageView.backgroundColor = [UIColor clearColor];
    UIGraphicsBeginImageContext(CGSizeMake(320, 396)); 
    [imageView.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

    Source: Converting a CGLayer to a *transparent* UIImage and PNG file in CoreGraphics iphone

    I’ve had this issue before too. My solution was not to do an image, but instead to set the shadow path to just the outline of the view you are animating.

    [imageView setContentMode:UIViewContentModeScaleAspectFit];
    imageView.layer.masksToBounds = NO;
    imageView.layer.shadowOffset = CGSizeMake(5, 5);
    imageView.layer.shadowRadius = 200;
    imageView.layer.shadowOpacity = 0.5;
    CGRect rect = [self rectFromImageView:imageView];
    imageView.layer.shadowPath = [UIBezierPath bezierPathWithRect:rect].CGPath;
    

    Which uses the following function which assumes the image is set to content mode aspect fit:

    -(CGRect)rectFromImageView:(UIImageView *)iv {
        CGRect rect = (CGRect){{0,0},iv.frame.size};
        if (iv.image.size.width/iv.frame.size.width > iv.image.size.height/iv.frame.size.height) {
            //rect.origin.x == 0
            CGFloat sf = iv.frame.size.width/iv.image.size.width;
            rect.size.height = sf*iv.image.size.height;
            rect.origin.y = floor((iv.frame.size.height - rect.size.height)/2);
        } else {
            //rect.origin.y == 0;
            CGFloat sf = iv.frame.size.height/iv.image.size.height;
            rect.size.width = sf*iv.image.size.width;
            rect.origin.x = floor((iv.frame.size.width - rect.size.width)/2);       
        }
        return rect;
    }
    

    If your image is just set to fill then just using the imageView.bounds should be sufficient

    Add shadow path to view like this

    [view.layer setShadowPath:[[UIBezierPath bezierPathWithRect:view.bounds] CGPath]]; //add path
    view.layer.shadowColor = [[UIColor blackColor] CGColor];
    view.layer.shadowOffset = CGSizeMake(x, y);
    view.layer.shadowRadius = rad;
    view.layer.shadowOpacity = 0.2f;