Commit 2af4cf03 by Daniel Dahan

Merge pull request #291 from gilthonweapps/UIImageBlur

Ui image blur
parents abfa095e b5964b51
......@@ -29,6 +29,7 @@
*/
import UIKit
import Accelerate
public extension UIImage {
/**
......@@ -46,4 +47,128 @@ public extension UIImage {
UIGraphicsEndImageContext()
return image
}
/**
Applies a blur effect to a UIImage
- Parameter blurRadius: The radius of the blur effect
- Parameter tintColor: The color used for the blur effect (optional)
- Parameter saturationDeltaFactor: The delta factor for the saturation of the blur effect
- Returns: a UIImage
*/
func applyBlur(blurRadius: CGFloat, tintColor: UIColor?, saturationDeltaFactor: CGFloat) -> UIImage? {
let screenScale = UIScreen.mainScreen().scale
let imageRect = CGRect(origin: CGPointZero, size: size)
var effectImage = self
let hasBlur = blurRadius > CGFloat(FLT_EPSILON)
let hasSaturationChange = fabs(saturationDeltaFactor - 1.0) > CGFloat(FLT_EPSILON)
if hasBlur || hasSaturationChange {
func createEffectBuffer(context: CGContext) -> vImage_Buffer {
let data = CGBitmapContextGetData(context)
let width = vImagePixelCount(CGBitmapContextGetWidth(context))
let height = vImagePixelCount(CGBitmapContextGetHeight(context))
let rowBytes = CGBitmapContextGetBytesPerRow(context)
return vImage_Buffer(data: data, height: height, width: width, rowBytes: rowBytes)
}
UIGraphicsBeginImageContextWithOptions(size, false, screenScale)
let effectInContext = UIGraphicsGetCurrentContext()
CGContextScaleCTM(effectInContext, 1.0, -1.0)
CGContextTranslateCTM(effectInContext, 0, -size.height)
CGContextDrawImage(effectInContext, imageRect, self.CGImage)
var effectInBuffer = createEffectBuffer(effectInContext!)
UIGraphicsBeginImageContextWithOptions(size, false, screenScale)
let effectOutContext = UIGraphicsGetCurrentContext()
var effectOutBuffer = createEffectBuffer(effectOutContext!)
if hasBlur {
let inputRadius = blurRadius * screenScale
var radius = UInt32(floor(inputRadius * 3.0 * CGFloat(sqrt(2 * M_PI)) / 4 + 0.5))
if radius % 2 != 1 {
radius += 1 // force radius to be odd so that the three box-blur methodology works.
}
let imageEdgeExtendFlags = vImage_Flags(kvImageEdgeExtend)
vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, nil, 0, 0, radius, radius, nil, imageEdgeExtendFlags)
vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, nil, 0, 0, radius, radius, nil, imageEdgeExtendFlags)
vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, nil, 0, 0, radius, radius, nil, imageEdgeExtendFlags)
}
var effectImageBuffersAreSwapped = false
if hasSaturationChange {
let s: CGFloat = saturationDeltaFactor
let floatingPointSaturationMatrix: [CGFloat] = [
0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0,
0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0,
0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0,
0, 0, 0, 1
]
let divisor: CGFloat = 256
let matrixSize = floatingPointSaturationMatrix.count
var saturationMatrix = [Int16](count: matrixSize, repeatedValue: 0)
for i: Int in 0 ..< matrixSize {
saturationMatrix[i] = Int16(round(floatingPointSaturationMatrix[i] * divisor))
}
if hasBlur {
vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, Int32(divisor), nil, nil, vImage_Flags(kvImageNoFlags))
effectImageBuffersAreSwapped = true
} else {
vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, Int32(divisor), nil, nil, vImage_Flags(kvImageNoFlags))
}
}
if !effectImageBuffersAreSwapped {
effectImage = UIGraphicsGetImageFromCurrentImageContext()
}
UIGraphicsEndImageContext()
if effectImageBuffersAreSwapped {
effectImage = UIGraphicsGetImageFromCurrentImageContext()
}
UIGraphicsEndImageContext()
}
// Set up output context.
UIGraphicsBeginImageContextWithOptions(size, false, screenScale)
let outputContext = UIGraphicsGetCurrentContext()
CGContextScaleCTM(outputContext, 1.0, -1.0)
CGContextTranslateCTM(outputContext, 0, -size.height)
// Draw base image.
CGContextDrawImage(outputContext, imageRect, self.CGImage)
// Draw effect image.
if hasBlur {
CGContextSaveGState(outputContext)
CGContextDrawImage(outputContext, imageRect, effectImage.CGImage)
CGContextRestoreGState(outputContext)
}
// Add in color tint.
if let color = tintColor {
CGContextSaveGState(outputContext)
CGContextSetFillColorWithColor(outputContext, color.CGColor)
CGContextFillRect(outputContext, imageRect)
CGContextRestoreGState(outputContext)
}
// Output image is ready.
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment