1

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:

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. :)

aopsfan
  • 2,451
  • 19
  • 30

3 Answers3

1

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;
Emil
  • 7,220
  • 17
  • 76
  • 135
setdvd
  • 221
  • 1
  • 7
1

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

Benjie
  • 7,701
  • 5
  • 29
  • 44
  • Actually, remembering further, I just disabled the shadows during animation by setting `imageView.layer.shadowOpacity = 0.0;` - sorry. Perhaps my solution might still work? – Benjie Oct 27 '11 at 15:31
  • I tried your solution, but it didn't work...I didn't get any shadow. Like I said, I am a real noob at this stuff. I tried extending the frame of my image view to account for the shadow within the frame, and then changed the content mode to center, thus centering the image in the view. I'll try the shadowOpacity = 0, if that doesn't look to bad during the animation, I'll use that. – aopsfan Oct 29 '11 at 01:14
  • tried removing the shadow, it didn't work and was still slow...I'm sure I must be doing something wrong. – aopsfan Oct 29 '11 at 01:29
  • Sorry for the late reply, I've been on vacation for a week without adequate wi-fi. I tried the new code, and although I got a shadow, animations were still very choppy. – aopsfan Nov 07 '11 at 21:30
1

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

Community
  • 1
  • 1
Benjie
  • 7,701
  • 5
  • 29
  • 44