从阴影视图创建 UIImage 同时保留 Alpha?

发布于 2024-12-12 09:10:57 字数 1108 浏览 0 评论 0原文

我有一个有点不寻常的问题。在我的应用程序中,我使用基本的 Quartz2d 图层阴影对 UIImageView 进行阴影处理。这是我的代码:

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

这会在图像视图后面产生漂亮的模糊效果。然而,我正在用这个视图做一些动画,并且在过渡期间不断重新计算阴影会导致非常不稳定的过渡。我想要做的是从图像视图中创建一个 UIImage 或 .png 文件并且模糊和 alpha 完好无损。这是我已经尝试过的:

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

由于我有一个“生长在图像视图之外”的阴影,因此我不能只在 UIGraphicsBeginImageContext 函数中传递他的大小。我设置了正确的大小,但生成的图像不会保存我的 Alpha,而是在阴影后面放置一个白色背景,这对我不起作用,因为我的真实背景是木材纹理。此外,视图并不位于结果文件的中心。

我非常擅长 UIKit,但我对 Quartz 2d 图形来说是个真正的菜鸟,所以如果对此有明显的答案,请无论如何发送。 :)

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

失与倦" 2024-12-19 09:11:08

添加阴影路径以像这样查看

[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;

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;
明明#如月 2024-12-19 09:11:06

我以前也遇到过这个问题。我的解决方案不是制作图像,而是将阴影路径设置为您正在制作动画的视图的轮廓。

[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;

它使用以下函数,假设图像设置为内容模式纵横比适合:

-(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;
}

如果您的图像只是设置为填充,那么只需使用 imageView.bounds 就足够了

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

枕花眠 2024-12-19 09:11:05

尝试将 UIImageViewbackgroundColor 设置为 [UIColor clearColor] - 这可能会使您当前的解决方案起作用。

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

来源:将 CGLayer 转换为CoreGraphics iphone 中的*透明* UIImage 和 PNG 文件

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文