Learn more about Russian war crimes in Ukraine.

What is CIColorKernel?

I’ve showed some uses of CIKernel, each of which produces an output pixel by transforming one pixel of some input images. To get the input pixels, I used code like this:

vec4 i1_px = sample(image1, samplerCoord(image1));
vec4 i2_px = sample(image2, samplerCoord(image2));

Kernels of this form, which only examine one point of the input image, can instead be expressed as CIColorKernels. Here’s a CIColorKernel which composes two images with some opacity:

kernel vec4 alpha_compose(__sample i1_px, __sample i2_px, float image2_opacity) {
  return i1_px*(1.0 - image2_opacity) + i2_px*image2_opacity;
}

Instead of the input being a sampler (an image), the input to a color kernel is a __sample, which is a vec4 representing a pixel sample of an input image. A color kernel is strictly less flexible than a general kernel, which allows for some optimizations when executing it.

Here’s the example kernel in use:

import Foundation
import CoreImage
import AppKit
let myKernel = CIColorKernel(string:
    "kernel vec4 alpha_compose(__sample i1_px, __sample i2_px, float image2_opacity) { " +
    "  return i1_px*(1.0 - image2_opacity) + i2_px*image2_opacity;" +
    "}")!
func ciImageFromPath(path: String) -> CIImage {
    let nsImage = NSImage(contentsOfFile: path)!
    let cgImage = nsImage.cgImage(forProposedRect: nil, context: nil, hints: [:])!
    return CIImage(cgImage: cgImage)
}
let inputImage1 = ciImageFromPath(path: "/Users/jim/shapes.png")
let inputImage2 = ciImageFromPath(path: "/Users/jim/Lenna.png")
let outputRect = CGRect(x: 0, y: 0, width: inputImage1.cgImage!.width, height: inputImage1.cgImage!.height)
let outputImage = myKernel.apply(
    withExtent: outputRect,
    roiCallback: { (Int32, CGRect) -> CGRect in return outputRect },
    arguments: [inputImage1, inputImage2, 0.2]
)!
let rep = NSBitmapImageRep(ciImage: outputImage.cropping(to: outputRect))
let imageData = rep.representation(using: NSBitmapImageFileType.PNG, properties: [:])!
try! imageData.write(to: URL.init(string: "file:/Users/jim/output.png")!, options: NSData.WritingOptions.atomic)

What can computers do? What are the limits of mathematics? And just how busy can a busy beaver be? This year, I’m writing Busy Beavers, a unique interactive book on computability theory. You and I will take a practical and modern approach to answering these questions — or at least learning why some questions are unanswerable!

It’s only $19, and you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

After months of secret toil, I and Andrew Carr released Everyday Data Science, a unique interactive online course! You’ll make the perfect glass of lemonade using Thompson sampling. You’ll lose weight with differential equations. And you might just qualify for the Olympics with a bit of statistics!

It’s $29, but you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

More by Jim

Tagged . All content copyright James Fisher 2017. This post is not associated with my employer. Found an error? Edit this page.