İOS 7 bulanıklık görünümüne benzer bir efekt nasıl üretebilirim?


219

Apple'ın herkese açık olarak yayınlanan iOS 7 örnek ekranından bu bulanık arka planı çoğaltmaya çalışıyorum:

iOS 7 Control Center ekran görüntüsü

Bu soru , aşağıdaki içeriklere bir CI filtresi uygulanmasını önermektedir, ancak bu tamamen farklı bir yaklaşımdır. İOS 7'nin birçok nedenden dolayı aşağıdaki görünümlerin içeriğini yakalamadığı açıktır:

  1. Bazı kaba testler yapmak, aşağıdaki görünümlerin ekran görüntüsünü yakalamak ve iOS 7'nin bulanıklık stilini taklit etmek için yeterince geniş bir yarıçapa sahip bir CIGaussianBlur filtresi uygulamak, bir simülatörde bile 1-2 saniye sürer.
  2. İOS 7 bulanıklaştırma görünümü, video veya animasyon gibi dinamik görünümler üzerinde belirgin bir gecikme olmadan bulanıklaşabilir.

Herkes bu efekti oluşturmak için hangi çerçeveleri kullanabileceklerini ve mevcut herkese açık API'larla benzer bir efekt oluşturmanın mümkün olup olmadığını varsayabilir mi?

Düzenle: (yorumdan) Tam olarak Apple'ın bunu nasıl yaptığını bilmiyoruz, ancak yapabileceğimiz temel varsayımlar var mı? Donanım kullandıklarını varsayabiliriz, değil mi?

Etki, her görüşte bağımsız mıdır, öyle ki efekt aslında arkasında ne olduğunu bilmez mi? Veya bulanıklığın nasıl çalıştığına bağlı olarak, bulanıklığın arkasındaki içerikler dikkate alınmalı mıdır?

Efektin arkasındaki içerikler ilgiliyse, Apple'ın aşağıdaki içeriklerden bir "özet akışı" aldığını ve bunları sürekli olarak bulanıklaştırdığını varsayabilir miyiz?


(Bence elmanın ana ekranları oluşturmak için saf GL kullandığını varsayabiliriz. UIViews ve işletim sisteminin önemli bir parçası olduğu için performansı düşürebilecek diğer şeylerle soyutladıklarından şüpheliyim)
Dave

Buradaki cevabımın yorumlarında belirttiğim gibi: stackoverflow.com/a/17048668/19679 işletim sistemini yazdılar, bu yüzden elbette mevcut görünümün altında birleştirilmiş katmanların içeriğine hızlı bir şekilde erişecekler. Özel IOSurface API'sında kullanabileceklerinin bazılarını görebiliriz: stackoverflow.com/questions/14135215/… . Gauss bulanıklaştırmaları, sabit bir yarıçapa sahipse veya hatta entegre görüntüler gibi ilginç optimizasyonlar kullanıyorsa, genel Gauss bulanıklaştırma durumlarından çok daha hızlı yapılabilir.
Brad Larson

@BradLarson - Jessica Simpson'ı yorumlamak için ... Bunun ne anlama geldiğini bilmiyorum ama kulağa hoş geliyor! Ama cidden, bir bulanıklık filtresiyle kısmen şeffaf bir görünüm kullanabileceğinizi ve bu efekti elde etmek için başka bir görünümün üzerine koyabileceğinizi mi söylüyorsunuz?
sangony

stackoverflow.com/a/25706250/2308190 ilk denediğimde benim için mükemmel çalıştı ve özlü oldu
Ben Wheeler

Yanıtlar:


134

Neden efekti kopyalamak zahmetine girsin? Sadece görünümünüzün arkasına bir UIToolbar çizin.

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

8
Crizzwald'a katılmıyorum. Bunun APple'in ne yapacağına dair beklenti kurallarının iyi bir yorumu olduğunu düşünmüyorum.
Andrew Johnson

