Как я могу создать эффект, похожий на размытие в iOS 7?
Автор вопроса: SnowmanОтветов: 12
Я пытаюсь воспроизвести этот размытый фон с публично выпущенного экрана примера iOS 7 от Apple:
В этом вопросе предлагается применить фильтр CI к содержимому ниже, но это совершенно другой подход. . Очевидно, что iOS 7 не захватывает содержимое представленных ниже представлений по многим причинам:
Выполнение грубого тестирования, создание снимка экрана представлений ниже и применение фильтра CIGaussianBlur с достаточно большим радиусом, чтобы имитировать стиль размытия iOS 7, занимает 1-2 секунды, даже на симуляторе.
Размытие в iOS 7 позволяет размывать динамические представления, такие как видео или анимация, без заметных задержек.
Может ли кто-нибудь предположить, какие фреймворки они могли бы использовать для создания этого эффекта, и возможно ли создать аналогичный эффект с текущими общедоступными API-интерфейсами?
Изменить: (из комментария) Мы точно не знаем, как Apple это делает, но можем ли мы сделать какие-то основные предположения? Мы можем предположить, что они используют оборудование, верно?
Является ли эффект самодостаточным в каждом представлении, так что эффект на самом деле не знает, что за ним стоит? Или необходимо, в зависимости от того, как работает размытие, учитывать содержимое размытия?
Если содержимое, стоящее за эффектом, имеет значение, можем ли мы предположить, что Apple получает "поток" содержимого ниже и непрерывно отображает его с размытием?
(Я думаю, мы можем предположить, что Apple в любом случае использует чистый GL для рендеринга домашних экранов. Я сомневаюсь, что они абстрагируют его с помощью UIViews и других вещей, которые могут снизить производительность, поскольку это такая ключевая часть ОС) Dave 12.06.2013
Как я указал в комментариях к моему ответу здесь: stackoverflow.com/a/17048668/19679 они написали ОС, поэтому конечно, у них будет ускоренный доступ к содержимому слоев, составленных под текущим представлением. Мы можем увидеть некоторые из того, что они могут использовать в частном API IOSurface: stackoverflow.com/questions/14135215/. Размытие по Гауссу может быть выполнено намного быстрее, чем случаи обобщенного размытия по Гауссу, если они имеют фиксированный радиус или даже с использованием интересных оптимизаций, таких как интегральные изображения. Brad Larson 13.06.2013
@BradLarson - Перефразируя Джессику Симпсон ... Я понятия не имею, что все это значит, но звучит чертовски круто! А если серьезно, вы говорите, что можете использовать частично прозрачный вид с фильтром размытия и наложить его поверх другого вида для достижения этого эффекта? sangony 17.06.2013
stackoverflow.com/a/25706250/2308190 отлично работал у меня в первый раз, когда я его попробовал, и был кратким Ben Wheeler 25.06.2015
Apple выпустила код на WWDC в качестве категории на UIImage, которая включает эту функцию. Если у вас есть учетная запись разработчика, вы можете получить категорию UIImage (и остальную часть примера кода), перейдя по этой ссылке: https://developer.apple.com/wwdc/schedule/, просматривая раздел 226 и нажимая на подробности. Я еще не играл с ним, но думаю, что эффект будет намного медленнее в iOS 6, есть некоторые улучшения в iOS 7, которые делают захват начального снимка экрана, который используется в качестве входных данных для размытия, намного быстрее.
На самом деле я готов поспорить, что этого будет довольно просто достичь. Вероятно, он не будет работать или выглядеть точно так же, как Apple, но может быть очень близок.
Прежде всего, вам нужно определить CGRect UIView, который вы будете представлять. Как только вы определите, что вам просто нужно захватить изображение части пользовательского интерфейса, чтобы его можно было размыть. Что-то вроде этого...
- (UIImage*)getBlurredImage {
// You will want to calculate this in code based on the view you will be presenting.
CGSize size = CGSizeMake(200,200);
UIGraphicsBeginImageContext(size);
[view drawViewHierarchyInRect:(CGRect){CGPointZero, w, h} afterScreenUpdates:YES]; // view is the view you are grabbing the screen shot of. The view that is to be blurred.
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Gaussian Blur
image = [image applyLightEffect];
// Box Blur
// image = [image boxblurImageWithBlur:0.2f];
return image;
}
Размытие по Гауссу - рекомендуется
Используя UIImage+ImageEffects категорию, предоставленную Apple здесь, вы получите гауссовский размытие, которое очень похоже на размытие в iOS 7.
Размытие по рамке
Вы также можете использовать размытие рамки, используя следующую категорию boxBlurImageWithBlur: UIImage. Это основано на алгоритме, который вы можете найти в здесь.
Теперь, когда вы вычисляете область экрана для размытия, передаете ее в категорию размытия и получаете обратно размытый UIImage, теперь остается только установить это размытое изображение в качестве фона для представления, которое вы будете представлять. Как я уже сказал, это не будет идеально соответствовать тому, что делает Apple, но все равно должно выглядеть довольно круто.
Я только что написал свой небольшой подкласс UIView, который может создавать собственное размытие iOS 7 в любом пользовательском представлении. Он использует UIToolbar, но безопасным способом для изменения его кадра, границ, цвета и альфа-канала с анимацией в реальном времени.
Пожалуйста, дайте мне знать, если заметите какие-либо проблемы.
Ходят слухи, что инженеры Apple утверждают, что для обеспечения такой производительности они считывают данные непосредственно из буфера графического процессора, что вызывает проблемы с безопасностью, поэтому пока нет общедоступного API для этого.
Ответ 7 · рейтинг 7 · Stornu2
Это решение, которое вы можете увидеть на видеороликах WWDC. Вам нужно сделать размытие по Гауссу, поэтому первое, что вам нужно сделать, это добавить новый файл .m и .h с кодом, который я пишу здесь, затем вы должны сделать снимок экрана, использовать желаемый эффект и добавьте его в свое представление, затем ваш UITable UIView или что-то еще должно быть прозрачным, вы можете поиграть с applyBlurWithRadius, чтобы заархивировать желаемый эффект, этот вызов работает с любым UIImage.
В конце размытое изображение будет фоном, а остальные элементы управления должны быть прозрачными.
Чтобы это работало, вам нужно добавить следующие библиотеки:
Вы можете найти свое решение в демонстрационной версии Apple на этой странице: WWDC 2013, найдите и скачайте образец кода UIImageEffects.
Затем с кодом @Jeremy Fox. Я изменил это на
- (UIImage*)getDarkBlurredImageWithTargetView:(UIView *)targetView
{
CGSize size = targetView.frame.size;
UIGraphicsBeginImageContext(size);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(c, 0, 0);
[targetView.layer renderInContext:c]; // view is the view you are grabbing the screen shot of. The view that is to be blurred.
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return [image applyDarkEffect];
}
Просто скопируйте слой UIToolbar, и все готово, AMBlurView сделает это за вас. Ладно, он не такой размытый, как центр управления, но достаточно размытый.
Помните, что iOS7 находится под соглашением о неразглашении.
Ответ 10 · рейтинг 6 · D33pN16h7
Каждый ответ здесь использует vImageBoxConvolve_ARGB8888, эта функция действительно очень медленная, это нормально, если производительность не является требованием высокого приоритета, но если вы используете ее для перехода между двумя контроллерами представления (например, ) этот подход означает время, превышающее 1 секунду или, может быть, больше, что очень плохо для пользовательского опыта вашего приложения.
Если вы предпочитаете оставить всю эту обработку изображений на GPU (и вы должны), вы можете получить гораздо лучший эффект, а также отличное время, округляющее 50 мс (предположим, что у вас есть время в 1 секунду в первом подходе), так что давайте сделаем это .
Сначала загрузите GPUImage Framework (под лицензией BSD) здесь.
Затем добавьте следующие классы (.m и .h) из GPUImage (я не уверен, что это минимум, необходимый только для эффекта размытия)
GPUImage.h
GPUImageAlphaBlendFilter
GPUImageFilter
GPUImageFilterGroup
GPUImageGaussianBlurPositionFilter
GPUImageGaussianSelectiveBlurFilter
GPUImageLuminanceRangeFilter
GPUImageOutput
GPUImageTwoInputFilter
GLProgram
GPUImageBoxBlurFilter
GPUImageGaussianBlurFilter
GPUImageiOSBlurFilter
GPUImageSaturationFilter
GPUImageSolidColorGenerator
GPUImageTwoPassFilter
GPUImageTwoPassTextureSamplingFilter
iOS / GPUImage-Prefix.pch
iOS / GPUImageContext
iOS / GPUImageMovieWriter
iOS / GPUImagePicture
iOS / GPUImageView
Затем создайте категорию в UIImage, которая добавит эффект размытия к существующему UIImage:
И наконец, добавьте в свой проект следующие фреймворки:
AVFoundation CoreMedia CoreVideo OpenGLES
Да, получил удовольствие от этого гораздо более быстрого подхода;)
Ответ 11 · рейтинг 4 · Byte
Вы можете попробовать использовать мой пользовательский вид, в котором есть возможность размывать фон. Он делает это, имитируя снимок фона и размывая его, как в коде WWDC от Apple. Очень просто использовать.
Я также сделал некоторые улучшения, чтобы имитировать динамическое размытие без потери производительности. Фоном моего представления является scrollView, который прокручивается вместе с представлением, тем самым обеспечивая эффект размытия для остальной части супервизора.