Как я могу создать эффект, похожий на размытие в iOS 7?

Я пытаюсь воспроизвести этот размытый фон с публично выпущенного экрана примера iOS 7 от Apple:

Скриншот Центра управления iOS 7

В этом вопросе предлагается применить фильтр CI к содержимому ниже, но это совершенно другой подход. . Очевидно, что iOS 7 не захватывает содержимое представленных ниже представлений по многим причинам:

  1. Выполнение грубого тестирования, создание снимка экрана представлений ниже и применение фильтра CIGaussianBlur с достаточно большим радиусом, чтобы имитировать стиль размытия iOS 7, занимает 1-2 секунды, даже на симуляторе.
  2. Размытие в iOS 7 позволяет размывать динамические представления, такие как видео или анимация, без заметных задержек.

Может ли кто-нибудь предположить, какие фреймворки они могли бы использовать для создания этого эффекта, и возможно ли создать аналогичный эффект с текущими общедоступными API-интерфейсами?

Изменить: (из комментария) Мы точно не знаем, как Apple это делает, но можем ли мы сделать какие-то основные предположения? Мы можем предположить, что они используют оборудование, верно?

Является ли эффект самодостаточным в каждом представлении, так что эффект на самом деле не знает, что за ним стоит? Или необходимо, в зависимости от того, как работает размытие, учитывать содержимое размытия?

Если содержимое, стоящее за эффектом, имеет значение, можем ли мы предположить, что Apple получает «поток» содержимого ниже и непрерывно отображает его с размытием?


person Snowman    schedule 12.06.2013    source источник
comment
(Я думаю, мы можем предположить, что Apple в любом случае использует чистый GL для рендеринга домашних экранов. Я сомневаюсь, что они абстрагируют его с помощью UIViews и других вещей, которые могут снизить производительность, поскольку это такая ключевая часть ОС)   -  person Dave    schedule 12.06.2013
comment
Как я указал в комментариях к моему ответу здесь: stackoverflow.com/a/17048668/19679 они написали ОС, поэтому конечно, у них будет ускоренный доступ к содержимому слоев, составленных под текущим представлением. Мы можем увидеть некоторые из того, что они могут использовать в частном API IOSurface: stackoverflow.com/questions/14135215/. Размытие по Гауссу может быть выполнено намного быстрее, чем случаи обобщенного размытия по Гауссу, если они имеют фиксированный радиус или даже с использованием интересных оптимизаций, таких как интегральные изображения.   -  person Brad Larson    schedule 13.06.2013
comment
@BradLarson - Перефразируя Джессику Симпсон ... Я понятия не имею, что все это значит, но звучит чертовски круто! А если серьезно, вы говорите, что можете использовать частично прозрачный вид с фильтром размытия и наложить его поверх другого вида для достижения этого эффекта?   -  person sangony    schedule 17.06.2013
comment
stackoverflow.com/a/25706250/2308190 отлично работал у меня в первый раз, когда я его попробовал, и был кратким   -  person Ben Wheeler    schedule 25.06.2015


Ответы (12)


Зачем копировать эффект? Просто нарисуйте UIToolbar позади вашего представления.

