Làm cách nào tôi có thể tạo hiệu ứng tương tự như chế độ xem mờ của iOS 7?


219

Tôi đang cố gắng tái tạo nền mờ này từ màn hình ví dụ iOS 7 được phát hành công khai của Apple:

Ảnh chụp màn hình Trung tâm điều khiển iOS 7

Câu hỏi này gợi ý áp dụng bộ lọc CI cho các nội dung bên dưới, nhưng đó là một cách tiếp cận hoàn toàn khác. Rõ ràng là iOS 7 không nắm bắt được nội dung của các chế độ xem bên dưới, vì nhiều lý do:

  1. Thực hiện một số thử nghiệm sơ bộ, chụp ảnh màn hình của các chế độ xem bên dưới và áp dụng bộ lọc CIGaussianBlur với bán kính đủ lớn để bắt chước kiểu làm mờ của iOS 7 mất 1-2 giây, ngay cả trên trình giả lập.
  2. Chế độ xem mờ của iOS 7 có thể làm mờ các chế độ xem động, chẳng hạn như video hoặc hình động, không có độ trễ đáng chú ý.

Bất cứ ai cũng có thể đưa ra giả thuyết về những khung công tác nào họ có thể sử dụng để tạo hiệu ứng này và liệu có thể tạo hiệu ứng tương tự với các API công khai hiện tại không?

Chỉnh sửa: (từ nhận xét) Chúng tôi không biết chính xác Apple đang làm như thế nào, nhưng chúng tôi có thể đưa ra những giả định cơ bản nào không? Chúng ta có thể cho rằng họ đang sử dụng phần cứng, phải không?

Là hiệu ứng độc lập trong mỗi chế độ xem, sao cho hiệu ứng không thực sự biết những gì đằng sau nó? Hoặc phải, dựa trên cách làm mờ hoạt động, nội dung đằng sau mờ được xem xét?

Nếu nội dung đằng sau hiệu ứng có liên quan, chúng ta có thể cho rằng Apple đang nhận được "nguồn cấp" nội dung bên dưới và liên tục hiển thị chúng với độ mờ không?


(Tôi nghĩ rằng chúng ta có thể giả định rằng apple đang sử dụng GL thuần túy để hiển thị màn hình chính. Tôi nghi ngờ họ đang trừu tượng hóa nó với UIView và những thứ khác sẽ làm giảm hiệu suất, vì đó là một phần quan trọng của HĐH)
Dave

Như tôi đã chỉ ra trong các nhận xét cho câu trả lời của mình ở đây: stackoverflow.com/a/17048668/19679 họ đã viết HĐH, vì vậy tất nhiên họ sẽ tăng tốc truy cập vào nội dung của các lớp được tổng hợp bên dưới chế độ xem hiện tại. Chúng ta có thể thấy một số thứ họ có thể đang sử dụng trong API riêng của IOSurface: stackoverflow.com/questions/14135215/ . Làm mờ Gaussian có thể được thực hiện nhanh hơn nhiều so với các trường hợp làm mờ Gaussian tổng quát nếu chúng có bán kính cố định hoặc thậm chí sử dụng tối ưu hóa thú vị như hình ảnh tích hợp.
Brad Larson

@BradLarson - Để diễn giải Jessica Simpson ... Tôi không biết tất cả điều đó có nghĩa là gì nhưng nghe có vẻ hay đấy! Nhưng nghiêm túc, bạn đang nói rằng bạn có thể sử dụng chế độ xem một phần trong suốt với bộ lọc mờ aa và đặt nó trên một chế độ xem khác để đạt được hiệu ứng này?
sangony

stackoverflow.com/a/25706250/2308190 hoạt động hoàn hảo với tôi ngay lần đầu tiên tôi dùng thử, và ngắn gọn
Ben Wheeler

Câu trả lời:


134

Tại sao phải nhân rộng hiệu ứng? Chỉ cần vẽ một UIToolbar phía sau tầm nhìn của bạn.

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

8
Tôi không đồng ý với crizzwald. Tôi không nghĩ đó là một cách giải thích tốt về các quy tắc kỳ vọng về những gì APple sẽ làm.
Andrew Johnson

117
Tôi đã thực hiện phương pháp này bởi một kỹ sư Apple UIKit trong tuần này tại phòng thí nghiệm Tech Talks của họ. Mặc dù anh ta chắc chắn sẽ không tán thành cách tiếp cận này, anh ta nhận ra sự cần thiết của hiệu ứng và thiếu API công khai thực sự cho điều này, và nói rằng cách tiếp cận này là lựa chọn "ít tệ nhất" hiện nay và khá an toàn như được viết. Cụ thể, ông nói không cố gắng thực hiện bất kỳ hình ảnh động nào của framehoặc transformcủa thanh công cụ / chế độ xem này hoặc bất cứ điều gì tương tự, hoặc những điều xấu sẽ xảy ra. Ông cũng đề nghị mạnh mẽ nộp các báo cáo lỗi Radar về điều này, để xây dựng một trường hợp nội bộ để chúng tôi có thể có được một API công khai thực sự cho hiệu ứng này!
smileyborg

