代码之家  ›  专栏  ›  技术社区  ›  Toma

createCGImage(\:from:)未使用正确的rect

  •  0
  • Toma  · 技术社区  · 7 年前

    我试图模糊图像的一部分:

    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)
    

    然而,当应用程序启动时,图片的错误部分就会模糊。下面是图像;底部的矩形应该会模糊其后面的图像,但会模糊其他部分。

    image

    3 回复  |  直到 7 年前
        1
  •  1
  •   Ray    7 年前

    看来你走对了方向。有几件事需要解决。。。

    可以通过将屏幕比例传递给方法并更新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)
    
        2
  •  1
  •   rickster    7 年前

    您是否注意到您的插入图像看起来不仅模糊,而且放大了?这应该是一个提示。。。

    UIKit视图、帧和图像大小以“点”为单位,这是一种用于进行布局的显示分辨率无关的单位。您的iPhone X显示器的点宽度与iPhone 6/7/8显示器的点宽度相同,尽管iPhone X的像素更多。(也就是说,它们在比例因子上有所不同:iPhone 6/7/8是2倍比例,iPhone X是3倍。)

    CGImage CIImage 测量像素,而不是点,因此在使用UIKit中的视图尺寸时,需要考虑屏幕的比例因子。由于要创建从整个视图模糊的图像,然后仅渲染模糊图像的一部分,因此处理比例因子的位置将在 createCGImage(_:from:) 调用只需将矩形的原点和大小乘以整个视图的 contentScaleFactor .

    此外,请注意,您不一定需要通过 CGImage公司 从中获取 UIImage CIImage公司 然后返回,您可以将外部图像视图的图像传递给 CIImage(image:) ,并将过滤器的结果 UIImage(ciImage:) . 在这种情况下,UIKit和CoreImage可以为您管理渲染上下文,并可能确保更好的性能(例如,通过将整个管道保持在GPU上)。但是,由于使用render调用指定裁剪矩形,因此需要在其他地方执行该操作,例如 CIImage公司 cropped(to:) 呼叫

        3
  •  0
  •   Shehata Gamal    7 年前

    问题是在内部添加任何覆盖 viewDidLoad 没有给出正确的框架尺寸,请将其添加到侧面 viewDidAppear