Як я можу створити ефект, подібний перегляду розмиття iOS 7?


219

Я намагаюся повторити цей розмитий фон із публічно випущеного на екрані iOS 7 приклада Apple:

Скріншот iOS 7 Control Center

Це питання пропонує застосувати фільтр CI до вмісту нижче, але це зовсім інший підхід. Очевидно, що iOS 7 з багатьох причин не фіксує вміст переглядів нижче:

  1. Проводячи грубі тестування, знімайте знімок зображень нижче та застосовуючи фільтр CIGaussianBlur з достатньо великим радіусом для імітації стилю розмиття iOS 7 займає 1-2 секунди навіть на тренажері.
  2. Вид розмиття iOS 7 здатний розмиватися над динамічними видами, такими як відео чи анімація, без помітного відставання.

Чи може хтось гіпотезувати, які рамки вони могли використовувати для створення цього ефекту, і якщо можливо створити подібний ефект із поточними загальнодоступними API?

Редагувати: (з коментаря) Ми точно не знаємо, як це робить Apple, але чи є основні припущення, які ми можемо зробити? Ми можемо припустити, що вони використовують апаратне забезпечення, правда?

Чи ефект у кожному погляді автономний, щоб ефект насправді не знав, що за ним стоїть? Або, виходячи з того, як розмиття працює, слід враховувати вміст, що стоїть за розмиттям?

Якщо вміст, що стоїть за ефектом, є релевантним, чи можна припустити, що Apple отримує "подачу" вмісту внизу та постійно виводить їх із розмиттям?


(Я думаю, ми можемо припустити, що Apple використовує чистий GL для рендерингу домашніх екранів у будь-якому випадку. Я сумніваюся, що вони абстрагують його UIViews та іншими речами, які б погіршили продуктивність, оскільки це така ключова частина ОС)
Дейв,

Як я вказав у коментарях до моєї відповіді тут: stackoverflow.com/a/17048668/19679 вони написали ОС, тому, звичайно, вони матимуть прискорений доступ до вмісту шарів, складених під поточним поданням. Ми можемо побачити деякі з того, що вони можуть використовувати в приватному IOSurface API: stackoverflow.com/questions/14135215 / ... . Розмивання Гаусса можна зробити набагато швидше, ніж узагальнені випадки розмиття Гаусса, якщо вони мають фіксований радіус або навіть використовують цікаві оптимізації, як цілісні зображення.
Бред Ларсон

@BradLarson - Перефразовуючи Джессіку Сімпсон ... Я поняття не маю, що все це означає, але це звучить круто, як чорт! Але якщо говорити серйозно, ви хочете сказати, що ви можете використовувати частково прозорий вид з фільтрами розмиття та розмістити його над іншим видом для досягнення цього ефекту?
сангонія

stackoverflow.com/a/25706250/2308190 прекрасно працював для мене перший раз, коли я спробував це, і був лаконічним
Бен Уілер

Відповіді:


134

Навіщо турбувати повтор ефекту? Просто намалюйте панель UITool за своїм поданням.

myView.backgroundColor = [UIColor clearColor];
UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:myView.frame];
bgToolbar.barStyle = UIBarStyleDefault;
[myView.superview insertSubview:bgToolbar belowSubview:myView];

8
Я не згоден із crizzwald. Я не думаю, що це добре тлумачення правил очікування того, що зробить APple.
Ендрю Джонсон

117
Цього тижня я застосував інженер Apple UIKit у лабораторії Tech Talks. Хоча він, звичайно, не схвалює такого підходу, він визнав необхідність ефекту та відсутність реального публічного API для цього, і сказав, що цей підхід є "найменш злим" варіантом на даний момент і є досить безпечним, як написано. В Зокрема , він сказав , не намагатися робити якісь - або анімації з frameабо transformцієї панелі інструментів / зору чи що - небудь подібне, або погані речі будуть відбуватися. Він також настійно запропонував подати звіти про помилки Radar про це, щоб створити справу всередині, щоб ми могли отримати справжній публічний API для цього ефекту!
smileyborg

44
Цікаво ... схоже, обліковий запис @ user2342340 створено просто для того, щоб відповісти на це питання анонімно. Вас здивує, чи це не неофіційний пост того, хто про ці речі знає більше, ніж решта нас :)
smileyborg

4
Це не працює на iPhone 4 під управлінням iOS 7. Це можливо, тому що в iPhone 4, оскільки потужність GPU занадто низька, система не додає звичного ефекту розмиття до UITabBarсамої себе.
Айуш Гоел

2
Як зробити його небілим? Якщо я змінити колір фону для панелі інструментів, він не відображатиме розмиття.
Микита П

64

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

Пряме посилання: https://developer.apple.com/downloads/download.action?path=wwdc_2013/wwdc_2013_sample_code/ios_uiimageeffects.zip


1
Я бачу відео, можу його переглянути, але не можу зрозуміти, де завантажити зразок коду!
Натан Н

Я не бачив великої різниці порівняно з простою фоновою зміною альфа; можливо, це тому, що я
показую

37

Насправді я б обміняв, що цього було б досить просто досягти. Це, ймовірно, не буде працювати або виглядати так, як відбувається в 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, але все одно це повинно виглядати досить круто.

Сподіваюся, це допомагає.


Здається, що синій колір та червоний колір розмитого зображення перекинулися.
Генрі

