Я большой поклонник технологии 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 здесь .