Создать новый UIImage, добавив тень к существующему UIImage
Я взглянул на этот вопрос: UIImage Shadow Trouble
Но принятый ответ не работал для меня.
То, что я пытаюсь сделать, это взять UIImage и добавить тень к нему, а затем вернуть совершенно новый UIImage, shadow и все.
Вот что я пытаюсь:
- (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;
}
В результате я получаю точно такое же изображение, как и раньше, с помощью этого метода.
Я делаю это правильно, или я что-то упускаю из виду?
7 ответов
Есть несколько проблем с вашим кодом:
- Целевое изображение слишком маленькое. Убедитесь, что есть достаточно места, чтобы нарисовать тень.
- Рассмотреть возможность использования
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;
}
Версия iOS8 / Swift (сделана как расширение 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()!)
}
}
(конвертировано из ответов Лорана Этиэмбла и Capikaw)
РЕДАКТИРОВАТЬ 2016/10/31: преобразован в Swift 3, и удалены все ненужные вещи
Использование:
let sourceImage: UIImage(named: "some image")
let shadowImage = sourceImage.addShadow()
Пытаясь использовать здесь некоторые из других примеров, я заметил, что они либо жестко запрограммировали смещение и размытие, либо не учитывают их правильно при определении размера и позиционирования вывода.
Следующий код решает эти проблемы (он основан на оригинальной работе Игоря Кулагина):
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
}
}
Мне нужен был метод, который принимал бы UIImage в качестве параметра и возвращал немного больший UIImage с тенями. Сообщения здесь были очень полезны для меня, так что вот мой метод. Возвращенное изображение имеет центрированную тень размером 5 пикселей на каждой стороне.
+(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;
}
Мне нужно больше тени для моих 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];
Мой метод, который рисует тень на изображении. Он имеет пользовательские параметры тени и отображает изображение в правильном размере и масштабе экрана. Должно быть реализовано в расширении 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
}
Ответ 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
}
Чтобы сделать изображение CGImage
как в этом случае, попробуйте
self.shadowImage.CGImage