2015-09-02 2 views
2

Как добиться размытия в реальном времени для UIImage на слайдереValueChanged (_ :)?Размытие в реальном времени для UIImage путем скольжения по iOS

@IBOutlet weak var imageView: UIImageView! 

@IBAction func sliderValueChanged(sender: UISlider) { 
    let blurRadius = sender.value 
    var img = imageView.image 

    // some image processing for img 

    //blurring for img 

    // some another image processing for img 

    imageView.image = img 
} 

не подходят размывание для UIImageView из-за присутствия другой обработки изображения.

Спасибо!

+0

https://github.com/cyndibaby905/TwitterCover – nathanwhy

+0

@nathanwhy К сожалению, TwitterCover только для UIViews, не UIImages – vkalit

ответ

1
- (UIImage *)blurWithCoreImage:(UIImage *)sourceImage 
{ 
    CIImage *inputImage = [CIImage imageWithCGImage:sourceImage.CGImage]; 

    // Apply Affine-Clamp filter to stretch the image so that it does not 
    // look shrunken when gaussian blur is applied 
    CGAffineTransform transform = CGAffineTransformIdentity; 
    CIFilter *clampFilter = [CIFilter filterWithName:@"CIAffineClamp"]; 
    [clampFilter setValue:inputImage forKey:@"inputImage"]; 
    [clampFilter setValue:[NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)] forKey:@"inputTransform"]; 

    // Apply gaussian blur filter with radius of 30 
    CIFilter *gaussianBlurFilter = [CIFilter filterWithName: @"CIGaussianBlur"]; 
    [gaussianBlurFilter setValue:clampFilter.outputImage forKey: @"inputImage"]; 
    [gaussianBlurFilter setValue:@30 forKey:@"inputRadius"]; 

    CIContext *context = [CIContext contextWithOptions:nil]; 
    CGImageRef cgImage = [context createCGImage:gaussianBlurFilter.outputImage fromRect:[inputImage extent]]; 

    // Set up output context. 
    UIGraphicsBeginImageContext(self.view.frame.size); 
    CGContextRef outputContext = UIGraphicsGetCurrentContext(); 

    // Invert image coordinates 
    CGContextScaleCTM(outputContext, 1.0, -1.0); 
    CGContextTranslateCTM(outputContext, 0, -self.view.frame.size.height); 

    // Draw base image. 
    CGContextDrawImage(outputContext, self.view.frame, cgImage); 

    // Apply white tint 
    CGContextSaveGState(outputContext); 
    CGContextSetFillColorWithColor(outputContext, [UIColor colorWithWhite:1 alpha:0.2].CGColor); 
    CGContextFillRect(outputContext, self.view.frame); 
    CGContextRestoreGState(outputContext); 

    // Output image is ready. 
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return outputImage; 
} 

Используя вышеприведенный код, вы можете размыть изображение. Надеюсь, это поможет.

+0

Спасибо вам, @ ashwinkumar-mangrulkar, я проверил, что и это работает! Но есть ли более быстрое решение? – vkalit

6

Для максимальной производительности вы должны использовать GLKView с CIFilter вместо UIImageView.

Одним из простейшей реализации будет что-то вроде этого (Xcode6/Swift1.2):

import UIKit 
import GLKit 

class BlurImageView: GLKView { 
    let clampFilter = CIFilter(name: "CIAffineClamp")! 
    let blurFilter = CIFilter(name: "CIGaussianBlur")! 
    let ciContext:CIContext 

    override init(frame: CGRect) { 
     let glContext = EAGLContext(API: .OpenGLES2) 
     ciContext = CIContext(
      EAGLContext: glContext, 
      options: [ 
       kCIContextWorkingColorSpace: NSNull() 
      ] 
     ) 
     super.init(frame: frame, context: glContext) 
     enableSetNeedsDisplay = true 
    } 

    required init(coder aDecoder: NSCoder) { 
     let glContext = EAGLContext(API: .OpenGLES2) 
     ciContext = CIContext(
      EAGLContext: glContext, 
      options: [ 
       kCIContextWorkingColorSpace: NSNull() 
      ] 
     ) 
     super.init(coder: aDecoder) 
     context = glContext 
     enableSetNeedsDisplay = true 
    } 

    @IBInspectable var inputImage: UIImage? { 
     didSet { 
      inputCIImage = inputImage.map { CIImage(image: $0)! } 
     } 
    } 

    @IBInspectable var blurRadius: Float = 0 { 
     didSet { 
      blurFilter.setValue(blurRadius, forKey: "inputRadius") 
      setNeedsDisplay() 
     } 
    } 

    var inputCIImage: CIImage? { 
     didSet { setNeedsDisplay() } 
    } 

    override func drawRect(rect: CGRect) { 
     if let inputCIImage = inputCIImage { 
      clampFilter.setValue(inputCIImage, forKey: kCIInputImageKey) 
      blurFilter.setValue(clampFilter.outputImage!, forKey: kCIInputImageKey) 
      let rect = CGRect(x: 0, y: 0, width: drawableWidth, height: drawableHeight) 
      ciContext.drawImage(blurFilter.outputImage!, inRect: rect, fromRect: inputCIImage.extent()) 
     } 
    } 
} 

Затем вы можете использовать это как:

class ViewController: UIViewController { 

    @IBOutlet var imageView: BlurImageView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     imageView.inputImage = UIImage(named:"testImage")! 
    } 

    @IBAction func sliderValueChanged(sender: UISlider) { 
     imageView.blurRadius = sender.value 
    } 
} 

См An Introduction to Core Image - objc.io и пример кода для более подробных объяснений и примеров.

+0

благодарим вас за отзыв! Но я получаю сообщение об ошибке в строке (imageView.inputImage = ...) «EXC_BAD_ACCESS (код = 1, адрес = 0x0) .Как я должен сделать правку initViewView? – vkalit

+1

Вот пример файла проекта :) https: // www. dropbox.com/s/kptb5sbz75fcgcx/CITest.zip?dl=0 – rintaro

+0

Привет, Ринтаро, Спасибо за этот замечательный ответ. Один быстрый вопрос: возможно ли генерировать быстрый результат для * UIImage * вместо CIImage/CGImage? Я имею в виду без чтобы преобразовать его каждый раз, когда он отображает. Лучший сценарий производительности –

Смежные вопросы