44
Thật thú vị ... có vẻ như tài khoản @ user2342340 được tạo ra chỉ để trả lời câu hỏi này ẩn danh. Làm cho bạn tự hỏi nếu đây không phải là một bài viết không chính thức bởi một người biết nhiều hơn những người còn lại về những điều này :)
smileyborg 17/12/13

4
Điều này không hoạt động trên iPhone 4 chạy iOS 7. Có thể là do trên iPhone 4, do công suất GPU quá thấp, hệ thống không thêm hiệu ứng làm mờ thông thường cho UITabBarchính nó.
Ayush Goel

2
Làm thế nào để tôi làm cho nó không trắng? Nếu tôi thay đổi màu nền cho thanh công cụ, nó sẽ không hiển thị mờ.
Nikita P

64

Apple đã phát hành mã tại WWDC dưới dạng danh mục trên UIImage bao gồm chức năng này, nếu bạn có tài khoản nhà phát triển, bạn có thể lấy danh mục UIImage (và phần còn lại của mã mẫu) bằng cách truy cập liên kết này: https://developer.apple. com / wwdc / calendar / và duyệt tìm phần 226 và nhấp vào chi tiết. Tôi chưa chơi xung quanh nó nhưng tôi nghĩ hiệu ứng sẽ chậm hơn rất nhiều trên iOS 6, có một số cải tiến đối với iOS 7 giúp chụp ảnh màn hình ban đầu được sử dụng làm đầu vào mờ nhanh hơn rất nhiều.

Liên kết trực tiếp: https://developer.apple.com/doads/doad.action?path=wwdc_2013/wwdc_2013_sample_code/ios_uiimageeffects.zip


1
Tôi xem video, tôi có thể xem nó, nhưng không thể tìm ra nơi để tải mã mẫu!
Nathan H

Tôi không thấy nhiều sự khác biệt so với thay đổi alpha nền đơn giản; có lẽ đó là vì tôi đang hiển thị video và chúng chỉ cần mờ hơn ...
Ja͢ck

37

Trên thực tế tôi đặt cược điều này sẽ khá đơn giản để đạt được. Nó có thể sẽ không hoạt động hoặc trông giống hệt như những gì Apple đang diễn ra nhưng có thể rất gần.

Trước hết, bạn cần xác định CGRect của UIView mà bạn sẽ trình bày. Khi bạn xác định rằng bạn chỉ cần lấy một hình ảnh của một phần của giao diện người dùng để nó có thể bị mờ. Một cái gì đó như thế này ...

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

Gaussian Blur - Khuyến nghị

Sử dụng UIImage+ImageEffectsDanh mục do Apple cung cấp tại đây , bạn sẽ nhận được một vệt mờ gaussian trông rất giống với mờ trong iOS 7.

Hộp mờ

Bạn cũng có thể sử dụng làm mờ hộp bằng cách sử dụng boxBlurImageWithBlur:danh mục UIImage sau . Điều này dựa trên một thuật toán mà bạn có thể tìm thấy ở đây .

@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

Bây giờ bạn đang tính diện tích màn hình để làm mờ, chuyển nó vào danh mục mờ và nhận lại UIImage đã bị mờ, bây giờ tất cả những gì còn lại là đặt hình ảnh mờ đó làm nền của chế độ xem bạn sẽ trình bày. Như tôi đã nói, đây sẽ không phải là một kết hợp hoàn hảo cho những gì Apple đang làm, nhưng nó vẫn trông khá tuyệt.

Hy vọng nó giúp.


Có vẻ như màu xanh lam và màu đỏ của hình ảnh bị mờ.
Henry

Có vẻ như ai đó đã sử dụng mã của bạn để tạo dự án này: github.com/alexdrone/ios-realtimeblur/blob/master/RealTimeBlur/, nhưng không may là không có sự ghi nhận và họ đã thêm một tuyên bố bản quyền "All Rights Reserved" ở trên cùng
Đánh dấu Erdmann

