Я большой поклонник технологии Apple Core Image : мое приложение Nodality полностью основано на фильтрах Core Image. Тем не менее, для новых пользователей код для добавления простого фильтра к изображению немного наклонен, а реализация очень строковая.
В этом посте рассматривается альтернатива, GPUImage от Брэда Ларсона . GPUImage — это фреймворк, содержащий богатый набор фильтров изображений, многие из которых отсутствуют в Core Image. Он имеет гораздо более простой и строго типизированный API и в некоторых случаях работает быстрее, чем Core Image.
Для начала давайте рассмотрим код, необходимый для применения гауссовского синего цвета к изображению ( inputImage ) с помощью Core Filter:
let inputImage = UIImage()
let ciContext = CIContext(options: nil)
let blurFilter = CIFilter(name: "CIGaussianBlur")
blurFilter.setValue(CIImage(image: inputImage), forKey: "inputImage")
blurFilter.setValue(10, forKey: "inputRadius")
let outputImageData = blurFilter.valueForKey("outputImage") as CIImage!
let outputImageRef: CGImage = ciContext.createCGImage(outputImageData, fromRect: outputImageData.extent())
let outputImage = UIImage(CGImage: outputImageRef)!
… мы не только должны явно определять контекст, но и имя фильтра и параметр являются строками, и нам нужно несколько шагов, чтобы преобразовать выходные данные фильтра в UIImage .
Вот та же функциональность с использованием GPUImage :
let inputImage = UIImage()
let blurFilter = GPUImageGaussianBlurFilter()
blurFilter.blurRadiusInPixels = 10
let outputImage = blurFilter.imageByFilteringImage(inputImage)
Здесь и фильтр, и его параметр радиуса размытия введены правильно, и фильтр возвращает экземпляр UIImage .
С другой стороны, есть некоторые настройки, чтобы сделать. После того, как вы получили локальную копию из GPUImage , перетащите рамки проекта в проект приложения. Затем на этапах сборки цели приложения добавьте зависимость цели, ссылку на GPUImage.framework в бинарных файлах ссылок и этап копирования файлов.
Экран фаз сборки должен выглядеть следующим образом:
Затем, просто импортировав GPUImage , вы готовы к работе.
Чтобы продемонстрировать некоторые забавные фильтры, содержащиеся в GPUImage , я создал небольшое демонстрационное приложение, GPUImageDemo .
Приложение демонстрирует Polar Pixellate, Polka Dot, Sketch, Threshold Sketch, Toon, Smooth Toon, Emboss, Sphere Refraction и Glass Sphere — ни один из которых не доступен в Core Image.
Вся работа по фильтрации выполняется в моем классе GPUImageDelegate, где оператор switch объявляет переменную GPUImageOutput (класс, который включает метод imageByFiltering () ) и устанавливает его для соответствующего конкретного класса в зависимости от пользовательского интерфейса.
Например, если для средства выбора задан эскиз порога, выполняется следующая инструкция case:
case ImageFilter.ThresholdSketch:
gpuImageFilter = GPUImageThresholdSketchFilter()
if let gpuImageFilter = gpuImageFilter as? GPUImageThresholdSketchFilter
{
if values.count > 1
{
gpuImageFilter.edgeStrength = values[0]
gpuImageFilter.threshold = values[1]
}
}
Если вы создаете этот проект, вы можете столкнуться с ошибкой сборки в целевой документации. Я просто удалил эту цель на зараженных машинах.
GPUImage достаточно быстр для фильтрации видео. Я взял свой недавний эксперимент с двумя миллионами частиц и добавил этап постобработки, который состоит из фильтра мультфильмов и фильтра тиснения. Они упакованы вместе в GPUImageFilterGroup :
let toonFilter = GPUImageSmoothToonFilter()
let embossFilter = GPUImageEmbossFilter()
let filterGroup = GPUImageFilterGroup()
toonFilter.threshold = 1
embossFilter.intensity = 2
filterGroup.addFilter(toonFilter)
filterGroup.addFilter(embossFilter)
toonFilter.addTarget(embossFilter)
filterGroup.initialFilters = [ toonFilter ]
filterGroup.terminalFilter = embossFilter
Поскольку GPUImageFilterGroup расширяет GPUImageFilterOutput , я могу взять вывод из текстуры Metal, создать его экземпляр UIImage и передать его в составной фильтр:
self.imageView.image = self.filterGroup.imageByFilteringImage(UIImage(CGImage: imageRef)!)
На моем iPad Air 2 конечный результат 2 000 000 частиц с последующей обработкой двумя фильтрами на изображении с разрешением 1024 x 1024 по-прежнему работает со скоростью около 20 кадров в секунду. Вот снимок экрана в реальном времени:
Исходный код моего GPUImageDemo доступен в моем репозитории GitHub здесь, а GPUImage здесь .