myView.backgroundColor = [UIColor clearColor];
UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:myView.frame];
bgToolbar.barStyle = UIBarStyleDefault;
[myView.superview insertSubview:bgToolbar belowSubview:myView];
person user2342340    schedule 09.08.2013
comment
Я не согласен с Криззвальдом. Я не думаю, что это хорошая интерпретация правил ожидания того, что будет делать APple. - person Andrew Johnson; 02.09.2013
comment
Это отличное решение! Apple, конечно же, не откажется от вас за то, что ваше приложение выглядит великолепно! - person bentford; 18.09.2013
comment
Это просто дает эффект полупрозрачности, но не размывает содержимое представления за панелью инструментов. - person Deepak G M; 23.09.2013
comment
Он работает, но, как и общесистемные эффекты размытия, работает только на новых устройствах. - person borisgolovnev; 30.09.2013
comment
Это не перспективный метод, поскольку Apple может изменить его внешний вид в любом крупном обновлении. - person Morrowless; 03.10.2013
comment
Я использовал этот подход инженером Apple UIKit на этой неделе в их лаборатории Tech Talks. Хотя он, конечно, не одобрил бы этот подход, он признал необходимость эффекта и отсутствие для этого реального общедоступного API и сказал, что этот подход на данный момент является наименее опасным вариантом и довольно безопасен, как написано. В частности, он сказал, что не пытайтесь делать какие-либо анимации frame или transform этой панели инструментов / представления или чего-либо подобного, иначе произойдут плохие вещи. Он также настоятельно рекомендовал отправлять отчеты об ошибках радара по этому поводу, чтобы создать внутреннее обоснование, чтобы мы могли получить настоящий общедоступный API для этого эффекта! - person smileyborg; 10.10.2013
comment
Интересно ... похоже, что аккаунт @ user2342340 был создан только для того, чтобы анонимно ответить на этот вопрос. Заставляет задуматься, не является ли это неофициальным постом того, кто знает об этих вещах больше, чем все мы :) - person smileyborg; 17.12.2013
comment
Это не работает на iPhone 4 под управлением iOS 7. Вероятно, это связано с тем, что на iPhone 4, поскольку мощность графического процессора слишком мала, система не добавляет обычный эффект размытия к самому себе. - person Ayush Goel; 06.02.2014
comment
Кто-нибудь знает, будет ли отвергнут следующий сценарий? Добавьте UIToolbar в UIView и анимируйте фрейм UIView (y origin только для уточнения). - person Brad G; 19.02.2014
comment
Как сделать его небелым? Если я изменю цвет фона для панели инструментов, размытие не будет. - person Nikita P; 25.02.2014
comment
@NikitaP Используйте стиль черной полосы. - person Leo Natan; 21.04.2014
comment
Теперь, когда в iOS 8 для этого есть API, вот небольшой код для iOS 7 и 8: stackoverflow.com/a/ 25669695/364446 - person KPM; 18.09.2014

Apple выпустила код на WWDC в качестве категории на UIImage, которая включает эту функцию. Если у вас есть учетная запись разработчика, вы можете получить категорию UIImage (и остальную часть примера кода), перейдя по этой ссылке: https://developer.apple.com/wwdc/schedule/, просматривая раздел 226 и нажимая на подробности. Я еще не играл с ним, но думаю, что эффект будет намного медленнее в iOS 6, есть некоторые улучшения в iOS 7, которые делают захват начального снимка экрана, который используется в качестве входных данных для размытия, намного быстрее.

Прямая ссылка: https://developer.apple.com/downloads/download.action?path=wwdc_2013/wwdc_2013_sample_code/ios_uiimageeffects.zip

person FreaknBigPanda    schedule 08.07.2013
comment
Я вижу видео, могу посмотреть, но не могу понять, где скачать образец кода! - person Nathan H; 01.09.2013
comment
Я не заметил большой разницы по сравнению с простым изменением фона альфа-канала; возможно, это потому, что я показываю видео, и им просто нужно больше размытия ... - person Ja͢ck; 17.09.2014

На самом деле я готов поспорить, что этого будет довольно просто достичь. Вероятно, он не будет работать или выглядеть точно так же, как 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. Это основано на алгоритме, который вы можете найти в здесь.

@implementation UIImage (Blur)

-(UIImage *)boxblurImageWithBlur:(CGFloat)blur {
    if (blur < 0.f || blur > 1.f) {
        blur = 0.5f;
    }
    int boxSize = (int)(blur * 50);
    boxSize = boxSize - (boxSize % 2) + 1;

    CGImageRef img = self.CGImage;

    vImage_Buffer inBuffer, outBuffer;

    vImage_Error error;

    void *pixelBuffer;

    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);

    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);

    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);

    pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));

    if(pixelBuffer == NULL)
        NSLog(@"No pixelbuffer");

    outBuffer.data = pixelBuffer;
    outBuffer.width = CGImageGetWidth(img);
    outBuffer.height = CGImageGetHeight(img);
    outBuffer.rowBytes = CGImageGetBytesPerRow(img);

    error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);

    if (error) {
        NSLog(@"JFDepthView: error from convolution %ld", error);
    }

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
                                         outBuffer.width,
                                         outBuffer.height,
                                         8,
                                         outBuffer.rowBytes,
                                         colorSpace,
                                         kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
    UIImage *returnImage = [UIImage imageWithCGImage:imageRef];

    //clean up
    CGContextRelease(ctx);
    CGColorSpaceRelease(colorSpace);

    free(pixelBuffer);
    CFRelease(inBitmapData);

    CGImageRelease(imageRef);

    return returnImage;
}