@Mark, cảm ơn vì đã ngẩng cao đầu. Tuy nhiên, thuật toán làm mờ này không phải là của riêng tôi. Tôi đã đề cập đến nơi tôi đã nhận nó từ bài viết của tôi ở trên. Như nó nói trong bài viết của tôi "Điều này dựa trên một thuật toán mà bạn có thể tìm thấy ở đây." với một liên kết đến indieambitions.com/idevblogaday/ mài Tôi chắc chắn sẽ gửi cho người này một tin nhắn và cho họ biết họ đang thiếu sự ghi nhận. Cảm ơn
Jeremy Fox

@MarkErdmann hãy xem các tệp của riêng bạn trong xcode. Nó có "Tất cả các quyền". Đó là một điều chung mà xcode thêm vào. Ngoài ra, tác giả đã thêm chỉ cần thêm một giấy phép.md nói rằng nó được cấp dưới quyền hạn
ông già Noel

Không sử dụng renderInContext, sử dụng mới drawViewHierarchyInRect:hoặc snapshotView:. WWDC nói chuyện 216 "Triển khai giao diện người dùng trên iOS7" yêu cầu cải thiện hiệu suất 5-15 lần.
bcattle

25

iOS8 đã trả lời những câu hỏi này.

UIVisualEffect

- (instancetype)initWithEffect:(UIVisualEffect *)effect

hoặc Swift:

init(effect effect: UIVisualEffect)


Tôi đoán giải pháp này chủ yếu là vô dụng cho đến khi iOS 9 ra mắt. Phần lớn các ứng dụng vẫn hỗ trợ iOS 7 và giải pháp này không được hỗ trợ ở đó.
Dmitry Sobolev

đúng sự thật, bạn có thể sử dụng loại điều này ngay bây giờ: github.com/nicklockwood/FXBlurView
Adam Waite

Tôi đã triển khai điều này với chuỗi công cụ Xcode 6 với iOS8 và nó hoạt động rất tốt. Tôi đã cố gắng thực hiện bằng CPU, nhưng hoạt động chậm hơn đáng kể so với phương pháp này.
Jon

Tại sao phải viết mã khi Xcode cung cấp trong bảng phân cảnh !!!!! Cảm ơn @AdamWaite
Mihir Oza

20

Tôi vừa viết lớp con nhỏ của UIView có khả năng tạo mờ iOS 7 gốc trên bất kỳ chế độ xem tùy chỉnh nào. Nó sử dụng UIToolbar nhưng theo cách an toàn để thay đổi khung, giới hạn, màu sắc và alpha với hình ảnh động thời gian thực.

Xin vui lòng cho tôi biết nếu bạn nhận thấy bất kỳ vấn đề.

https://github.com/ivoleko/ILTranslucentView

Ví dụ ILTranslucentView


Tôi đã thử một số cách tiếp cận khác (như tự thêm một UIToolbar hoặc danh mục UIImage + ImageEffects.h của Apple); của bạn là giải pháp tốt nhất và dễ dàng nhất. Cảm ơn!
Yunus Nedim Mehel

4
Nó phản ứng tốt như thế nào với bản tải xuống iOS 7.0.3 mới? Các lớp khác đã sử dụng kỹ thuật này không hiển thị chính xác nữa: [
achi

@achi, tôi không nhận thấy bất kỳ vấn đề nào với iOS 7.0.3.
Ivo Leko

Bạn có biết liệu có ứng dụng nào hoạt hình bằng cách sử dụng phương pháp của bạn và đã được Apple chấp nhận không?
Brad Goss

Chào các cậu. Có, ứng dụng sử dụng lớp này sẽ được Apple chấp thuận!
Ivo Leko

10

Có một tin đồn rằng các kỹ sư của Apple đã tuyên bố, để làm cho trình diễn này họ đang đọc trực tiếp ra khỏi bộ đệm gpu, điều này làm tăng các vấn đề bảo mật, đó là lý do tại sao chưa có API công khai để làm điều này.


6
Nếu điều này là đúng thì đó là - giải pháp tồi tệ nhất từ ​​trước đến nay.
elslooo

2
aaaaaand mờ được xóa khỏi iOS 7.
Code

3
Nó chỉ bị xóa trên các thiết bị đang gặp vấn đề về hiệu suất.
Cody C

24
Đây có phải là nguồn gốc của tin đồn? :)
Jano

11
Tin đồn đó có lẽ là bunk. OpenGL ES 2.0 trên iOS cho phép bạn đọc và ghi vào bộ đệm khung mà không có bất kỳ rủi ro bảo mật nào. Làm mờ được thực hiện bằng cách sử dụng các shader GLSL, đó là lý do tại sao nó chạy nhanh.
uốn cong

7

