【问题标题】:Creating a blur effect in iOS7在 iOS7 中创建模糊效果
【发布时间】:2013-10-26 07:12:30
【问题描述】:

几个小时后,我一直在寻找这个问题的答案,但我就是想不通。当我按下“按钮”按钮时,我想为图像添加高斯模糊效果。用户是添加图像的人。

我根据来自 SO 和网络上其他地方的来源为“按钮”创建了一个动作。不起作用。我究竟做错了什么?任何代码将不胜感激。这是我的“按钮”操作:

- (IBAction)test:(id)sender {
    CIFilter *gaussianBlurFilter = [CIFilter filterWithName: @"CIGaussianBlur"];
    [gaussianBlurFilter setValue:imageView.image forKey: @"inputImage"];
    [gaussianBlurFilter setValue:[NSNumber numberWithFloat: 10] forKey: @"inputRadius"];
}

如果您需要我为回答问题所做的其他任何事情,请告诉我:D

【问题讨论】:

    标签: uiimage ios7 cifilter ciimage


    【解决方案1】:

    CIFilter 的输入必须是 CIImage 而不是 UIImage

    【讨论】:

      【解决方案2】:

      三个观察:

      1. 您需要将inputImage 设置为您的UIImage 中的CIImage

        [gaussianBlurFilter setValue:[CIImage imageWithCGImage:[imageView.image CGImage]] forKey:kCIInputImageKey];
        
      2. 我没有看到你在抢outputImage,例如:

        CIImage *outputImage = [gaussianBlurFilter outputImage];
        
      3. 您大概想将 CIImage 转换回 UIImage

      所以,把所有这些放在一起:

      CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
      [gaussianBlurFilter setDefaults];
      CIImage *inputImage = [CIImage imageWithCGImage:[imageView.image CGImage]];
      [gaussianBlurFilter setValue:inputImage forKey:kCIInputImageKey];
      [gaussianBlurFilter setValue:@10 forKey:kCIInputRadiusKey];
      
      CIImage *outputImage = [gaussianBlurFilter outputImage];
      CIContext *context   = [CIContext contextWithOptions:nil];
      CGImageRef cgimg     = [context createCGImage:outputImage fromRect:[inputImage extent]];  // note, use input image extent if you want it the same size, the output image extent is larger
      UIImage *image       = [UIImage imageWithCGImage:cgimg];
      CGImageRelease(cgimg);
      

      或者,如果您转到WWDC 2013 sample code(需要付费开发者订阅)并下载iOS_UIImageEffects,则可以获取UIImage+ImageEffects 类别。这提供了一些新方法:

      - (UIImage *)applyLightEffect;
      - (UIImage *)applyExtraLightEffect;
      - (UIImage *)applyDarkEffect;
      - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;
      - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;
      

      因此,要模糊和成像并使其变亮(给出“毛玻璃”效果),您可以这样做:

      UIImage *newImage = [image applyLightEffect];
      

      有趣的是,Apple 的代码使用CIFilter,而是调用vImage high-performance image processing framework 中的vImageBoxConvolve_ARGB8888

      这项技术在 WWDC 2013 视频Implementing Engaging UI on iOS 中有说明。


      我知道问题是关于 iOS 7,但现在在 iOS 8 中,可以使用 UIBlurEffect 为任何 UIView 对象添加模糊效果:

      UIVisualEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
      UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];    
      effectView.frame = imageView.bounds;
      [imageView addSubview:effectView];
      

      【讨论】:

      • 可以说我在 ibaction 中没有任何代码,我会在 ibaction 中写什么?这是你写的最后一段代码吗?顺便说一句,感谢您的精彩回复,很抱歉没有这么多理解:D
      • 我收到一条警告“未使用的变量图像”,这是代码的倒数第二行
      • @user2891448 我不确定你想用image 做什么。也许更新imageView.image = image;
      • 最后一件事,我想用一个变量设置模糊量的值,我该怎么做?这是在 [gaussianBlurFilter setValue:@10 forKey:kCIInputRadiusKey];
      • @user2891448 假设你有一个名为CGFloat 的变量radius,那么你会做[gaussianBlurFilter setValue:@(radius) forKey:kCIInputRadiusKey];
      【解决方案3】:

      这对我有用,但是速度很慢。我将在应用程序加载时进行转换,并在许多地方使用一次转换后的图像。

      此模糊效果适用于 iOS 8.4。 Swift 语言。

      override func viewDidLoad()
      {
          super.viewDidLoad()
      
          var backgroundImage = self.blurImage(UIImage(named: "background.jpg")!)
      
          self.view.backgroundColor = UIColor(patternImage:backgroundImage)
      }
      
      func blurImage(imageToBlur:UIImage) -> UIImage
      {
          var gaussianBlurFilter = CIFilter(name: "CIGaussianBlur")
          gaussianBlurFilter.setValue(CIImage(CGImage: imageToBlur.CGImage), forKey:kCIInputImageKey)
      
          var inputImage = CIImage(CGImage: imageToBlur.CGImage)
      
          var outputImage = gaussianBlurFilter.outputImage
          var context = CIContext(options: nil)
          var cgimg = context.createCGImage(outputImage, fromRect: inputImage.extent())
      
          return UIImage(CGImage: cgimg)!
      }
      

      【讨论】:

      • 这很有趣..但也很慢.. :/ 至少在 Apple TV 上
      • 是的,它很慢:/。您可以进行“按需”模糊,这可能会有所帮助,或者如果您在应用程序中有一些加载,则调用 blurImage 函数。在某些时候,我保存了模糊的图像,所以当我需要它们时,我可以从内存或其他地方加载它们,而不是再次调用该函数。希望这对您有所帮助或指出正确的方向:)))
      【解决方案4】:

      Swift 2.0

      对 UIImageView 进行扩展。 (File-New-File-Empty Swift File - 将其命名为 Extensions。)

      import Foundation
      import UIKit
      
      extension UIImageView{
      
       //Method 1
       func makeBlurImage(targetImageView:UIImageView?)
       {
        let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = targetImageView!.bounds
      
        blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] // for supporting device rotation
        targetImageView?.addSubview(blurEffectView)
       }
       //Method 2
       func convertToBlurImage(imageToBlur:UIImage) -> UIImage
       {
        let gaussianBlurFilter = CIFilter(name: "CIGaussianBlur")
        gaussianBlurFilter!.setValue(CIImage(CGImage: imageToBlur.CGImage!), forKey:kCIInputImageKey)
      
        let initialImage = CIImage(CGImage: imageToBlur.CGImage!)
      
        let finalImage = gaussianBlurFilter!.outputImage
        let finalImagecontext = CIContext(options: nil)
      
        let finalCGImage = finalImagecontext.createCGImage(finalImage!, fromRect: initialImage.extent)
        return UIImage(CGImage: finalCGImage)
       }
      }
      

      用法:

      使用方法一:

      override func viewDidLoad() {
        super.viewDidLoad()
      
        let sampleImageView = UIImageView(frame: CGRectMake(0, 200, 300, 325))
        let sampleImage:UIImage = UIImage(named: "ic_120x120")!
        sampleImageView.image =  sampleImage
      
        //Convert To Blur Image Here
        sampleImageView.makeBlurImage(sampleImageView)
      
        self.view.addSubview(sampleImageView)
       }
      

      使用方法二:

         override func viewDidLoad() {
            super.viewDidLoad()
      
            let sampleImageView = UIImageView(frame: CGRectMake(0, 200, 300, 325))
            let sampleImage:UIImage = UIImage(named: "ic_120x120")!
      
            //Convert to Blurred Image Here
            let sampleImage2 =  sampleImageView.convertToBlurImage(sampleImage)
            sampleImageView.image =  sampleImage2
      
            self.view.addSubview(sampleImageView)
           }
      

      【讨论】:

        【解决方案5】:

        这是一个图像模糊的扩展

        斯威夫特 3

        extension UIImage {
        
            public func blurImage(radius: CGFloat) -> UIImage {
        
                let inputImage = CIImage(image: self)!
        
                let parameters: [String:Any] = [
                    kCIInputRadiusKey: radius,
                    kCIInputImageKey: inputImage
                ]
                let filter = CIFilter(name: "CIGaussianBlur",
                                      withInputParameters: parameters)!
        
                let cgimg = CIContext().createCGImage(filter.outputImage!, from: inputImage.extent)
                return UIImage(cgImage: cgimg!)
            }
        
        }
        

        【讨论】:

          【解决方案6】:

          Swift 4 UIImage 扩展,无需强制解包:

          extension UIImage {
              /// Applies a gaussian blur to the image.
              ///
              /// - Parameter radius: Blur radius.
              /// - Returns: A blurred image.
              func blur(radius: CGFloat = 6.0) -> UIImage? {
                  let context = CIContext()
                  guard let inputImage = CIImage(image: self) else { return nil }
          
                  guard let clampFilter = CIFilter(name: "CIAffineClamp") else { return nil }
                  clampFilter.setDefaults()
                  clampFilter.setValue(inputImage, forKey: kCIInputImageKey)
          
                  guard let blurFilter = CIFilter(name: "CIGaussianBlur") else { return nil }
                  blurFilter.setDefaults()
                  blurFilter.setValue(clampFilter.outputImage, forKey: kCIInputImageKey)
                  blurFilter.setValue(radius, forKey: kCIInputRadiusKey)
          
                  guard let blurredImage = blurFilter.value(forKey: kCIOutputImageKey) as? CIImage,
                      let cgImage = context.createCGImage(blurredImage, from: inputImage.extent) else { return nil }
          
                  let resultImage = UIImage(cgImage: cgImage, scale: scale, orientation: imageOrientation)
                  return resultImage
              }
          }
          

          我强烈建议在后台线程上模糊图像:

          let image = UIImage(named: "myImage")
          DispatchQueue.global(qos: .userInitiated).async {
              let blurredImage = image.blur()
              DispatchQueue.main.async {
                  self.myImageView.image = blurredImage
              }
          }
          

          【讨论】:

          • 这样做后图像会被裁剪,有什么方法可以避免这种情况吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-05
          • 1970-01-01
          相关资源
          最近更新 更多