@end

Теперь, когда вы вычисляете область экрана для размытия, передаете ее в категорию размытия и получаете обратно размытый UIImage, теперь остается только установить это размытое изображение в качестве фона для представления, которое вы будете представлять. Как я уже сказал, это не будет идеально соответствовать тому, что делает Apple, но все равно должно выглядеть довольно круто.

Надеюсь, это поможет.

person Jeremy Fox    schedule 16.06.2013
comment
Кажется, что поменялись местами синий и красный цвет размытого изображения. - person Henry; 09.07.2013
comment
Похоже, кто-то использовал ваш код для создания этого проекта: github.com/alexdrone/ios-realtimeblur/blob/master/RealTimeBlur/, но, к сожалению, авторство отсутствует, и они добавили вверху заявление об авторских правах« Все права защищены ». - person Mark Erdmann; 14.08.2013
comment
@Mark, спасибо за внимание. Однако этот алгоритм размытия не мой собственный. Я уже упоминал, откуда я это взял, в своем посте выше. Как говорится в моем сообщении, это основано на алгоритме, который вы можете найти здесь. со ссылкой на indieambitions.com/idevblogaday/ Я обязательно отправлю этому человеку сообщение и сообщу ему, что у него отсутствует указание авторства. Спасибо - person Jeremy Fox; 14.08.2013
comment
@MarkErdmann взгляните на свои собственные файлы в xcode. Все права защищены. Это общая вещь, которую добавляет xcode. Также автор добавил только что добавленную лицензию.md, в которой говорится, что она лицензирована под лицензией MIT. - person Andrew; 16.08.2013
comment
Не используйте renderInContext, используйте новый drawViewHierarchyInRect: или snapshotView:. WWDC talk 216 «Внедрение привлекательного пользовательского интерфейса на iOS7» заявляет о 5-15-кратном улучшении производительности. - person bcattle; 04.02.2014
comment
@bcattle Спасибо, я отредактировал ответ и добавил drawViewHierarchyInRect:afterScreenUpdates: - person Jeremy Fox; 04.02.2014

iOS8 ответила на эти вопросы.

UIVisualEffect

- (instancetype)initWithEffect:(UIVisualEffect *)effect

или Swift:

init(effect effect: UIVisualEffect)

person Adam Waite    schedule 11.09.2014
comment
Думаю, это решение бесполезно, пока не выйдет iOS 9. Большинство приложений по-прежнему поддерживают iOS 7, и это решение там не поддерживается. - person Dmitry Sobolev; 01.11.2014
comment
правда, правда, сейчас вы можете использовать такие вещи: github.com/nicklockwood/FXBlurView - person Adam Waite; 01.11.2014
comment
Я реализовал это с помощью инструментария Xcode 6 с iOS8, и он отлично работает. Я пробовал реализовать на CPU, но работает заметно медленнее, чем этот метод. - person Jon; 10.03.2015
comment
Зачем кодировать, когда Xcode предоставляет в самом раскадровке !!!!! Спасибо @AdamWaite - person Mihir Oza; 11.06.2020

Я только что написал свой небольшой подкласс UIView, который может создавать собственное размытие iOS 7 в любом пользовательском представлении. Он использует UIToolbar, но безопасным способом для изменения его кадра, границ, цвета и альфа-канала с анимацией в реальном времени.

Пожалуйста, дайте мне знать, если заметите какие-либо проблемы.

https://github.com/ivoleko/ILTranslucentView

Примеры ILTranslucentView

