0

I have a CIFilter pipeline.

It currently outputs UIImage using:

private func renderImage(ciImage: CIImage) -> UIImage?
{
    let cgImage = Filter.context.createCGImage(ciImage, from: ciImage.extent)

    return cgImage.map(UIImage.init)
}

This UIImage is later converted to JPEG and stored.

There's now a demand to filter images in bulk and skip the UIImage format. This needs to be done as fast as possible.

Here are a few ways to do this.

Which way is the fastest?

meaning-matters
  • 21,929
  • 10
  • 82
  • 142
  • 1
    Just a word of caution: conversion from CIImage to actual image is never fast, as all the filters / transformations are applied on conversion (although they are optimized). If speed is really important, consider using Accelerate framework (i.e.: https://developer.apple.com/documentation/accelerate/building_a_basic_image-processing_workflow) – timbre timbre Nov 18 '21 at 16:02
  • @KirilS. Being new to Accelerate, I guess that would mean I'd have to implement the CIFilters that come with iOS myself and rewrite myMetal filters? – meaning-matters Nov 18 '21 at 22:42
  • Oh, yea, with Metal filters it's not worth it. I was thinking more about built-in filters. The conversion from CIImage to JPEG may still be slow-ish, especially for RAW images. But you will see. Good luck! – timbre timbre Nov 19 '21 at 01:46
  • @KirilS. Why isn't it worth it to use Accelerate with Metal filters? Aren't all builtin CIFilters in Metal? – meaning-matters Nov 19 '21 at 06:01
  • I meant _if_ image's destination is a bitmap, _and_ you are using some built-in filters, you are wasting (potentially a long) time on converting from CIImage to CGImage / JPEG. Instead you could use Accelerate directly on bitmap (Apple provides some good examples on how to do the same built-in filters with Accelerate). However with your custom filters, translating them to Accelerate, debugging those filters, and testing whether the lost ability to run on GPU is compensated by speed of conversion to bitmap - that's not realistic. – timbre timbre Nov 19 '21 at 15:08
  • Can give you an example. We had a chain of 4 CI filters: resample, greyscale, rotate, sharpen - simple chain. But convert back to JPEG took a long time - about 7 sec per (raw) image. Most of the time was the conversion (i.e. disabling all the filters didn't improve anything). So we tried the Accelerate and with it got processing time down to about 3 sec per image. So yea, filter application itself was obviously slower, but since it needed no conversion, the total time was much better. – timbre timbre Nov 19 '21 at 15:18

1 Answers1

1

You can do that with the CIContext as well:

let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)!
// if you need the JPEG data
let data = Filter.context.jpegRepresentation(of: ciImage, colorSpace: colorSpace)
// or if you want to write to file directly
try Filter.context.writeJPEGRepresentation(of: ciImage, to: url, colorSpace: colorSpace)
Frank Rupprecht
  • 9,191
  • 31
  • 56