Skip to content

Instantly share code, notes, and snippets.

@FezVrasta
Created September 28, 2023 09:53
Show Gist options
  • Save FezVrasta/d03e709e30c21d470889853b1157b48c to your computer and use it in GitHub Desktop.
Save FezVrasta/d03e709e30c21d470889853b1157b48c to your computer and use it in GitHub Desktop.
import Foundation
import CoreImage
import UIKit
func convertCIImageToUIImage(ciImage: CIImage) -> UIImage {
let context = CIContext(options: nil)
let cgImage = context.createCGImage(ciImage, from: ciImage.extent)
let uiImage = UIImage(cgImage: cgImage!)
return uiImage
}
func convertUIImageToCIImage(uiImage: UIImage) -> CIImage {
guard let ciImage = uiImage.ciImage ?? CIImage(image: uiImage) else {
fatalError("Failed to convert UIImage to CIImage.")
}
return ciImage
}
func applyCustomCIFilter(uiImage: UIImage)-> UIImage? {
let origImage = convertUIImageToCIImage(uiImage: uiImage)
// custom filter to convert light gray to white and dark gray to black
let invertWithThresholdKernel = CIColorKernel(source: """
kernel vec4 invertWithThreshold(__sample pixel, float threshold) {
// Determine the saturation by comparing the range of colors.
// If the most intense channel is very close to the least intense channel,
// then this color is close to gray.
float minColor = min(pixel.r, min(pixel.g, pixel.b));
float maxColor = max(pixel.r, max(pixel.g, pixel.b));
float saturation = maxColor == 0.0 ? 0.0 : (maxColor - minColor) / maxColor;
if (saturation < threshold) {
// Invert the color, setting alpha to 1
// Handling transparency requires first unmultiplying the colors. Rather than mess with that,
// this code assumes that everything is opaque.
return vec4(1.0 - pow(pixel.r, 2.2), 1.0 - pow(pixel.g, 2.2), 1.0 - pow(pixel.b, 2.2), 1.0);
} else {
return pixel;
}
}
""")
guard let outImage = invertWithThresholdKernel?.apply(extent: (origImage.extent), arguments: [origImage as Any, 0.1 as Float])! else { return nil }
return convertCIImageToUIImage(ciImage: outImage);
}
@FezVrasta
Copy link
Author

I would be curious to know what's the correct way to use this in a widget since the CIColorKernel is deprecated but Metal shaders don't seem to be supported in widgets?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment