109 lines
3.9 KiB
Swift
109 lines
3.9 KiB
Swift
//
|
|
// UIImage.swift
|
|
// Mastodon
|
|
//
|
|
// Created by sxiaojian on 2021/3/8.
|
|
//
|
|
|
|
import CoreImage
|
|
import CoreImage.CIFilterBuiltins
|
|
import UIKit
|
|
|
|
extension UIImage {
|
|
public static func placeholder(
|
|
size: CGSize = CGSize(width: 1, height: 1),
|
|
color: UIColor,
|
|
cornerRadius: CGFloat = 0
|
|
) -> UIImage {
|
|
let render = UIGraphicsImageRenderer(size: size)
|
|
|
|
return render.image { (context: UIGraphicsImageRendererContext) in
|
|
// set clear fill
|
|
context.cgContext.setFillColor(color.cgColor)
|
|
|
|
let rect = CGRect(origin: .zero, size: size)
|
|
|
|
// clip corner if needs
|
|
if cornerRadius > 0 {
|
|
let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
|
|
context.cgContext.addPath(path)
|
|
context.cgContext.clip(using: .evenOdd)
|
|
}
|
|
|
|
// set fill
|
|
context.fill(rect)
|
|
}
|
|
}
|
|
}
|
|
|
|
// refs: https://www.hackingwithswift.com/example-code/media/how-to-read-the-average-color-of-a-uiimage-using-ciareaaverage
|
|
extension UIImage {
|
|
@available(iOS 14.0, *)
|
|
public var dominantColor: UIColor? {
|
|
guard let inputImage = CIImage(image: self) else { return nil }
|
|
|
|
let filter = CIFilter.areaAverage()
|
|
filter.inputImage = inputImage
|
|
filter.extent = inputImage.extent
|
|
guard let outputImage = filter.outputImage else { return nil }
|
|
|
|
var bitmap = [UInt8](repeating: 0, count: 4)
|
|
let context = CIContext(options: [.workingColorSpace: kCFNull])
|
|
context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil)
|
|
|
|
return UIColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255)
|
|
}
|
|
}
|
|
|
|
extension UIImage {
|
|
public var domainLumaCoefficientsStyle: UIUserInterfaceStyle? {
|
|
guard let brightness = cgImage?.brightness else { return nil }
|
|
return brightness > 100 ? .light : .dark // 0 ~ 255
|
|
}
|
|
}
|
|
|
|
extension UIImage {
|
|
public func blur(radius: CGFloat) -> UIImage? {
|
|
guard let inputImage = CIImage(image: self) else { return nil }
|
|
let blurFilter = CIFilter.gaussianBlur()
|
|
blurFilter.inputImage = inputImage
|
|
blurFilter.radius = Float(radius)
|
|
guard let outputImage = blurFilter.outputImage else { return nil }
|
|
guard let cgImage = CIContext().createCGImage(outputImage, from: outputImage.extent) else { return nil }
|
|
let image = UIImage(cgImage: cgImage, scale: scale, orientation: imageOrientation)
|
|
return image
|
|
}
|
|
}
|
|
|
|
extension UIImage {
|
|
public func withRoundedCorners(radius: CGFloat? = nil) -> UIImage? {
|
|
let maxRadius = min(size.width, size.height) / 2
|
|
let cornerRadius: CGFloat = {
|
|
guard let radius = radius, radius > 0 else { return maxRadius }
|
|
return min(radius, maxRadius)
|
|
}()
|
|
|
|
let render = UIGraphicsImageRenderer(size: size)
|
|
return render.image { (_: UIGraphicsImageRendererContext) in
|
|
let rect = CGRect(origin: .zero, size: size)
|
|
UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).addClip()
|
|
draw(in: rect)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension UIImage {
|
|
public static func adaptiveUserInterfaceStyleImage(lightImage: UIImage, darkImage: UIImage) -> UIImage {
|
|
let imageAsset = UIImageAsset()
|
|
imageAsset.register(lightImage, with: UITraitCollection(traitsFrom: [
|
|
UITraitCollection(displayScale: 1.0),
|
|
UITraitCollection(userInterfaceStyle: .light)
|
|
]))
|
|
imageAsset.register(darkImage, with: UITraitCollection(traitsFrom: [
|
|
UITraitCollection(displayScale: 1.0),
|
|
UITraitCollection(userInterfaceStyle: .dark)
|
|
]))
|
|
return imageAsset.image(with: UITraitCollection.current)
|
|
}
|
|
}
|