通过向现有 UIImage 添加阴影来创建新的 UIImage

问题描述 投票:0回答:9

我查看了这个问题:UIImage Shadow Trouble

但是接受的答案对我不起作用。

我想做的是获取一个 UIImage 并为其添加阴影,然后返回一个全新的 UIImage、阴影和所有内容。

这就是我正在尝试的:

- (UIImage*)imageWithShadow {

    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef shadowContext = CGBitmapContextCreate(NULL, self.size.width, self.size.height + 1, CGImageGetBitsPerComponent(self.CGImage), 0, 
                                                 colourSpace, kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colourSpace);

    CGContextSetShadow(shadowContext, CGSizeMake(0, -1), 1);
    CGContextDrawImage(shadowContext, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage);

    CGImageRef shadowedCGImage = CGBitmapContextCreateImage(shadowContext);
    CGContextRelease(shadowContext);

    UIImage * shadowedImage = [UIImage imageWithCGImage:shadowedCGImage];
    CGImageRelease(shadowedCGImage);

    return shadowedImage;
}

结果是我得到了与通过此方法之前完全相同的图像。

我正在以正确的方式执行此操作,或者我是否遗漏了一些明显的东西?

iphone objective-c cocoa-touch uiimage cgcontext
9个回答
17
投票

您的代码存在几个问题:

  • 目标图像太小。确保有足够的地方来绘制阴影。
  • 考虑使用
    CGContextSetShadowWithColor
    来定义阴影及其颜色。
  • 不要忘记坐标系是翻转的,因此原点是左下角,而不是左上角。

通过解决这些问题,应该绘制阴影。

- (UIImage*)imageWithShadow {
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef shadowContext = CGBitmapContextCreate(NULL, self.size.width + 10, self.size.height + 10, CGImageGetBitsPerComponent(self.CGImage), 0, 
                                             colourSpace, kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colourSpace);

    CGContextSetShadowWithColor(shadowContext, CGSizeMake(5, -5), 5, [UIColor blackColor].CGColor);
    CGContextDrawImage(shadowContext, CGRectMake(0, 10, self.size.width, self.size.height), self.CGImage);

    CGImageRef shadowedCGImage = CGBitmapContextCreateImage(shadowContext);
    CGContextRelease(shadowContext);

    UIImage * shadowedImage = [UIImage imageWithCGImage:shadowedCGImage];
    CGImageRelease(shadowedCGImage);

    return shadowedImage;
}

12
投票

UIImage 的快速扩展:

extension UIImage {
    
    func addShadow(blurSize: CGFloat = 6.0) -> UIImage {
                    
        let shadowColor = UIColor(white:0.0, alpha:0.8).cgColor
        
        let context = CGContext(data: nil,
                                width: Int(self.size.width + blurSize),
                                height: Int(self.size.height + blurSize),
                                bitsPerComponent: self.cgImage!.bitsPerComponent,
                                bytesPerRow: 0,
                                space: CGColorSpaceCreateDeviceRGB(),
                                bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!
        
        context.setShadow(offset: CGSize(width: blurSize/2,height: -blurSize/2),
                          blur: blurSize,
                          color: shadowColor)
        context.draw(self.cgImage!,
                     in: CGRect(x: 0, y: blurSize, width: self.size.width, height: self.size.height),
                     byTiling:false)
        
        return UIImage(cgImage: context.makeImage()!)
    }
}

(根据 Laurent Etiemble 和 capikaw 的答案转换)

用途:

let sourceImage: UIImage(named: "some image")
let shadowImage = sourceImage.addShadow()

5
投票

在尝试使用此处的一些其他示例时,我注意到它们似乎要么对偏移和模糊进行硬编码,要么在调整输出大小和定位时没有正确考虑它们。

以下代码解决了这些问题(它基于 Igor Kulagin 的原创作品):

extension UIImage {
    /// Returns a new image with the specified shadow properties.
    /// This will increase the size of the image to fit the shadow and the original image.
    func withShadow(blur: CGFloat = 6, offset: CGSize = .zero, color: UIColor = UIColor(white: 0, alpha: 0.8)) -> UIImage {

        let shadowRect = CGRect(
            x: offset.width - blur,
            y: offset.height - blur,
            width: size.width + blur * 2,
            height: size.height + blur * 2
        )
        
        UIGraphicsBeginImageContextWithOptions(
            CGSize(
                width: max(shadowRect.maxX, size.width) - min(shadowRect.minX, 0),
                height: max(shadowRect.maxY, size.height) - min(shadowRect.minY, 0)
            ),
            false, 0
        )
        
        let context = UIGraphicsGetCurrentContext()!

        context.setShadow(
            offset: offset,
            blur: blur,
            color: color.cgColor
        )
        
        draw(
            in: CGRect(
                x: max(0, -shadowRect.origin.x),
                y: max(0, -shadowRect.origin.y),
                width: size.width,
                height: size.height
            )
        )
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        
        UIGraphicsEndImageContext()
        return image
    }
}

5
投票

我的 UIImages 需要一个更大的阴影。这是我的答案的变体,它允许定制没有偏移的阴影大小。

- (UIImage*)imageWithShadow:(UIImage*)originalImage BlurSize:(float)blurSize {     
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef shadowContext = CGBitmapContextCreate(NULL, originalImage.size.width + (blurSize*2), originalImage.size.height + (blurSize*2), CGImageGetBitsPerComponent(originalImage.CGImage), 0, colourSpace, kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colourSpace);
    
    CGContextSetShadowWithColor(shadowContext, CGSizeMake(0, 0), blurSize, [UIColor blackColor].CGColor);
    CGContextDrawImage(shadowContext, CGRectMake(blurSize, blurSize, originalImage.size.width, originalImage.size.height), originalImage.CGImage);
    
    CGImageRef shadowedCGImage = CGBitmapContextCreateImage(shadowContext);
    CGContextRelease(shadowContext);
    
    UIImage * shadowedImage = [UIImage imageWithCGImage:shadowedCGImage];
    CGImageRelease(shadowedCGImage);
    
    return shadowedImage;
}

像这样使用它:

UIImage *shadowedImage = [self imageWithShadow:myImage BlurSize:30.0f];

5
投票

我需要一个方法,它接受 UIImage 作为参数并返回一个稍大的带有阴影的 UIImage。这里的帖子对我非常有帮助,所以这是我的方法。

返回的图像每侧都有一个居中 5px 的阴影。

+ (UIImage*)imageWithShadowForImage:(UIImage *)initialImage {

    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef shadowContext = CGBitmapContextCreate(NULL, initialImage.size.width + 10, initialImage.size.height + 10, CGImageGetBitsPerComponent(initialImage.CGImage), 0, colourSpace, kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colourSpace);
    
    CGContextSetShadowWithColor(shadowContext, CGSizeMake(0,0), 5, [UIColor blackColor].CGColor);
    CGContextDrawImage(shadowContext, CGRectMake(5, 5, initialImage.size.width, initialImage.size.height), initialImage.CGImage);
    
    CGImageRef shadowedCGImage = CGBitmapContextCreateImage(shadowContext);
    CGContextRelease(shadowContext);
    
    UIImage * shadowedImage = [UIImage imageWithCGImage:shadowedCGImage];
    CGImageRelease(shadowedCGImage);
    
    return shadowedImage;
}

4
投票

我在图像上绘制阴影的方法。它具有自定义阴影参数,并以正确的尺寸和屏幕比例渲染图像。应该在 UIImage 扩展中实现。 (斯威夫特 3)。

func addingShadow(blur: CGFloat = 1, shadowColor: UIColor = UIColor(white: 0, alpha: 1), offset: CGSize = CGSize(width: 1, height: 1) ) -> UIImage {

    UIGraphicsBeginImageContextWithOptions(CGSize(width: size.width + 2 * blur, height: size.height + 2 * blur), false, 0)
    let context = UIGraphicsGetCurrentContext()!

    context.setShadow(offset: offset, blur: blur, color: shadowColor.cgColor)
    draw(in: CGRect(x: blur - offset.width / 2, y: blur - offset.height / 2, width: size.width, height: size.height))
    let image = UIGraphicsGetImageFromCurrentImageContext()!

    UIGraphicsEndImageContext()

    return image
}

0
投票

如本例所示,要使图像成为

CGImage
,请尝试

self.shadowImage.CGImage

0
投票

GK100 在 Swift 2 / iOS9 中的答案

func addShadow(blurSize: CGFloat = 6.0) -> UIImage {

    let data : UnsafeMutablePointer<Void> = nil
    let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()!
    let bitmapInfo : CGBitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue)

    let myColorValues:[CGFloat] = [0.0, 0.0, 0.0, 0.8]
    let myColor = CGColorCreate(colorSpace, myColorValues)

    let shadowContext : CGContextRef = CGBitmapContextCreate(data, Int(self.size.width + blurSize), Int(self.size.height + blurSize), CGImageGetBitsPerComponent(self.CGImage), 0, colorSpace, bitmapInfo.rawValue)!

    CGContextSetShadowWithColor(shadowContext, CGSize(width: blurSize/2,height: -blurSize/2),  blurSize, myColor)
    CGContextDrawImage(shadowContext, CGRect(x: 0, y: blurSize, width: self.size.width, height: self.size.height), self.CGImage)

    let shadowedCGImage : CGImageRef = CGBitmapContextCreateImage(shadowContext)!
    let shadowedImage : UIImage = UIImage(CGImage: shadowedCGImage)

    return shadowedImage
}

0
投票

我为

UIImage
创建了一个更完整的扩展函数,可以添加阴影。

我使用

radius
而不是
blur
来匹配将阴影添加到
CGLayer
的方式,但您可以按照自己的喜好进行操作。

extension UIImage {
    func withShadow(offset: CGSize, radius: CGFloat, color: UIColor) -> UIImage {
        let format = UIGraphicsImageRendererFormat()
        format.scale = scale
        return UIGraphicsImageRenderer(size: size, format: format).image { context in
            context.cgContext.setShadow(offset: offset, blur: radius * 2, color: color.cgColor)
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.