-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(blur-processing): change to Metal API
- Loading branch information
1 parent
f26e7fa
commit 25b20fc
Showing
6 changed files
with
95 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,65 @@ | ||
// | ||
// UIImage+Blur.swift | ||
// ShadowView | ||
// | ||
// Created by Pierre Perrin on 25/07/2017. | ||
// Copyright © 2017 Pierreperrin. All rights reserved. | ||
// | ||
|
||
import UIKit | ||
import CoreGraphics | ||
import CoreImage | ||
import Metal | ||
import UIKit | ||
|
||
extension UIImage{ | ||
|
||
/// Resize the image to a centain percentage | ||
extension UIImage { | ||
/// Resize the image to a certain percentage | ||
/// | ||
/// - Parameter percentage: Percentage value | ||
/// - Returns: UIImage(Optional) | ||
func resized(withPercentage percentage: CGFloat) -> UIImage? { | ||
let canvasSize = size.scaled(by: percentage) | ||
UIGraphicsBeginImageContextWithOptions(canvasSize, false, scale) | ||
defer { UIGraphicsEndImageContext() } | ||
draw(in: CGRect(origin: .zero, size: canvasSize)) | ||
return UIGraphicsGetImageFromCurrentImageContext() | ||
return resized(toSize: size.scaled(by: percentage)) | ||
} | ||
|
||
|
||
/// Resize the image to a certain width, maintaining aspect ratio | ||
/// | ||
/// - Parameter width: Desired width | ||
/// - Returns: UIImage(Optional) | ||
func resized(toWidth width: CGFloat) -> UIImage? { | ||
let canvasSize = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height))) | ||
UIGraphicsBeginImageContextWithOptions(canvasSize, false, scale) | ||
let height = CGFloat(ceil(width / size.width * size.height)) | ||
return resized(toSize: CGSize(width: width, height: height)) | ||
} | ||
|
||
/// Apply a Gaussian blur to the image using Metal GPU acceleration | ||
/// | ||
/// - Parameter blurRadius: The blur radius | ||
/// - Returns: UIImage(Optional) | ||
func applyBlur(blurRadius: CGFloat) -> UIImage? { | ||
guard let ciImage = CIImage(image: self) else { return nil } | ||
guard let filter = CIFilter(name: "CIGaussianBlur") else { return nil } | ||
|
||
filter.setValue(ciImage, forKey: kCIInputImageKey) | ||
filter.setValue(blurRadius, forKey: kCIInputRadiusKey) | ||
|
||
// Create a Metal-backed CIContext for GPU acceleration | ||
guard let device = MTLCreateSystemDefaultDevice() else { return nil } | ||
let context = CIContext(mtlDevice: device) | ||
|
||
guard let output = filter.outputImage else { return nil } | ||
guard let cgImage = context.createCGImage(output, from: ciImage.extent) else { return nil } | ||
|
||
return UIImage(cgImage: cgImage) | ||
} | ||
|
||
/// General method for resizing an image to a specific size | ||
/// | ||
/// - Parameter size: Target size | ||
/// - Returns: UIImage(Optional) | ||
private func resized(toSize size: CGSize) -> UIImage? { | ||
UIGraphicsBeginImageContextWithOptions(size, false, scale) | ||
defer { UIGraphicsEndImageContext() } | ||
draw(in: CGRect(origin: .zero, size: canvasSize)) | ||
draw(in: CGRect(origin: .zero, size: size)) | ||
return UIGraphicsGetImageFromCurrentImageContext() | ||
} | ||
|
||
|
||
func applyBlur(blurRadius:CGFloat) -> UIImage?{ | ||
|
||
guard let ciImage = CIImage(image: self) else {return nil} | ||
|
||
if let filter = CIFilter(name: "CIGaussianBlur") { | ||
|
||
filter.setValue(ciImage, forKey: kCIInputImageKey) | ||
filter.setValue(blurRadius, forKey: kCIInputRadiusKey) | ||
let eaglContext = | ||
EAGLContext(api: EAGLRenderingAPI.openGLES3) | ||
?? EAGLContext(api: EAGLRenderingAPI.openGLES2) | ||
?? EAGLContext(api: EAGLRenderingAPI.openGLES1) | ||
|
||
let context = eaglContext == nil ? | ||
CIContext(options: nil) | ||
: CIContext(eaglContext: eaglContext!) | ||
|
||
if let output = filter.outputImage, | ||
let cgimg = context.createCGImage(output, from: ciImage.extent) | ||
{ | ||
return UIImage(cgImage: cgimg) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
|
||
extension CGSize { | ||
|
||
/// Generates a new size that is this size scaled by a cerntain percentage | ||
/// Generates a new size that is this size scaled by a certain percentage | ||
/// | ||
/// - Parameter percentage: the percentage to scale to | ||
/// - Returns: a new CGSize instance by scaling self by the given percentage | ||
/// - Parameter percentage: The percentage to scale to | ||
/// - Returns: A new CGSize instance by scaling self by the given percentage | ||
func scaled(by percentage: CGFloat) -> CGSize { | ||
return CGSize(width: width * percentage, height: height * percentage) | ||
} | ||
|
||
} |