person Ivo Leko    schedule 21.10.2013
comment
Я пробовал и другие подходы (например, сам добавлял UIToolbar или категорию Apple UIImage + ImageEffects.h); ваше было лучшим и самым простым решением. Спасибо! - person Yunus Nedim Mehel; 24.10.2013
comment
Насколько хорошо он реагирует на новую загрузку iOS 7.0.3? Другие классы, которые использовали эту технику, больше не отображаются правильно: [ - person achi; 27.10.2013
comment
@achi, с iOS 7.0.3 проблем не заметил. - person Ivo Leko; 11.11.2013
comment
Знаете ли вы, были ли какие-либо приложения, которые анимируются с использованием вашего подхода, были приняты Apple? - person Brad G; 19.02.2014
comment
Привет, народ. Да, приложение, использующее этот класс, будет одобрено Apple! - person Ivo Leko; 22.07.2014

Ходят слухи, что инженеры Apple утверждают, что для обеспечения такой производительности они считывают данные непосредственно из буфера графического процессора, что вызывает проблемы с безопасностью, поэтому пока нет общедоступного API для этого.

person Cody C    schedule 25.06.2013
comment
Если это правда, то это, безусловно, худшее решение. - person elslooo; 09.08.2013
comment
аааааи размытие удалено из iOS 7. - person Code Guru; 04.09.2013
comment
Он был удален только на устройствах, на которых наблюдались проблемы с производительностью. - person Cody C; 04.09.2013
comment
Этот пост - источник слухов? :) - person Jano; 18.09.2013
comment
Этот слух, вероятно, чушь. OpenGL ES 2.0 на iOS позволяет читать и записывать в фреймбуферы без какого-либо риска для безопасности. Размытие выполняется с помощью шейдеров GLSL, поэтому оно выполняется быстро. - person bentford; 18.09.2013
comment
@Jano, ты убил меня, братан - person Edward Anthony; 30.07.2015

Это решение, которое вы можете увидеть на видеороликах WWDC. Вам нужно сделать размытие по Гауссу, поэтому первое, что вам нужно сделать, это добавить новый файл .m и .h с кодом, который я пишу здесь, затем вы должны сделать снимок экрана, использовать желаемый эффект и добавьте его в свое представление, затем ваш UITable UIView или что-то еще должно быть прозрачным, вы можете поиграть с applyBlurWithRadius, чтобы заархивировать желаемый эффект, этот вызов работает с любым UIImage.

В конце размытое изображение будет фоном, а остальные элементы управления должны быть прозрачными.

Чтобы это работало, вам нужно добавить следующие библиотеки:

Acelerate.framework, UIKit.framework, CoreGraphics.framework

Я надеюсь тебе это понравится.

Удачного кодирования.

    //Screen capture.
    UIGraphicsBeginImageContext(self.view.bounds.size);

    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(c, 0, 0);
    [self.view.layer renderInContext:c];

    UIImage* viewImage = UIGraphicsGetImageFromCurrentImageContext();
    viewImage = [viewImage applyLightEffect];

    UIGraphicsEndImageContext();

    //.h FILE
    #import <UIKit/UIKit.h>

    @interface UIImage (ImageEffects)

   - (UIImage *)applyLightEffect;
   - (UIImage *)applyExtraLightEffect;
   - (UIImage *)applyDarkEffect;
   - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;

   - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;

   @end

    //.m FILE
    #import "cGaussianEffect.h"
    #import <Accelerate/Accelerate.h>
    #import <float.h>


     @implementation UIImage (ImageEffects)


    - (UIImage *)applyLightEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyExtraLightEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyDarkEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor
    {
        const CGFloat EffectColorAlpha = 0.6;
        UIColor *effectColor = tintColor;
        int componentCount = CGColorGetNumberOfComponents(tintColor.CGColor);
        if (componentCount == 2) {
            CGFloat b;
            if ([tintColor getWhite:&b alpha:NULL]) {
                effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
            }
        }
        else {
            CGFloat r, g, b;
            if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
                effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
            }
        }
        return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil];
    }


    - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
    {
        if (self.size.width < 1 || self.size.height < 1) {
            NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
            return nil;
        }
        if (!self.CGImage) {
            NSLog (@"*** error: image must be backed by a CGImage: %@", self);
            return nil;
        }
        if (maskImage && !maskImage.CGImage) {
            NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
            return nil;
        }

        CGRect imageRect = { CGPointZero, self.size };
        UIImage *effectImage = self;

        BOOL hasBlur = blurRadius > __FLT_EPSILON__;
        BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
        if (hasBlur || hasSaturationChange) {
            UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
            CGContextRef effectInContext = UIGraphicsGetCurrentContext();
            CGContextScaleCTM(effectInContext, 1.0, -1.0);
            CGContextTranslateCTM(effectInContext, 0, -self.size.height);
            CGContextDrawImage(effectInContext, imageRect, self.CGImage);

            vImage_Buffer effectInBuffer;
            effectInBuffer.data     = CGBitmapContextGetData(effectInContext);
            effectInBuffer.width    = CGBitmapContextGetWidth(effectInContext);
            effectInBuffer.height   = CGBitmapContextGetHeight(effectInContext);
            effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);

            UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
            CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
            vImage_Buffer effectOutBuffer;
            effectOutBuffer.data     = CGBitmapContextGetData(effectOutContext);
            effectOutBuffer.width    = CGBitmapContextGetWidth(effectOutContext);
            effectOutBuffer.height   = CGBitmapContextGetHeight(effectOutContext);
            effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);

            if (hasBlur) {
                CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
                NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
                if (radius % 2 != 1) {
                    radius += 1;
                }
                vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
                vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
                vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
            }
            BOOL effectImageBuffersAreSwapped = NO;
            if (hasSaturationChange) {
                CGFloat s = saturationDeltaFactor;
                CGFloat floatingPointSaturationMatrix[] = {
                    0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,
                    0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,
                    0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,
                                  0,                    0,                    0,  1,
                };
                const int32_t divisor = 256;
                NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
                int16_t saturationMatrix[matrixSize];
                for (NSUInteger i = 0; i < matrixSize; ++i) {
                    saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
                }
                if (hasBlur) {
                    vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
                    effectImageBuffersAreSwapped = YES;
                }
                else {
                    vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
                }
            }
            if (!effectImageBuffersAreSwapped)
                effectImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            if (effectImageBuffersAreSwapped)
                effectImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
        }

        UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
        CGContextRef outputContext = UIGraphicsGetCurrentContext();
        CGContextScaleCTM(outputContext, 1.0, -1.0);
        CGContextTranslateCTM(outputContext, 0, -self.size.height);

        CGContextDrawImage(outputContext, imageRect, self.CGImage);

        if (hasBlur) {
            CGContextSaveGState(outputContext);
            if (maskImage) {
                CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
            }
            CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
            CGContextRestoreGState(outputContext);
        }

        if (tintColor) {
            CGContextSaveGState(outputContext);
            CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
            CGContextFillRect(outputContext, imageRect);
            CGContextRestoreGState(outputContext);
        }

        UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return outputImage;
    }
