[英]Swift How do I convert a UIImageView into a UIImage Without Losing blur effect
I am making an app using Swift 4.0. 我正在使用Swift 4.0开发应用程序。 It is a sort of social media app.
这是一种社交媒体应用程序。 My app has a collectionView (the users feed) with multiple collectionViewCells.
我的应用程序有一个具有多个collectionViewCells的collectionView(用户供稿)。 The problem with this however is that for every cell I have, I am blurring a portion or sometimes all of the image.
但是,这样做的问题是,对于我拥有的每个单元,我都会模糊部分或全部图像。 This causes heavy lag on the device after a couple scrolls to the point where you can barely use it.
夫妇滚动到几乎无法使用设备的位置后,这会在设备上造成严重的延迟。
In order to counter this I thought it would make much more sense instead of blurring the cells image I would just blur it when the user uploads it into the sql database and when it shows up in other users feed/timeline they're iPhone won't have to blur the image because the image they pulled from the database is already pulled. 为了解决这个问题,我认为这将比模糊单元格图像更有意义,而只是在用户将其上传到sql数据库中并且当它出现在其他用户的供稿/时间轴中时,它们就会被iPhone所迷惑。不必模糊图像,因为他们从数据库中提取的图像已经被提取。
I have had some luck turning UIImageViews into UIImages but whenever I render it to an image the blurring effect gets distorted and essentially turns into a white overlay with a some transparency. 我很幸运地将UIImageViews转换为UIImages,但是每当我将其渲染为图像时,模糊效果就会失真,并且实质上变成具有一定透明度的白色覆盖层。
Code for turning UIImageViews into UIImages: 用于将UIImageViews转换为UIImages的代码:
extension UIImage {
convenience init(view: UIView) {
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: image!.cgImage!)
}
}
After that I simply call it with 之后,我简单地用
let background = UIImageView(frame: CGRect(x: 0, y: 0, width: cell.frame.width, height: 200))
background.image = profileImage
let label = UIBlurEffect(style: UIBlurEffectStyle.prominent)
let blurEffectView = UIVisualEffectView(effect: label)
blurEffectView.frame = CGRect(x: 0, y: 0, width: background.frame.width, height: background.frame.height)
background.addSubview(blurEffectView)
let secondImage = UIImage(view: background)
It may be hard to see but there is no blur in the first image it is just a transparent white overlay 可能很难看到,但第一张图像中没有模糊,只是透明的白色覆盖层
You need to take a snapshot of the container view after the visual effect view is applied. 应用视觉效果视图后,需要对容器视图进行快照。 I will demonstrate a flow which will work.
我将演示一个有效的流程。
Your Controller: 您的控制器:
class PreviewController: UIViewController,VisualEffectCustomDelegate{
@IBOutlet weak var screenshotView: UIView!
@IBOutlet weak var previewImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
addBlur()
}
func addBlur(){
let label = UIBlurEffect(style: UIBlurEffectStyle.prominent)
let blurEffectView = CustomVisualEffect(effect: label)
blurEffectView.frame = CGRect(x: 0, y: 0, width: screenshotView.frame.width, height: screenshotView.frame.height)
blurEffectView.delegate = self
screenshotView.addSubview(blurEffectView)
}
func viewAppeared() {
print("Appeared")
previewImageView.image = screenshotView.screenShot
}
}
extension UIView {
var screenShot: UIImage? {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, 1.0);
if let _ = UIGraphicsGetCurrentContext() {
drawHierarchy(in: bounds, afterScreenUpdates: true)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return screenshot
}
return nil
}
}
We implement a protocol VisualEffectCustomDelegate to the controller class. 我们为控制器类实现了协议VisualEffectCustomDelegate。
protocol VisualEffectCustomDelegate {
func viewAppeared()
}
Create your own custom class as a child of VisualEffectView class: 创建自己的自定义类作为VisualEffectView类的子类:
class CustomVisualEffect: UIVisualEffectView {
var delegate: VisualEffectCustomDelegate!
override init(effect: UIVisualEffect?) {
super.init(effect: effect)
}
convenience init(){
self.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMoveToWindow() {
print("Visible Now")
delegate.viewAppeared()
}
}
The above implementation will work. 以上实现将起作用。 What happens here is as follows: Your controller class confirms to a protocol VisualEffectCustomDelegate, which has a function named viewAppeared.
发生的情况如下:控制器类确认协议VisualEffectCustomDelegate,该协议具有一个名为viewAppeared的函数。 We are going to use this method when we know for sure that the visual effect view is visible in the window.
当我们确定在窗口中可见视觉效果视图时,将使用此方法。 We use the didMoveToWindow method of the UIView class to fire the protocol method.
我们使用UIView类的didMoveToWindow方法来触发协议方法。 When you initiate the CustomVisualEffect view in your controller, pass the controller to the view object.
在控制器中启动CustomVisualEffect视图时,请将控制器传递给视图对象。 I hope this is clear.
我希望这很清楚。
Since you are dealing with a UITableView/UICollectionView, make the changes to the code as you see fit. 由于您正在处理UITableView / UICollectionView,因此请根据需要对代码进行更改。
// try like this //这样尝试
public extension UIImageView {
public func snapshotImage() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
drawHierarchy(in: bounds, afterScreenUpdates: false)
let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return snapshotImage
}
} }
// get image from your imageview
let image = background.snapshotImage()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.