Blur в iOS7

    С седьмой версией iOS многие элементы UI стали выглядеть привлекательнее (см. Session 226, Implementing Engaging UI on iOS).

    Например, теперь поп-оверы, большинство баров и алерты имеют размытый фон.



    Что делать, если хочется добавить блюр в свой контрол, подскажет эта статья.


    Блюр бывает разный


    Есть два типа блюра: статический и динамический. Как и следует из названия, первый размывает контент единожды, а второй обновляется через небольшие промежутки времени.

    Реализовать блюр несложно. Общая схема такая: сделать снимок фона за view, (например, при помощи renderInContext), размыть его и установить полученное изображение в качестве фона view. В случае динамического блюра все вышеперечисленные действия выполняются по таймеру. Как пример такого подхода рекомендую глянуть FXBlurView.

    Главным плюсом 7-ки в плане блюра является высокая скорость работы. Например, можно смотреть видео и при этом панель с регулировкой громкости будет блюриться в реальном времени без каких-либо лагов.

    Итак, способы реализовать быстрый блюр в iOS 7.

    Кража лейера


    Идея довольно проста. Раз у UIToolbar есть прозрачность, то можно взять и использовать его лейер в качестве фона.

    UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:[self bounds]]];
    [toolbar setBarTintColor:[UIColor greenColor]];
    [self.layer insertSublayer:[self.toolbar layer] atIndex:0];
    

    Подход хорош, работает стабильно и очень прост.
    Уже есть готовая реализация под названием iOS-blur (доступна через CocoaPods).

    Использование drawViewHierarchyInRect:afterScreenUpdates


    Если стоит задача наворотить хитрый блюр, то придется самим брать фон и размывать его.
    К счастью, в iOS 7 появился чрезвычайно быстрый способ создания снимков view drawViewHierarchyInRect:afterScreenUpdates.


    На картинке из презентации видно, что скорость получения снимка view возросла в 15 раз!

    Использовать довольно просто (готовая реализация):

    -(UIImage *)blurredSnapshot
    {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, self.window.screen.scale);
        [self drawViewHierarchyInRect:self.frame afterScreenUpdates:NO];
        UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
        UIImage *blurredSnapshotImage = [snapshotImage applyLightEffect];
        UIGraphicsEndImageContext();
        return blurredSnapshotImage;
    }
    

    В данном примере для блюра испосльзуется категория UIImage+ImageEffects взятая из WWDC и использующая мощь Accelerate Framework. Конечно можно блюрить и чем нибудь другим. Например CIFilter или его приватной реализацией как сделано в JMIBlurView. Главная мысль в том, что с 7-ки можно персестать использовать renderInContext, который отрабатывает почти секунду и добиться real-time блюра без исользования шейдров.

    Как пример реализации динамического блюра рекомендую глянуть 7blur.

    Заключение


    Блюр на iOS7 работает очень быстро, и его несложно реализовать. Так что смело используйте его в своих приложениях, не боясь потерять производительность.
    e-Legion Ltd. 80,66
    Лидер мобильной разработки в России
    Поделиться публикацией
    Похожие публикации
    Комментарии 25
    • 0
      По мойму, очень хорошо а лаконично всё описано. Спасибо большое за обзор разных способов!
      • +1
        Как раз вовремя. Правда я уже реализовал real time blur, но все равно спасибо, я утвердился в мысли, что все правильно сделал. Кстати есть еще одна реализация динамического блюра, основанная на небольшом реверс-инжиниринге uitoolbar и использовании CAFilter. Правда это закрытый API, не факт, что Apple пропустит.
        • +1
          А почему-бы не использовать для этого CIFilter (CIGaussianBlur), он немного медленнее, но зато встроенный родной и стандартный.
          А вот кстати хорошая статья на сравнение разных подходов.
          А тут наглядная демонстрация встроенных фильтров.
          • 0
            Они медленные. Очень медленные.И CIFilter применяется к картинке, а CAFilter применяется к UIView.
            • 0
              CAFilter нельзя использовать, картинку из UIView получить — тривиальная задача, она всегда доступная через бэкинг стор у Layer этого вью.
              Они не такие и медленные, долго создается контекст, если держать один контекст во время операции динамического размытия, то всё будет ок.
            • 0
              Особой разницы, чем блюрить нет.
              Можно CIFilter, но UIImage+ImageEffects из WWDC работающий с Accelerated Framework гораздо лучше. Проблема в том, что renderInContext, который приходилось использовать до 7-ки работает очень медленно и real time blur с ним фиг сделаешь.
              • 0
                Ну так и CIGaussianBlur появился только в семерке вроде.
                • 0
                  Тошнотворно он работает. Ужасное размытие, если сравнивать с Ps.
                  • 0
                    Беру свои слова обратно — забыл, что работаю в 5 битном режиме 8-|
                  • 0
                    В частности поэтому и (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates
              • +3
                Я бы с удовольствием почитал, как реализовать такой же эффект в вэбе.
                (результаты моих экспериментов совсем не так красивы)
              • 0
                А на каких устройствах вы тестировали? Хотелось бы узнать скорость работы начиная с iPhone 4S. На 4-ке тоже было бы интересно узнать, но думаю и так ясно, что на нем будет гораздо медленнее работать.
                • +2
                  Или можно сделать в ворде =)
                  • +1
                    А мне в iOS7 блур не понравился, т.к. иногда кажется, что экран испорчен/грязный, а оказывается это что-то на заднем плане.
                    • +1
                      Кстати, странно что Apple не включили в новые API возможность без каких-то ухищрений блюрить вьюхи так же как UIToolbar, было же очевидно что все ломанутся использовать эту возможность. Тем более что их же приложения вовсю эту возможность используют, например AppStore на iOS. И что мы в итоге получаем? Кучу приложений с растянутым UIToolbar и кражу лейера, несерьезно.
                      • +2
                        Насколько я заметил, то, что автор топика привел как «готовую реализацию» на самом деле просто выпилено из кода примеров WWDC. Статья тоже по сути просто вольный пересказ небольшого кусочка одной из сессий WWDC.
                        • 0
                          Готовых реализаций полно на gitlab и нет смысла изобретать велосипед.
                          Задача поста рассказать о там, как без лишних телодвижений реализовать блюр.
                          Из WWDC, пожалуй только applyLightEffect.
                        • 0
                          Насколько помню, текущая реализация слишком низкоуровневая (буквально на уровне драйверов видеокарты). Не включили по соображениям безопасности и целостности API.
                        • 0
                          Нативный блюр в iOS делается с помощью закрытых методов API, которые работают на очень низком уровне прямо с графическим буфером. Только это способно дать такую скорость отрисовки.
                          Снэпшоты подходят для статики, но динамику ими уже не нарисовать — будут тормоза (например, не выйдет сэмулировать блюр в навигейшн баре и списке прокрутки).
                          • 0
                            А куда более низкоуровневей? бэкинг-стор у CALAyer — это ни что иное как память видеокарты, ты веделяешь себе кусок и все операции происходят не в CPU, а в GPU с помощью конвеера.
                            Другой вопрос, что тут для эффектов испольузется блжндинг двух буферов, и для этого нужно иметь доступ к обоим бУферам. Поэтому мне кажется проблема состоит в том, что:
                            — с соображений безопасности
                            — не унифицировали API, поэтому не могут еще гарантировать обратой совместимости
                            — вообще решили, что не нужно это разработчикам.

                            Или всё вместе.
                          • 0
                            Вместо renderInContext новый метод советуют в приложении-примере.
                            • 0
                              А кто-нибудь пробовал библиотеку iFlou вот отсюда? iFlou — The Blur Effect you need!
                              Blur эффект для iOS в данном случае использует технику, при которой используется заранее подготовленная картинка

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое