Last active
February 26, 2023 18:33
-
-
Save SheffieldKevin/566dc048dd6f36716bcd to your computer and use it in GitHub Desktop.
A couple of swift functions for comparing two CGImage using CIImage in OS X
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
/** | |
@brief Returns true if images have same meta. Width, Height, bit depth. | |
@discussion Assumes images are non null. | |
*/ | |
func doImagesHaveSameMeta(#image1:CGImage, #image2:CGImage) -> Bool { | |
if CGImageGetWidth(image1) != CGImageGetWidth(image2) { | |
return false | |
} | |
if CGImageGetHeight(image1) != CGImageGetHeight(image2) { | |
return false | |
} | |
if CGImageGetBitsPerComponent(image1) != CGImageGetBitsPerComponent(image2) { | |
return false | |
} | |
if CGImageGetBytesPerRow(image1) != CGImageGetBytesPerRow(image2) { | |
return false | |
} | |
if CGImageGetBitsPerPixel(image1) != CGImageGetBitsPerPixel(image2) { | |
return false | |
} | |
return true | |
} | |
/** | |
@brief Returns the maximum difference of pixel values in the image. | |
@discussion Assumes doImagesHaveSameMeta has already returned true on | |
the images passed into this function. OSX only as iOS doesn't have the | |
CIAreaMaximum filter. | |
*/ | |
func compareImages(#image1:CGImage, #image2:CGImage) -> Int { | |
var diff = 0 | |
// First create the CIImage representations of the CGImage. | |
let ciImage1 = CIImage(CGImage: image1) | |
let ciImage2 = CIImage(CGImage: image2) | |
// Create the difference blend mode filter and set its properties. | |
let diffFilter = CIFilter(name: "CIDifferenceBlendMode") | |
diffFilter.setDefaults() | |
diffFilter.setValue(ciImage1, forKey: kCIInputImageKey) | |
diffFilter.setValue(ciImage2, forKey: kCIInputBackgroundImageKey) | |
// Create the area max filter and set its properties. | |
let areaMaxFilter = CIFilter(name: "CIAreaMaximum") | |
areaMaxFilter.setDefaults() | |
areaMaxFilter.setValue(diffFilter.valueForKey(kCIOutputImageKey), | |
forKey: kCIInputImageKey) | |
let compareRect = CGRectMake(0.0, 0.0, CGFloat(CGImageGetWidth(image1)), | |
CGFloat(CGImageGetHeight(image1))) | |
let extents = CIVector(CGRect: compareRect) | |
areaMaxFilter.setValue(extents, forKey: kCIInputExtentKey) | |
// The filters have been setup, now set up the CGContext bitmap context the | |
// output is drawn to. Setup the context with our supplied buffer. | |
let alphaInfo = CGImageAlphaInfo.PremultipliedLast | |
let bitmapInfo = CGBitmapInfo(rawValue: alphaInfo.rawValue) | |
let colorSpace = CGColorSpaceCreateDeviceRGB() | |
var buf: [CUnsignedChar] = Array<CUnsignedChar>(count: 16, repeatedValue: 255) | |
let context = CGBitmapContextCreate(&buf, 1, 1, 8, 16, colorSpace, bitmapInfo) | |
// Now create the core image context CIContext from the bitmap context. | |
let ciContextOpts = [ | |
kCIContextWorkingColorSpace : colorSpace, | |
kCIContextUseSoftwareRenderer : false | |
] | |
let ciContext = CIContext(CGContext: context, options: ciContextOpts) | |
// Get the output CIImage and draw that to the Core Image context. | |
let valueImage = areaMaxFilter.valueForKey(kCIOutputImageKey)! as CIImage | |
ciContext.drawImage(valueImage, inRect: CGRectMake(0,0,1,1), | |
fromRect: valueImage.extent()) | |
// This will have modified the contents of the buffer used for the CGContext. | |
// Find the maximum value of the different color components. Remember that | |
// the CGContext was created with a Premultiplied last meaning that alpha | |
// is the fourth component with red, green and blue in the first three. | |
let maxVal = max(buf[0], max(buf[1], buf[2])) | |
diff = Int(maxVal) | |
return diff | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for putting this together! I couldn't get it to compile on Xcode 13, so I created an updated version (works with Swift 5):
https://gist.github.com/nicolas-miari/519cb8fd31c16e5daac263412996d08a