Схоже, хтось використав ваш код для створення цього проекту: github.com/alexdrone/ios-realtimeblur/blob/master/RealTimeBlur/…, але, на жаль, атрибуції немає, і вони додали заяву про авторські права "Усі права захищені" на вершині.
Марк Ердман

@ Марк, дякую за голову вгору. Однак цей алгоритм розмивання не є моїм власним. Я вже згадував, звідки я це взяв у своєму дописі вище. Як говориться в моєму дописі "Це засновано на алгоритмі, який ви можете знайти тут". із посиланням на indieambitions.com/idevblogaday/… Я обов'язково надішлю цій людині повідомлення та повідомляю їм, що вони відсутні. Спасибі
Джеремі Фокс

@MarkErdmann подивіться на власні файли у xcode. У ньому є "Усі права захищені". Це загальна річ, яка додає xcode. Також автор додав щойно додану ліцензію.md, в якій говориться про те, що її відвідували під ліцензією
Санта Клаус

Чи не слід використовувати renderInContext, використовуйте новий drawViewHierarchyInRect:або snapshotView:. WWDC talk 216 "Реалізація залученого інтерфейсу на iOS7" вимагає покращення продуктивності в 5-15 разів.
bcattle

25

iOS8 відповів на ці питання.

UIVisualEffect

- (instancetype)initWithEffect:(UIVisualEffect *)effect

або Swift:

init(effect effect: UIVisualEffect)


Я думаю, що це рішення здебільшого марно, поки iOS 9 не вийде. Більшість додатків все ще підтримують iOS 7, і це рішення там не підтримується.
Дмитро Соболєв

справжнє правда, ви можете використовувати цю річ зараз: github.com/nicklockwood/FXBlurView
Adam Waite

Я реалізував це за допомогою інструментарію Xcode 6 з iOS8, і він чудово працює. Я намагався реалізувати за допомогою процесора, але працює помітно повільніше, ніж цей метод.
Jon

Чому кодувати, коли Xcode надає в самій раскадровці !!!!! Завдяки @AdamWaite
Mihir Оза

20

Я щойно написав мій маленький підклас UIView, який має можливість створювати вбудовану розмиття iOS 7 у будь-якому власному режимі. Він використовує панель UITool, але безпечним способом зміни рамки, меж, кольорів та альфа з анімацією в реальному часі.

Будь ласка, повідомте мене, якщо ви помітили якісь проблеми.

https://github.com/ivoleko/ILTranslucentView

Приклади ILTranslucentView


Я спробував деякі інші підходи (наприклад, сам додати панель UITool або категорію UIImage + ImageEffects.h від Apple); ваше було найкращим і найпростішим рішенням. Дякую!
Юнус Недім Мехель

4
Наскільки добре він реагує на нове завантаження iOS 7.0.3? Інші класи, які використовували цю методику, більше не відображаються правильно: [
achi

@achi, я не помітив жодної проблеми з iOS 7.0.3.
Іво Леко

Чи знаєте ви, чи якісь програми, які анімують за допомогою вашого підходу, чи були прийняті Apple?
Бред Госс

Привіт, народ. Так, додаток, який використовує цей клас, буде схвалений Apple!
Іво Леко

10

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


6
Якщо це правда, то це - на сьогоднішній день - найгірше рішення.
elslooo

2
aaaaaand розмиття видалено з iOS 7.
Code Guru

3
Її було видалено лише на пристроях, які бачили проблеми з продуктивністю.
Cody C

24
Чи є цей пост джерелом чуток? :)
Яно

11
Ця чутка, мабуть, двоярусна. OpenGL ES 2.0 на iOS дозволяє читати та писати у фреймбуфери без будь-якого ризику для безпеки. Розмиття виконується за допомогою шейдерів GLSL, саме тому воно працює швидко.
Бентфорд

7

Це рішення, яке ви можете побачити у відеороликах 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;
    }

7

Ви можете знайти своє рішення з DEMO 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];
}

Сподіваюся, що це вам допоможе.


7

Ось дійсно простий спосіб зробити це: https://github.com/JagCesar/iOS-blur

Просто скопіюйте шар UIToolbar і AMBlurView зробить це за вас. Гаразд, це не так розмито, як центр управління, але достатньо розмито.

Пам'ятайте, що iOS7 знаходиться під NDA.


6

Кожна відповідь тут використовується vImageBoxConvolve_ARGB8888 ця функція дійсно, дуже повільна, це прекрасно, якщо продуктивність не є вимогою високого пріоритету, але якщо ви цю функцію для переходу між двома контролерами перегляду (наприклад), такий підхід означає рази більше 1 друге або, можливо, більше, це дуже погано для користувацького досвіду вашої програми.

Якщо ви віддаєте перевагу залишити всю цю обробку зображення на графічному процесорі (і вам слід), ви можете отримати набагато кращий ефект, а також приголомшливі рази, округлюючи 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

Так, повеселіться цим набагато швидшим підходом;)


4

Ви можете спробувати скористатися моїм власним представленням, яке має можливість розмити фон. Це робиться, підробляючи знімок фону і розмиваючи його, як і той, який у WWDC-коді Apple. Це дуже просто у використанні.

Я також домігся покращення, щоб підробити динамічну розмитість, не втрачаючи продуктивність. Фон мого перегляду - це scrollView, який прокручується з видом, таким чином забезпечуючи ефект розмиття для решти огляду.

Дивіться приклад та код на моєму GitHub


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.