Сила Core Image Framework
Core Image — это технология обработки и анализа изображений, разработанная для обеспечения практически непрерывной обработки фотографий и видеоизображений в iOS и OS X. Apple создала несколько великолепных готовых фотоэффектов, которые вы можете легко использовать в своих приложениях для фотосъемки с помощью такие имена, как Instant, Process, Sepia, Tonal и т. д.
Базовая ссылка на изображение
Библиотека разработчиков iOS дает хорошее объяснение обработки изображений Core Image в Базовой коллекции ссылок на Core Image .
Я предлагаю вам также проверить страницу Справочника по CIFilter
изображений , чтобы получить полный список доступных CIFilter
. Обратите внимание, что не все из них совместимы с iOS; некоторые из них работают только на OS X.
Мы будем использовать следующие фильтры Core Image:
-
CIPhotoEffectChrome
-
CISepiaTone
-
CIPhotoEffectTransfer
-
CIPhotoEffectTonal
-
CIPhotoEffectProcess
-
CIPhotoEffectNoir
-
CIPhotoEffectInstant
-
CIPhotoEffectFade
Замечания: Это руководство написано с использованием Xcode 7.3 и Swift 2.2 с целевым значением развертывания 8.0, поэтому ваше приложение будет работать и на старых устройствах.
Давайте начнем!
Создать проект и добавить представления
Откройте Xcode и создайте новый проект, iOS Single View Application . Выберите Swift в качестве языка и Универсальный для устройств. Вы получите пустой UIViewController
в раскадровке и пару файлов .swift : ViewController.swift и AppDelegate.swift .
Выберите контроллер в раскадровке и установите его размер на iPhone 3,5 дюйма на правой панели в разделе « Имитированные метрики» . Это поможет вам адаптировать представления для iPhone 4S, устройства Apple с наименьшим доступным размером экрана.
Мы не будем использовать Auto Layout в этом руководстве, потому что оно портит макеты на больших устройствах, таких как iPad и iPad Pro. Отключите его, выбрав « Инспектор файлов» и снимите флажок « Использовать автоматическую компоновку» . Затем нажмите кнопку « Отключить классы размеров» во всплывающем окне.
Теперь найдите изображение JPEG — либо из Интернета, либо с вашего Mac — и перетащите его под папку Assets.xcassets на панели навигатора проекта. Мы будем использовать это как пример изображения, к которому мы можем применить наши фильтры. Назовите этот файл picture.jpg ; мы назовем это позже в коде.
Вам придется перетащить несколько дополнительных видов в контроллер. Выберите библиотеку объектов в правом нижнем углу Xcode и перетащите UIView
в центр экрана. Измените размер изображения до 320 x 320 пикселей и отцентрируйте его по горизонтали.
Теперь добавьте два UIImageView
на вашу раскадровку, найдя их в библиотеке объектов и перетащив их в основной UIView
. Измените размеры этих изображений, чтобы заполнить этот основной вид (мы рассмотрим, как настроить их свойства автоматического изменения размера позже). Назначьте файл picture.jpg первому представлению изображения с помощью панели инспектора атрибутов.
Затем перетащите UIScrollView
в нижнюю часть экрана и установите его ширину, соответствующую ширине контроллера. Вы также можете добавить UILabel
в верхнюю часть контроллера и установить для него текст Filters . Это будет название вашего приложения.
Наконец, добавьте UIButton
в верхний левый угол экрана и сделайте заголовок Сохранить .
Задать режимы автоматического изменения размера и макета
Размер инспектора Панель можно отобразить, нажав на маленькую иконку линейки в правом верхнем углу экрана. Сделайте это сейчас и начните редактировать размеры вида, выбрав UIButton . Инспектор размера покажет вам координаты x и y на экране (имейте в виду, что x равно 0 в левой части экрана, а y — 0 в верхней части). Установите ширину и высоту до 44 пикселей.
Установите маску авторазмера кнопки, чтобы прикрепить ее к верхней и левой сторонам экрана.
Теперь выберите все другие виды, один за другим, и отрегулируйте их размер и положение следующим образом:
Название приложения имеет ширину 320 пикселей и высоту 44 пикселя и прикрепляется к верхней части экрана.
Каждое изображение имеет ширину и высоту 320 пикселей.
Наконец, представление прокрутки (для параметров фильтра) имеет ширину 320 пикселей и высоту 80 пикселей.
Объявление видов в файле .swift
Одной из самых приятных особенностей XCode является возможность разделить рабочее пространство на две части и иметь раскадровку на одной стороне и файл Swift на другой стороне. Чтобы сделать это, вы должны щелкнуть значок Assistant Editor в правом верхнем углу окна Xcode:
Если ваш ViewController
выбран в раскадровке, в правой части автоматически отобразится его относительный файл .swift . Если этого не произойдет, вы можете попробовать щелкнуть горизонтальное меню в верхней части файла swift и переключить Manual на Automatic :
Теперь давайте приложим некоторые из наших представлений к файлу ViewController.swift . На панели « Структура документа» выберите UIView
который содержит два UIImageView
, удерживайте нажатой клавишу « Control» (или правую кнопку мыши) и перетащите указатель мыши внизу, чтобы получить объявление класса вашего контроллера представления.
Отпустите кнопку мыши, и появится всплывающее окно. Введите имя UIView
— containerView — и нажмите кнопку Подключиться .
Вы только что добавили объявление для IBOutlet
типа UIView
в свой файл .swift . Сделайте то же самое для других видов изображений: перетащите синюю линию ниже каждого экземпляра, который вы объявите, и назовите первый originalImage
а второй imageToFilter
. Убедитесь, что в качестве изображения используется originalImage
с изображением picture.jpg .
Затем подключите UIScrollView
и назовите его filtersScrollView
. Это сохранит все кнопки для применения фильтров к вашей картинке.
Мы объявим нашу UIButton
позже как IBAction
. Эта кнопка позволит нам сохранить наше отфильтрованное изображение в библиотеке фотографий нашего устройства.
Давайте код!
Создание массива основных фильтров изображений
В Swift вы можете объявить глобальные переменные, просто поместив их вне объявления class
, в нашем случае это:
1
|
class ViewController: UIViewController {
|
Нам нужно создать массив имен CIFilter
:
01
02
03
04
05
06
07
08
09
10
|
var CIFilterNames = [
«CIPhotoEffectChrome»,
«CIPhotoEffectFade»,
«CIPhotoEffectInstant»,
«CIPhotoEffectNoir»,
«CIPhotoEffectProcess»,
«CIPhotoEffectTonal»,
«CIPhotoEffectTransfer»,
«CISepiaTone»
]
|
Как упоминалось в начале этого урока, мы должны использовать исходные имена фильтров Core Image, чтобы наше приложение распознало их. Мы назначим эти фильтры кнопкам, которые создадим позже, чтобы применить фильтр к нашему изображению.
Скрытие строки состояния
В большинстве случаев вы можете скрыть строку состояния с экрана. Начиная с Xcode 7.0, больше невозможно установить скрытое свойство viewDidLoad()
состояния в Info.plist , поэтому вы должны добавить этот метод прямо над viewDidLoad()
:
1
2
3
|
override func prefersStatusBarHidden() -> Bool {
return true
}
|
Создание кнопок фильтра
Метод viewDidLoad()
— это экземпляр по умолчанию, который Xcode создает каждый раз, когда вы добавляете файл .swift в свой проект; он вызывается, когда экран и все его виды загружаются. Если вы хотите выполнить какое-либо действие еще до того, как это произойдет, вы можете использовать viewDidAppear()
или viewWillAppear()
, но нам это не нужно. Итак, давайте добавим несколько переменных типа CGFloat
прямо под super.viewDidLoad()
:
1
2
3
4
5
6
7
8
|
override func viewDidLoad() {
super.viewDidLoad()
var xCoord: CGFloat = 5
let yCoord: CGFloat = 5
let buttonWidth:CGFloat = 70
let buttonHeight: CGFloat = 70
let gapBetweenButtons: CGFloat = 5
|
Эти значения необходимы для размещения ряда кнопок внутри нашего filtersScrollView
. Как видно из приведенного выше кода, xCoord
— это позиция X, в которой будет размещена кнопка, yCoord
— это позиция Y, buttonWidth
и buttonHeight
— ее размер, а gapBetweenButtons
— это пространство между каждой кнопкой.
Теперь нам нужно создать кнопки с помощью цикла for
, который продублирует пользовательскую UIButton
и поместит ее в filtersScrollView
на основе приведенных выше значений.
Поместите этот код прямо под экземплярами CGFloat
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
var itemCount = 0
for i in 0..<CIFilterNames.count {
itemCount = i
// Button properties
let filterButton = UIButton(type: .Custom)
filterButton.frame = CGRectMake(xCoord, yCoord, buttonWidth, buttonHeight)
filterButton.tag = itemCount
filterButton.addTarget(self, action: #selector(ViewController.filterButtonTapped(_:)), forControlEvents: .TouchUpInside)
filterButton.layer.cornerRadius = 6
filterButton.clipsToBounds = true
// CODE FOR FILTERS WILL BE ADDED HERE…
|
Давайте посмотрим, что происходит в этом коде. itemCount
— это переменная, которую мы будем использовать позже, чтобы добавить кнопки фильтров в качестве filtersScrollView
. Вы можете заметить, что мы объявили эту переменную с префиксом var
. Это потому, что он будет изменен циклом for
. Если вы хотите объявить константы в Swift, вы используете префикс let
, как мы делали для filterButton
.
Используя новый синтаксис цикла for
Swift 2.2, нам больше не нужно писать i++
. Цикл будет автоматически увеличивать i
, считая от 0 до количества элементов в массиве CIFilterNames
.
Внутри цикла for
мы создаем пользовательскую кнопку, устанавливаем ее значения CGRect
, присваиваем ей тег и добавляем к нему целевое действие, которое вызывает функцию, которую мы увидим позже: filterButtonTapped()
.
Чтобы наша кнопка выглядела красиво, с закругленными углами, мы используем свойство layer
и устанавливаем его угловой радиус равным 6. Затем мы обрезаем изображение, которое будет содержаться в его границах, в противном случае оно будет покрывать закругленные углы.
Добавьте изображение в кнопки и примените фильтры
Следующий фрагмент кода должен быть добавлен под комментарием к предыдущему:
1
2
3
4
5
6
7
8
9
|
// Create filters for each button
let ciContext = CIContext(options: nil)
let coreImage = CIImage(image: originalImage.image!)
let filter = CIFilter(name: «\(CIFilterNames[i])» )
filter!.setDefaults()
filter!.setValue(coreImage, forKey: kCIInputImageKey)
let filteredImageData = filter!.valueForKey(kCIOutputImageKey) as!
let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent)
let imageForButton = UIImage(CGImage: filteredImageRef);
|
Здесь мы инициализируем CIContext
и CIImage
чтобы Core Image работал с originalImage
( picture.jpg ), который будет отображаться каждой кнопкой. Затем мы CIFilter
переменную фильтра типа CIFilter
которая будет вызываться каждой кнопкой в цикле for
на CIFilterNames
массива CIFilterNames
.
Наш экземпляр filter
должен установить свое состояние по умолчанию, а затем он становится ключом ввода для изображений. Затем мы создаем объект данных из него и его ссылку на изображение, которое мы будем использовать для создания UIImage
который будет прикреплен к кнопке.
Поскольку фильтры, которые мы выбрали для этого урока, уже сделаны Apple, нам не нужно применять какие-либо дополнительные значения (например, интенсивность, цвет и т. Д.). Если вы хотите получить информацию о других CIFilters
, вы можете проверить страницу справки по CIFilters
основного изображения .
В последней строке этого раздела мы наконец установили фоновое изображение кнопки, которое мы создали ранее.
1
2
|
// Assign filtered image to the button
filterButton.setBackgroundImage(imageForButton, forState: .Normal)
|
Добавление кнопок в ScrollView
Еще несколько строк для завершения нашего viewDidLoad()
:
01
02
03
04
05
06
07
08
09
10
|
// Add Buttons in the Scroll View
xCoord += buttonWidth + gapBetweenButtons
filtersScrollView.addSubview(filterButton)
} // END FOR LOOP
// Resize Scroll View
filtersScrollView.contentSize = CGSizeMake(buttonWidth * CGFloat(itemCount+2), yCoord)
} // END viewDidload()
|
Мы добавляем кнопки в качестве вложенных видов в filtersScrollView
зависимости от их положения, ширины и расстояния, которые они должны хранить между собой. Затем, наконец, мы закрываем цикл for
.
Наконец, мы должны установить contentSize
нашего ScrollView
чтобы соответствовать всем кнопкам. Здесь мы наконец используем itemCount
ранее переменную itemCount
, преобразованную в CGFloat
(потому что CGSizeMake
не принимает значения Int
).
Действие кнопки фильтра
Мы почти закончили, всего несколько строк кода!
В классе ViewController
вне viewDidLoad()
создайте filterButtonTapper()
. Это будет вызываться каждый раз, когда вы нажимаете на одну из кнопок, которые мы создали ранее.
1
2
3
4
5
|
func filterButtonTapped(sender: UIButton) {
let button = sender as UIButton
imageToFilter.image = button.backgroundImageForState(UIControlState.Normal)
}
|
UIButton
нам нужно создать экземпляр UIButton
, а затем установить изображение imageToFilter
на основе фонового изображения этой кнопки, которое уже отфильтровано кодом, помещенным в viewDidLoad()
.
Убедитесь, что UIImageView
именем imageToFilter
перекрывает originalImage
, как показано ниже, в противном случае приложение не покажет вам обработанное изображение, потому что исходное изображение скрывает его.
Сохранение обработанной картинки
Мы подошли к концу этого урока, и есть еще одна функция, которую нужно добавить в ваш файл .swift . Это кнопка «Сохранить», которую мы ранее поместили в раскадровку. Удерживая Control и кнопку мыши, перетащите синюю линию от UIButton
на пустое место в вашем классе, отпустите кнопку мыши, и появится новое всплывающее окно. Здесь вы должны изменить тип соединения на Action и ввести имя вашего метода — в данном случае savePicButton
— и нажать кнопку Connect .
На этот раз вы создали IBAction
, и вот код, который необходимо поместить в него:
1
2
3
4
5
6
7
8
|
// Save the image into camera roll
UIImageWriteToSavedPhotosAlbum(imageToFilter.image!, nil, nil, nil)
let alert = UIAlertView(title: «Filters»,
message: «Your image has been saved to Photo Library»,
delegate: nil,
cancelButtonTitle: «OK»)
alert.show()
|
Первая строка просто сохраняет изображение, содержащееся в imageToFilter
непосредственно в библиотеке фотографий вашего устройства или в iOS Simulator. Затем мы UIAlertView
простой UIAlertView
который подтверждает, что операция была выполнена.
Хорошо, давайте запустим наше приложение и посмотрим, что произойдет, если мы нажмем кнопки внизу. Если вы все сделали правильно, ваше приложение должно выглядеть так:
Спасибо за чтение, и увидимся в следующий раз! Пожалуйста, ознакомьтесь с другими нашими руководствами по разработке приложений для Swift и iOS.