Ios createCGImage(xAE:from:)未使用正确的rect
我试图模糊图像的一部分:Ios createCGImage(xAE:from:)未使用正确的rect,ios,swift,uiimage,core-image,Ios,Swift,Uiimage,Core Image,我试图模糊图像的一部分: extension UIImage { func blur(rect: CGRect, radius: CGFloat) -> UIImage? { let context = CIContext(options: nil) let inputImage = CIImage(cgImage: self.cgImage!) let filter = CIFilter(name: "CIGaussianBlur"
extension UIImage {
func blur(rect: CGRect, radius: CGFloat) -> UIImage? {
let context = CIContext(options: nil)
let inputImage = CIImage(cgImage: self.cgImage!)
let filter = CIFilter(name: "CIGaussianBlur")
filter?.setValue(inputImage, forKey: kCIInputImageKey)
filter?.setValue(radius, forKey: kCIInputRadiusKey)
let outputImage = filter?.outputImage
if let outputImage = outputImage {
let cgImage = context.createCGImage(outputImage, from: rect)
if let cgImage = cgImage {
return UIImage(cgImage: cgImage)
}
}
return nil
}
}
用法:
guard let blurredImage = self.imageView.image?.blur(rect: self.blur.frame, radius: 2.0) else { fatalError("could not blur image") }
let img = UIImageView(image: blurredImage)
img.frame = self.blur.frame
self.view.addSubview(img)
然而,当应用程序启动时,图片的错误部分会模糊。下面是图片;底部的矩形应该模糊其后面的图像,但它会模糊其他部分
问题是在
viewDidLoad
中添加任何覆盖都不会给出正确的帧大小在侧边添加viewDidAppear
问题是在viewDidLoad
中添加任何覆盖都不会给出正确的帧大小在侧边添加viewDidAppear
您注意到您的插入图像了吗看起来不只是模糊,而是放大了?这应该是一个提示
UIKit视图、帧和图像大小以“点”为单位,这是一种用于布局的显示分辨率无关的单位。您的iPhoneX显示器的点宽度与iPhone6/7/8显示器的点宽度相同,尽管iPhoneX的像素更多。(也就是说,它们的比例系数不同:iPhone6/7/8是2倍的比例,iPhoneX是3倍的比例。)
CGImage
和CIImage
测量像素,而不是点,因此在使用UIKit中的视图尺寸时,需要考虑屏幕的比例因子。由于您正在创建要从整个视图模糊的图像,然后仅渲染模糊图像的一部分,因此处理比例因子的位置将在createCGImage(u:from:)
call中-只需将矩形的原点和大小乘以整个视图的角度即可
另外,请注意,从
UIImage
到CIImage
再返回,不一定需要通过CGImage
,您可以将外部图像视图的图像传递到,并将过滤器的结果传递到。在这种情况下,UIKit和CoreImage为您管理渲染上下文,并可能确保更好的性能(例如,通过将整个管道保持在GPU上)。但是,由于使用render调用来指定裁剪矩形,因此需要在其他地方执行此操作—例如,CIImage
调用。您是否注意到插入图像看起来不仅模糊,而且放大了?这应该是一个提示
UIKit视图、帧和图像大小以“点”为单位,这是一种用于布局的显示分辨率无关的单位。您的iPhoneX显示器的点宽度与iPhone6/7/8显示器的点宽度相同,尽管iPhoneX的像素更多。(也就是说,它们的比例系数不同:iPhone6/7/8是2倍的比例,iPhoneX是3倍的比例。)
CGImage
和CIImage
测量像素,而不是点,因此在使用UIKit中的视图尺寸时,需要考虑屏幕的比例因子。由于您正在创建要从整个视图模糊的图像,然后仅渲染模糊图像的一部分,因此处理比例因子的位置将在createCGImage(u:from:)
call中-只需将矩形的原点和大小乘以整个视图的角度即可
另外,请注意,从
UIImage
到CIImage
再返回,不一定需要通过CGImage
,您可以将外部图像视图的图像传递到,并将过滤器的结果传递到。在这种情况下,UIKit和CoreImage为您管理渲染上下文,并可能确保更好的性能(例如,通过将整个管道保持在GPU上)。但是,由于使用render调用来指定裁剪矩形,因此需要在其他地方执行此操作—例如,CIImage
调用。看起来您的操作是正确的。有几件事需要解决
可以通过将屏幕比例传递到方法并更新rect的原点和大小来调整比例
由于CoreGraphics和UIKit坐标系之间的转换,模糊部分的定位被关闭。为了解决这个问题,您只需要将窗口的高度减去要模糊的矩形的位置和高度(考虑比例)
请查看以下代码:
extension UIImage {
func blur(rect: CGRect, radius: CGFloat, scale: CGFloat) -> UIImage? {
if let cgImage = self.cgImage {
let inputImage = CIImage(cgImage: cgImage)
let context = CIContext(options: nil)
let filter = CIFilter(name: "CIGaussianBlur")
filter?.setValue(inputImage, forKey: kCIInputImageKey)
filter?.setValue(radius, forKey: kCIInputRadiusKey)
// Rect bounds need to be adjusted for based on Image's Scale and Container's Scale
// Y Position Needs to be Inverted because of UIKit <-> CoreGraphics Coordinate Systems
let newRect = CGRect(
x: rect.minX * scale,
y: ((((CGFloat(cgImage.height) / scale)) - rect.minY - rect.height) * scale),
width: rect.width * scale,
height: rect.height * scale
)
if let outputImage = filter?.outputImage,
let cgImage = context.createCGImage(outputImage, from: newRect) {
return UIImage(
cgImage: cgImage,
scale: scale,
orientation: imageOrientation
)
}
}
return nil
}
}
let blurredImage = self.imageView.image?.blur(rect: self.blur.frame, radius: 2.0, scale: UIScreen.main.scale)
扩展UIImage{
func模糊(rect:CGRect,半径:CGFloat,比例:CGFloat)->UIImage{
如果让cgImage=self.cgImage{
让inputImage=CIImage(cgImage:cgImage)
let context=CIContext(选项:nil)
let filter=CIFilter(名称:“CIGaussianBlur”)
过滤器?.setValue(输入图像,forKey:kCIInputImageKey)
过滤器?.setValue(半径,分叉:kCIInputRadiusKey)
//矩形边界需要根据图像的比例和容器的比例进行调整
//由于UIKit CoreGraphics坐标系,Y位置需要反转
设newRect=CGRect(
x:rect.minX*比例,
y:(((CGFloat(cgImage.height)/比例)-rect.minY-rect.height)*比例),
宽度:矩形宽度*比例,
高度:矩形高度*比例
)
如果let outputImage=filter?.outputImage,
让cgImage=context.createCGImage(outputImage,from:newRect){
返回UIImage(
cgImage:cgImage,
比例:比例,
方向:图像方向
)
}
}
归零
}
}
让blurredImage=self.imageView.image?.blur(rect:self.blur.frame,半径:2.0,比例:UIScreen.main.scale)
看来你走对了方向。有几件事需要解决 可以通过将屏幕比例传递到方法并更新rect的原点和大小来调整比例 由于CoreGraphics和UIKit坐标系之间的转换,模糊部分的定位被关闭。为了解决这个问题,您只需要将窗口的高度减去要模糊的矩形的位置和高度(考虑比例) 请查看以下代码:
extension UIImage {
func blur(rect: CGRect, radius: CGFloat, scale: CGFloat) -> UIImage? {
if let cgImage = self.cgImage {
let inputImage = CIImage(cgImage: cgImage)
let context = CIContext(options: nil)
let filter = CIFilter(name: "CIGaussianBlur")
filter?.setValue(inputImage, forKey: kCIInputImageKey)
filter?.setValue(radius, forKey: kCIInputRadiusKey)
// Rect bounds need to be adjusted for based on Image's Scale and Container's Scale
// Y Position Needs to be Inverted because of UIKit <-> CoreGraphics Coordinate Systems
let newRect = CGRect(
x: rect.minX * scale,
y: ((((CGFloat(cgImage.height) / scale)) - rect.minY - rect.height) * scale),
width: rect.width * scale,
height: rect.height * scale
)
if let outputImage = filter?.outputImage,
let cgImage = context.createCGImage(outputImage, from: newRect) {
return UIImage(
cgImage: cgImage,
scale: scale,
orientation: imageOrientation
)
}
}
return nil
}
}
let blurredImage = self.imageView.image?.blur(rect: self.blur.frame, radius: 2.0, scale: UIScreen.main.scale)
扩展UIImage{
func模糊(矩形:CGRect,半径:CGFloat,sca