117
Bu yaklaşımı bu hafta bir Apple UIKit mühendisi tarafından Tech Talks laboratuvarında çalıştırdım. Bu yaklaşımı kesinlikle kabul etmeyecek olsa da, bunun için gerçek kamusal API'nın etkisine ve eksikliğine olan ihtiyacı fark etti ve bu yaklaşımın şimdilik "en az kötü" seçenek olduğunu ve yazılı olarak oldukça güvenli olduğunu söyledi. Özellikle , bu araç çubuğunun / görünümünün veya herhangi bir animasyonunu frameveya transformbunun gibi herhangi bir animasyonu yapmaya çalışmadığını veya kötü şeylerin olacağını söyledi. Ayrıca, bu etki için gerçek bir genel API alabilmemiz için dahili olarak bir vaka oluşturmak üzere Radar hata raporları göndermenizi şiddetle tavsiye etti!
smileyborg

44
İlginç ... Görünüşe göre @ user2342340 hesabı sadece bu soruya anonim olarak cevap vermek için oluşturuldu. Bu şeyler hakkında geri kalanımızdan daha fazlasını bilen birinin resmi olmayan bir yazı olup olmadığını merak etmenizi sağlar :)
smileyborg

4
Bu, iOS 7 çalıştıran iPhone 4'te çalışmaz. Muhtemelen iPhone 4'te, GPU gücü çok düşük olduğundan, sistem UITabBarkendisine normal bulanıklık efektini eklemez .
Ayush Goel

2
Beyaz olmayan nasıl yapılır? Araç çubuğunun arka plan rengini değiştirirsem, bulanıklığı göstermez.
Nikita P

64

Apple, bu işlevselliği içeren bir UIImage kategorisi olarak WWDC'de kod yayınladı, bir geliştirici hesabınız varsa, şu bağlantıya giderek UIImage kategorisini (ve örnek kodun geri kalanını) alabilirsiniz: https://developer.apple. com / wwdc / schedule / adresine gidin ve bölüm 226'ya göz atın ve detayları tıklayın. Henüz onunla oynamadım, ancak etkinin iOS 6'da çok daha yavaş olacağını düşünüyorum, iOS 7'de, bulanıklığa çok daha hızlı girdi olarak kullanılan ilk ekran görüntüsünü yakalamayı sağlayan bazı geliştirmeler var.

Doğrudan bağlantı: https://developer.apple.com/downloads/download.action?path=wwdc_2013/wwdc_2013_sample_code/ios_uiimageeffects.zip


1
Videoyu izliyorum, izleyebiliyorum, ancak örnek kodun nereden indirileceğini bulamıyorum!
Nathan H

Basit bir arka plan alfa değişimine kıyasla çok fazla fark görmedim; belki de videoları görüntülüyorum ve sadece daha fazla bulanıklığa ihtiyaçları var ...
Ja͢ck

37

Aslında bunu başarmanın oldukça basit olacağına bahse girerim. Muhtemelen Apple'ın olup bittiği gibi çalışmayacak veya görünmeyecek, ancak çok yakın olabilirdi.

Her şeyden önce, sunacağınız UIView CGRect'ini belirlemeniz gerekir. Bulanıklaşabilmesi için kullanıcı arayüzünün bir kısmının görüntüsünü almanız gerektiğini belirledikten sonra. Böyle bir şey ...

- (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;
}

Gauss Bulanıklığı - Önerilir

BuradaUIImage+ImageEffects sağlanan Kategori Apple'ları kullanarak, iOS 7'deki bulanıklığa çok benzeyen bir gauss bulanıklığı elde edersiniz.

Kutu bulanıklığı

Aşağıdaki boxBlurImageWithBlur:UIImage kategorisini kullanarak bir kutu bulanıklığı da kullanabilirsiniz . Bu, burada bulabileceğiniz bir algoritmaya dayanmaktadır .

@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

Artık ekran alanını bulanıklaştırmak için hesaplıyor, bulanıklaştırma kategorisine geçiriyorsunuz ve bulanık bir UIImage geri alıyorsunuz, şimdi geriye kalan tek şey bu bulanık görüntüyü sunacağınız görünümün arka planı olarak ayarlamaktır. Dediğim gibi, bu Apple'ın yaptığı şey için mükemmel bir eşleşme olmayacak, ancak yine de oldukça havalı görünmeli.

Umarım yardımcı olur.


Bulanık görüntünün mavi rengi ve kırmızı rengi değişmiş gibi görünüyor.
Henry