person Stornu2    schedule 26.09.2013

Вы можете найти свое решение в демонстрационной версии 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];
}

Надеюсь, что это поможет вам.

person Senry    schedule 04.09.2013


Каждый ответ здесь использует 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:

#import "UIImage+Utils.h"

#import "GPUImagePicture.h"
#import "GPUImageSolidColorGenerator.h"
#import "GPUImageAlphaBlendFilter.h"
#import "GPUImageBoxBlurFilter.h"

@implementation UIImage (Utils)

- (UIImage*) GPUBlurredImage
{
    GPUImagePicture *source =[[GPUImagePicture alloc] initWithImage:self];

    CGSize size = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale);

    GPUImageBoxBlurFilter *blur = [[GPUImageBoxBlurFilter alloc] init];
    [blur setBlurRadiusInPixels:4.0f];
    [blur setBlurPasses:2.0f];
    [blur forceProcessingAtSize:size];
    [source addTarget:blur];

    GPUImageSolidColorGenerator * white = [[GPUImageSolidColorGenerator alloc] init];

    [white setColorRed:1.0f green:1.0f blue:1.0f alpha:0.1f];
    [white forceProcessingAtSize:size];

    GPUImageAlphaBlendFilter * blend = [[GPUImageAlphaBlendFilter alloc] init];
    blend.mix = 0.9f;

    [blur addTarget:blend];
    [white addTarget:blend];

    [blend forceProcessingAtSize:size];
    [source processImage];

    return [blend imageFromCurrentlyProcessedOutput];
}

@end

И наконец, добавьте в свой проект следующие фреймворки:

AVFoundation CoreMedia CoreVideo OpenGLES

Да, получил удовольствие от этого гораздо более быстрого подхода;)

person D33pN16h7    schedule 20.11.2013

Вы можете попробовать использовать мой пользовательский вид, в котором есть возможность размывать фон. Он делает это, имитируя снимок фона и размывая его, как в коде WWDC от Apple. Очень просто использовать.

Я также сделал некоторые улучшения, чтобы имитировать динамическое размытие без потери производительности. Фоном моего представления является scrollView, который прокручивается вместе с представлением, тем самым обеспечивая эффект размытия для остальной части супервизора.

См. Пример и код на моем GitHub

person Byte    schedule 17.09.2013

Core Background реализует желаемый эффект iOS 7.

https://github.com/justinmfischer/core-background

Отказ от ответственности: я являюсь автором этого проекта

person Justin Fischer    schedule 03.07.2013