Đây là một giải pháp mà bạn có thể thấy trong các vidios của WWDC. Bạn phải thực hiện Gaussian Blur, vì vậy điều đầu tiên bạn phải làm là thêm tệp .m và .h mới với mã tôi đang viết ở đây, sau đó bạn phải tạo và chụp màn hình, sử dụng hiệu ứng mong muốn và thêm nó vào chế độ xem của bạn, sau đó là UIVable UITable của bạn hoặc những gì phải minh bạch, bạn có thể chơi với applicationBlurWithRadius, để lưu trữ hiệu ứng mong muốn, cuộc gọi này hoạt động với bất kỳ UIImage nào.

Cuối cùng, hình ảnh bị mờ sẽ là nền và phần còn lại của các điều khiển ở trên phải trong suốt.

Để làm việc này, bạn phải thêm các thư viện tiếp theo:

Acelerate.framework, UIKit.framework, CoreGraphics.framework

Tôi hy vọng bạn thích nó.

Chúc mừng mã hóa.

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

Bạn có thể tìm thấy giải pháp của mình từ DEMO của apple trong trang này: WWDC 2013 , tìm hiểu và tải xuống mã mẫu UIImageEffects.

Sau đó, với mã của @Jeremy Fox. Tôi đã đổi nó thành

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

Hy vọng điều này sẽ giúp bạn.


7

Đây là một cách thực sự dễ dàng: https://github.com/JagCesar/iOS-blur

Chỉ cần sao chép lớp UIToolbar và bạn đã hoàn thành, AMBlurView sẽ làm điều đó cho bạn. Được rồi, nó không mờ như trung tâm điều khiển, nhưng đủ mờ.

Hãy nhớ rằng iOS7 nằm dưới NDA.


6

Mọi phản hồi ở đây đều sử dụng vImageBoxConvolve_ARGB8888 , chức năng này thực sự rất chậm, điều đó tốt, nếu hiệu suất không phải là yêu cầu ưu tiên cao, nhưng nếu bạn đang sử dụng điều này để chuyển đổi giữa hai Bộ điều khiển xem (ví dụ) thì cách tiếp cận này có nghĩa là hơn 1 lần thứ hai hoặc có thể hơn, điều đó rất tệ cho trải nghiệm người dùng của ứng dụng của bạn.

Nếu bạn muốn để lại tất cả quá trình xử lý hình ảnh này cho GPU (Và bạn nên), bạn có thể có được hiệu ứng tốt hơn nhiều và thời gian làm tròn 50ms tuyệt vời (giả sử rằng bạn có thời gian 1 giây trong cách tiếp cận đầu tiên), vì vậy, hãy làm điều đó .

Trước tiên hãy tải xuống GPUImage Framework (BSD Licensed) tại đây .

Tiếp theo, Thêm các lớp sau (.m và .h) từ GPUImage (Tôi không chắc chắn đây là những mức tối thiểu cần thiết cho hiệu ứng làm mờ)

  • GPUImage.h
  • GPUImageAlphaBlendFilter
  • GPUImageFilter
  • GPUImageFiltergroup
  • GPUImageGaussianBlurPocationFilter
  • GPUImageGaussianSelectiveBlurFilter
  • GPUImageLuminanceRangeFilter
  • GPUImageOutput
  • GPUImageTwoInputFilter
  • Chương trình GL
  • GPUImageBoxBlurFilter
  • GPUImageGaussianBlurFilter
  • GPUImageiOSBlurFilter
  • GPUImageSaturationFilter
  • GPUImageSolidColorGenerator
  • GPUImageTwoPassFilter
  • GPUImageTwoPassTextureSamplingFilter

  • iOS / GPUImage-Prefix.pch

  • iOS / GPUImageContext
  • iOS / GPUImageMovieWriter
  • iOS / GPUImagePicture
  • Xem iOS / GPU

Tiếp theo, tạo một thể loại trên UIImage, điều đó sẽ thêm hiệu ứng làm mờ cho UIImage hiện có:

#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

Và cuối cùng, thêm các khung sau vào dự án của bạn:

AVFoundation CoreMedia CoreVideo OpenGLES

Vâng, vui vẻ với cách tiếp cận nhanh hơn nhiều này;)


4

Bạn có thể thử sử dụng chế độ xem tùy chỉnh của tôi, có khả năng làm mờ nền. Nó thực hiện điều này bằng cách giả mạo chụp ảnh nền và làm mờ nó, giống như ảnh trong mã WWDC của Apple. Nó rất đơn giản để sử dụng.

Tôi cũng đã thực hiện một số cải tiến để giả mạo mờ động mà không làm giảm hiệu suất. Nền của chế độ xem của tôi là một cuộn Xem cuộn với chế độ xem, do đó cung cấp hiệu ứng làm mờ cho phần còn lại của giám sát.

Xem ví dụ và mã trên GitHub của tôi


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.