Birisi bu projeyi oluşturmak için kodunuzu kullandı gibi görünüyor: github.com/alexdrone/ios-realtimeblur/blob/master/RealTimeBlur/… ama maalesef bir atıf yok ve "Tüm Hakları Saklıdır" telif hakkı bildirimi eklediler tepede.
Mark Erdmann

@ Mark, dikkatleri için teşekkürler. Ancak, bu bulanıklaştırma algoritması benim değil. Yukarıdaki yazımda nereden aldığımı söylemiştim. Yazımda söylediği gibi "Bu, burada bulabileceğiniz bir algoritmaya dayanıyor." indieambitions.com/idevblogaday/… bağlantı ile bu kişiye kesinlikle bir mesaj göndereceğim ve atıfta bulunmadıklarını bildireceğim. Teşekkürler
Jeremy Fox

@MarkErdmann xcode'da kendi dosyalarınıza bir göz atın. "Tüm Hakları Saklıdır". Bu, xcode'un eklediği genel bir şey. Ayrıca yazar sadece bir lisans ekledi. Mit lisence altında lisanslı diyor
Noel Baba

Kullanmayın renderInContext, yenisini kullanın drawViewHierarchyInRect:veya snapshotView:. WWDC talk 216 "iOS7'de İlgi Çekici Kullanıcı Arayüzünün Uygulanması" 5-15x performans artışı olduğunu iddia ediyor.
bcattle

25

iOS8 bu soruları yanıtladı.

UIVisualEffect

- (instancetype)initWithEffect:(UIVisualEffect *)effect

veya Swift:

init(effect effect: UIVisualEffect)


Bu çözüm, iOS 9 bitene kadar çoğunlukla işe yaramaz. Uygulamaların çoğu hala iOS 7'yi destekliyor ve bu çözüm orada desteklenmiyor.
Dmitry Sobolev

true true, şimdilik bu tür şeyleri kullanabilirsiniz: github.com/nicklockwood/FXBlurView
Adam Waite

Bunu iOS8 ile Xcode 6 araç zinciriyle uyguladım ve harika çalışıyor. CPU kullanarak uygulamaya çalıştım, ancak bu yöntemden belirgin şekilde daha yavaş çalışıyor.
Jon

Neden Xcode film şeridinin kendisinde sağladığı zaman kodlama !!!!! @AdamWaite
Mihir Oza

20

Herhangi bir özel görünümde yerel iOS 7 bulanıklığı üretme yeteneğine sahip küçük UIView alt sınıfımı yazdım. UIToolbar kullanır, ancak gerçek zamanlı animasyonla çerçevesini, sınırlarını, rengini ve alfa değerini değiştirmek için güvenli bir şekilde kullanır.

Herhangi bir sorun fark ederseniz lütfen bize bildirin.

https://github.com/ivoleko/ILTranslucentView

ILTranslucentView örnekleri


Başka yaklaşımlar denedim (kendim bir UIToolbar veya Apple'ın UIImage + ImageEffects.h kategorisi eklemek gibi); en iyi ve en kolay çözümdü. Teşekkürler!
Yunus Nedim Mehel

4
Yeni iOS 7.0.3 indirmesine ne kadar iyi tepki veriyor? Bu tekniği kullandık Diğer sınıflar artık doğru şekilde oluşturulmaz: [
achi

@achi, iOS 7.0.3 ile herhangi bir sorun fark etmedim.
Ivo Leko

Yaklaşımınızı kullanarak canlanan ve Apple tarafından kabul edilen herhangi bir uygulama olup olmadığını biliyor musunuz?
Brad Goss

Merhaba millet. Evet, bu sınıfı kullanan uygulama Apple tarafından onaylanacak!
Ivo Leko

10

Apple mühendislerinin iddia ettikleri bir söylenti var, bu performansı doğrudan gpu tamponundan okuyorlar, bu da güvenlik sorunlarını gündeme getiriyor, bu yüzden bunu yapmak için henüz kamuya açık bir API yok.


6
Eğer bu doğruysa, o zamana kadar - bu şimdiye kadarki en kötü çözümdür.
elslooo

2
aaaaave bulanıklık iOS 7'den kaldırıldı.
Code Guru

3
Yalnızca performans sorunları gören cihazlardan kaldırıldı.
Cody C

24
Bu yazı söylentinin kaynağı mı? :)
Jano

11
Bu söylenti muhtemelen ranza. İOS'ta OpenGL ES 2.0, herhangi bir güvenlik riski olmadan çerçeve tamponlarını okumanıza ve yazmanıza olanak tanır. Bulanıklık GLSL gölgelendiricileri kullanılarak yapılır, bu yüzden hızlı çalışır.
bentford

7

Bu, WWDC'nin videolarında görebileceğiniz bir çözümdür. Bir Gauss Bulanıklığı yapmak zorundasınız, bu yüzden yapmanız gereken ilk şey buraya yazdığım kodla yeni bir .m ve .h dosyası eklemek, sonra yapmak ve ekran çekimi yapmak, istenen efekti kullanmak ve görünümünüze ekleyin, sonra UITable UIView veya neyin şeffaf olması gerektiğine göre, istenen etkiyi arşivlemek için, bu çağrı herhangi bir UIImage ile çalışır.

Sonunda mevsimlik görüntü arka plan olacaktır ve yukarıdaki kontrollerin geri kalanı şeffaf olmalıdır.

Bunun çalışması için aşağıdaki kütüphaneleri eklemeniz gerekir:

Acelerate.framework, UIKit.framework, CoreGraphics.framework

Umarım beğenmişsindir.

Mutlu kodlama.

    //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

Çözümünüzü Apple DEMO'sundan bu sayfada bulabilirsiniz: WWDC 2013 , UIImageEffects örnek kodunu bulun ve indirin.

Sonra @ Jeremy Fox'un koduyla. Olarak değiştirdim

- (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];
}

Umarım bu size yardımcı olacaktır.


7

İşte bunu yapmanın gerçekten kolay bir yolu: https://github.com/JagCesar/iOS-blur

Sadece UIToolbar katmanını kopyalayın ve işiniz bitti, AMBlurView bunu sizin için yapar. Tamam, kontrol merkezi kadar bulanık değil ama yeterince bulanık.

İOS7'nin NDA altında olduğunu unutmayın.


6

Buradaki her yanıt vImageBoxConvolve_ARGB8888 kullanıyor, bu işlev gerçekten çok yavaş, yani performans yüksek öncelikli bir gereklilik değilse, ancak bunu iki Görünüm Kontrol Cihazı arasında geçiş yapmak için kullanıyorsanız (örneğin) bu yaklaşım 1'den fazla demektir ikincisi ya da daha fazlası, uygulamanızın kullanıcı deneyimi için çok kötü.

Tüm bu görüntü işlemeyi GPU'ya bırakmayı tercih ederseniz (Ve yapmalısınız) çok daha iyi bir etki elde edebilirsiniz ve ayrıca 50 ms'yi yuvarlayarak harika zamanlar elde edebilirsiniz (ilk yaklaşımda 1 saniyelik bir zamanınız olduğunu varsayalım), hadi yapalım .

Önce GPUImage Framework'ü (BSD Lisanslı) buradan indirin .

Sonra, GPUImage'dan aşağıdaki sınıfları (.m ve .h) ekleyin (bunların yalnızca bulanıklık efekti için gereken minimum değer olduğundan emin değilim)

  • 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

Ardından, UIImage'da mevcut bir UIImage'a bulanıklık efekti ekleyecek bir kategori oluşturun:

#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

Son olarak, projenize aşağıdaki çerçeveleri ekleyin:

AVFoundation CoreMedia CoreVideo OpenGLES

Evet, bu çok daha hızlı yaklaşımla eğlenin;)


4

Arka planı bulanıklaştırma özelliğine sahip özel görünümümü kullanmayı deneyebilirsiniz. Bunu, Apple'ın WWDC kodundaki gibi arka planın anlık görüntüsünü alıp bulanıklaştırarak yapar. Kullanması çok basit.

Ayrıca performansı kaybetmeden dinamik bulanıklaşmaya karşı bazı iyileştirmeler yaptım. Görünümümün arka planı, görünümle birlikte kayan, böylece denetimin geri kalanı için bulanıklaştırma efekti sağlayan bir scrollView.

GitHub'ımdaki örneğe ve koda bakın


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.