-
-
Save dautermann/f12ea0e17b309823ec9d6fb461a42ca4 to your computer and use it in GitHub Desktop.
Colorize / tint a UIImage (Swift 3 compatible)
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
import UIKit | |
extension UIImage { | |
// colorize image with given tint color | |
// this is similar to Photoshop's "Color" layer blend mode | |
// this is perfect for non-greyscale source images, and images that have both highlights and shadows that should be preserved | |
// white will stay white and black will stay black as the lightness of the image is preserved | |
func tint(tintColor: UIColor) -> UIImage? { | |
return modifiedImage { context, rect in | |
// draw black background - workaround to preserve color of partially transparent pixels | |
context.setBlendMode(.normal) | |
UIColor.black.setFill() | |
context.fill(rect) | |
// draw original image | |
context.setBlendMode(.normal) | |
if let cgImage = self.cgImage { | |
context.draw(cgImage, in: rect) | |
// tint image (loosing alpha) - the luminosity of the original image is preserved | |
context.setBlendMode(.color) | |
tintColor.setFill() | |
context.fill(rect) | |
// mask by alpha values of original image | |
context.setBlendMode(.destinationIn) | |
context.draw(cgImage, in: rect) | |
} | |
} | |
} | |
// fills the alpha channel of the source image with the given color | |
// any color information except to the alpha channel will be ignored | |
func fillAlpha(fillColor: UIColor) -> UIImage? { | |
return modifiedImage { context, rect in | |
// draw tint color | |
context.setBlendMode(.normal) | |
fillColor.setFill() | |
context.fill(rect) | |
// mask by alpha values of original image | |
context.setBlendMode(.destinationIn) | |
if let cgImage = self.cgImage { | |
context.draw(cgImage, in: rect) | |
} | |
} | |
} | |
private func modifiedImage( draw: (CGContext, CGRect) -> ()) -> UIImage? { | |
// using scale correctly preserves retina images | |
UIGraphicsBeginImageContextWithOptions(size, false, scale) | |
let context: CGContext! = UIGraphicsGetCurrentContext() | |
assert(context != nil) | |
// correctly rotate image | |
context.translateBy(x: 0, y: size.height); | |
context.scaleBy(x: 1.0, y: -1.0); | |
let rect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height) | |
draw(context, rect) | |
let image = UIGraphicsGetImageFromCurrentImageContext() | |
UIGraphicsEndImageContext() | |
return image | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment