Bagaimana saya bisa menghasilkan efek yang mirip dengan tampilan blur iOS 7?

219

Saya mencoba meniru latar belakang buram ini dari layar contoh iOS 7 yang dirilis Apple:

Tangkapan layar iOS 7 Control Center

Pertanyaan ini menyarankan menerapkan filter CI untuk konten di bawah ini, tetapi itu pendekatan yang sama sekali berbeda. Jelas bahwa iOS 7 tidak menangkap konten tampilan di bawah ini, karena berbagai alasan:

  1. Melakukan beberapa pengujian kasar, menangkap tangkapan layar tampilan di bawah dan menerapkan filter CIGaussianBlur dengan radius yang cukup besar untuk meniru gaya blur iOS 7 membutuhkan waktu 1-2 detik, bahkan pada simulator.
  2. Tampilan blur iOS 7 mampu mengaburkan tampilan dinamis, seperti video atau animasi, tanpa jeda yang terlihat.

Adakah yang bisa membuat hipotesis kerangka kerja apa yang bisa mereka gunakan untuk membuat efek ini, dan jika mungkin untuk membuat efek yang sama dengan API publik saat ini?

Edit: (dari komentar) Kami tidak tahu persis bagaimana Apple melakukannya, tetapi adakah asumsi dasar yang dapat kami buat? Kita dapat berasumsi mereka menggunakan perangkat keras, bukan?

Apakah efek mandiri di setiap tampilan, sehingga efeknya tidak benar-benar tahu apa yang ada di baliknya? Atau haruskah, berdasarkan cara kerja blur, konten di balik blur dipertimbangkan?

Jika konten di balik efek tersebut relevan, dapatkah kita berasumsi bahwa Apple menerima "umpan" dari konten di bawah ini dan terus-menerus menjadikannya kabur?

Manusia salju
sumber
(Saya pikir kita dapat berasumsi bahwa apel menggunakan GL murni untuk membuat layar beranda. Saya ragu mereka mengabstraksikannya dengan UIViews dan hal-hal lain yang akan menurunkan kinerja, karena itu merupakan bagian penting dari OS)
Dave
Seperti yang saya tunjukkan dalam komentar untuk jawaban saya di sini: stackoverflow.com/a/17048668/19679 mereka menulis OS, jadi tentu saja mereka akan mempercepat akses ke konten lapisan yang dikomposisikan di bawah tampilan saat ini. Kita dapat melihat beberapa dari apa yang mungkin mereka gunakan di iOSurface API pribadi: stackoverflow.com/questions/14135215/… . Gaussian blur dapat dibuat jauh lebih cepat daripada kasus Gaussian blur umum jika mereka memiliki jari-jari tetap, atau bahkan menggunakan optimasi yang menarik seperti gambar integral.
Brad Larson
@BradLarson - Mengutip Jessica Simpson ... Saya tidak tahu apa artinya tapi kedengarannya keren! Tapi serius, apakah Anda mengatakan bahwa Anda dapat menggunakan tampilan sebagian transparan dengan aa blur filter dan meletakkannya di atas tampilan lain untuk mencapai efek ini?
sangony
stackoverflow.com/a/25706250/2308190 bekerja dengan sempurna untuk saya pertama kali saya mencobanya, dan ringkas
Ben Wheeler

Jawaban:

134

Mengapa repot mereplikasi efeknya? Cukup gambarkan UIToolbar di belakang tampilan Anda.

myView.backgroundColor = [UIColor clearColor];
UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:myView.frame];
bgToolbar.barStyle = UIBarStyleDefault;
[myView.superview insertSubview:bgToolbar belowSubview:myView];
pengguna2342340
sumber
8
Saya tidak setuju dengan crizzwald. Saya tidak berpikir itu interpretasi yang baik dari aturan ekspektasi dari apa yang akan dilakukan oleh APPLE.
Andrew Johnson
117
Saya menjalankan pendekatan ini oleh seorang insinyur Apple UIKit minggu ini di lab Tech Talks mereka. Meskipun dia tentu tidak akan mendukung pendekatan ini, dia mengakui perlunya efek dan kurangnya API publik nyata untuk ini, dan mengatakan bahwa pendekatan ini adalah pilihan "paling tidak jahat" untuk saat ini dan cukup aman seperti yang tertulis. Secara khusus ia mengatakan jangan mencoba untuk melakukan animasi dari frameatau transformdari toolbar ini / view atau sesuatu seperti itu, atau hal-hal buruk akan terjadi. Dia juga sangat menyarankan untuk mengajukan laporan bug Radar tentang ini, untuk membangun sebuah kasus secara internal sehingga kita bisa mendapatkan API publik nyata untuk efek ini!
smileyborg
44
Menarik ... sepertinya akun @ user2342340 dibuat hanya untuk menjawab pertanyaan ini secara anonim. Membuat Anda bertanya-tanya apakah ini bukan pos tidak resmi oleh seseorang yang tahu lebih banyak dari kita tentang hal-hal ini :)
smileyborg
4
Ini tidak berfungsi pada iPhone 4 yang menjalankan iOS 7. Mungkin karena pada iPhone 4, karena daya GPU terlalu rendah, sistem tidak menambahkan efek blur yang biasa ke itu UITabBarsendiri.
Ayush Goel
2
Bagaimana saya membuatnya non-putih? Jika saya mengubah warna latar belakang untuk toolbar, itu tidak menunjukkan blur.
Nikita P
64

Apple merilis kode di WWDC sebagai kategori di UIImage yang mencakup fungsi ini, jika Anda memiliki akun pengembang, Anda dapat mengambil kategori UIImage (dan kode contoh lainnya) dengan masuk ke tautan ini: https://developer.apple. com / wwdc / schedule / dan browsing untuk bagian 226 dan mengklik detail. Saya belum bermain-main dengannya tapi saya pikir efeknya akan jauh lebih lambat di iOS 6, ada beberapa peningkatan untuk iOS 7 yang membuat menyambar screen shot awal yang digunakan sebagai input untuk blur jauh lebih cepat.

Tautan langsung: https://developer.apple.com/downloads/download.action?path=wwdc_2013/wwdc_2013_sample_code/ios_uiimageeffects.zip

FreaknBigPanda
sumber
1
Saya melihat videonya, saya bisa menontonnya, tetapi tidak tahu ke mana harus mengunduh kode sampel!
Nathan H
Saya tidak melihat banyak perbedaan dibandingkan dengan perubahan latar belakang alpha sederhana; mungkin itu karena saya menampilkan video dan mereka hanya perlu lebih banyak blur ...
Ja͢ck
37

Sebenarnya saya berani bertaruh ini akan lebih mudah untuk dicapai. Mungkin tidak akan beroperasi atau terlihat persis seperti apa yang terjadi Apple tetapi bisa sangat dekat.

Pertama-tama, Anda harus menentukan CGRect dari UIView yang akan Anda presentasikan. Setelah Anda menentukan bahwa Anda hanya perlu mengambil gambar dari bagian UI sehingga dapat kabur. Sesuatu seperti ini...

- (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 - Direkomendasikan

Menggunakan UIImage+ImageEffectsKategori Apple yang disediakan di sini , Anda akan mendapatkan gaussian blur yang sangat mirip dengan blur di iOS 7.

Box Blur

Anda juga bisa menggunakan blur kotak menggunakan boxBlurImageWithBlur:kategori UIImage berikut . Ini didasarkan pada algorythem yang dapat Anda temukan di sini .

@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

Sekarang Anda menghitung area layar menjadi buram, meneruskannya ke kategori kabur dan menerima kembali UIImage yang telah buram, sekarang yang tersisa adalah mengatur gambar buram itu sebagai latar belakang tampilan yang akan Anda sajikan. Seperti yang saya katakan, ini tidak akan menjadi pasangan yang sempurna untuk apa yang dilakukan Apple, tetapi tetap terlihat keren.

Semoga ini bisa membantu.

Jeremy Fox
sumber
Tampaknya warna biru gambar kabur dan warna merah tertukar.
Henry
Sepertinya seseorang telah menggunakan kode Anda untuk membuat proyek ini: github.com/alexdrone/ios-realtimeblur/blob/master/RealTimeBlur/… tapi sayangnya tidak ada atribusi, dan mereka telah menambahkan pernyataan hak cipta "Semua Hak Dilindungi" di atas.
Mark Erdmann
@ Mark, terima kasih untuk kepala. Namun, algoritma kabur ini bukan milik saya. Saya sudah menyebutkan dari mana saya mendapatkannya di pos saya di atas. Seperti yang tertulis di posting saya, "Ini didasarkan pada algorythem yang dapat Anda temukan di sini." dengan tautan ke indieambitions.com/idevblogaday/... Saya pasti akan mengirim pesan kepada orang ini dan memberi tahu mereka bahwa mereka kehilangan atribusi. Terima kasih
Jeremy Fox
@MarkErdmann lihat file Anda sendiri di xcode. Ini memiliki "All Rights Reserved". Ini adalah hal umum yang ditambahkan xcode. Juga penulis menambahkan hanya menambahkan lisensi.md yang mengatakan itu lisensi di bawah mit lisensi
Santa Claus
Jangan gunakan renderInContext, gunakan yang baru drawViewHierarchyInRect:atau snapshotView:. WWDC talk 216 "Implementing Engaging UI di iOS7" mengklaim peningkatan kinerja 5-15x.
bcattle
25

iOS8 menjawab pertanyaan-pertanyaan ini.

Efek UIVisual

- (instancetype)initWithEffect:(UIVisualEffect *)effect

atau Swift:

init(effect effect: UIVisualEffect)

Adam Waite
sumber
Saya kira solusi ini sebagian besar tidak berguna sampai iOS 9 keluar. Sebagian besar aplikasi masih mendukung iOS 7, dan solusi ini tidak didukung di sana.
Dmitry Sobolev
benar benar, Anda dapat menggunakan hal semacam ini untuk saat ini: github.com/nicklockwood/FXBlurView
Adam Waite
Saya menerapkan ini dengan toolchain Xcode 6 dengan iOS8, dan bekerja dengan baik. Saya mencoba menerapkan menggunakan CPU, tetapi bekerja terasa lebih lambat daripada metode ini.
Jon
Mengapa kode ketika Xcode menyediakan di storyboard itu sendiri !!!!! Terima kasih @AdamWaite
Mihir Oza
20

Saya baru saja menulis subkelas kecil saya dari UIView yang memiliki kemampuan untuk menghasilkan iOS 7 blur asli pada tampilan kustom apa pun. Ini menggunakan UIToolbar tetapi dengan cara yang aman untuk mengubah bingkai, batas, warna dan alfa dengan animasi real-time.

Tolong beri tahu saya jika Anda melihat ada masalah.

https://github.com/ivoleko/ILTranslucentView

Contoh ILTranslucentView

Ivo Leko
sumber
Saya telah mencoba beberapa pendekatan lain (seperti menambahkan UIToolbar sendiri, atau kategori UIImage + ImageEffects.h Apple); Anda adalah solusi terbaik dan termudah. Terima kasih!
Yunus Nedim Mehel
4
Seberapa baik reaksinya terhadap unduhan iOS 7.0.3 yang baru? Kelas lain yang telah menggunakan teknik ini tidak membuat dengan benar lagi: [
achi
@achi, saya tidak melihat adanya masalah dengan iOS 7.0.3.
Ivo Leko
Apakah Anda tahu jika ada aplikasi yang hidup menggunakan pendekatan Anda dan telah diterima oleh Apple?
Brad Goss
Hai kawan. Ya, aplikasi yang menggunakan kelas ini akan disetujui oleh Apple!
Ivo Leko
10

Ada desas-desus bahwa insinyur Apple mengklaim, untuk membuat pemain ini mereka membaca langsung dari buffer gpu yang menimbulkan masalah keamanan yang mengapa belum ada API publik untuk melakukan ini.

Cody C
sumber
6
Jika ini benar maka itu - sejauh ini - solusi terburuk yang pernah ada.
elslooo
2
aaaaaand blur dihapus dari iOS 7.
Code Guru
3
Itu hanya dihapus pada perangkat yang melihat masalah kinerja.
Cody C
24
Apakah ini posting sumber rumor? :)
Jano
11
Rumor itu mungkin susun. OpenGL ES 2.0 di iOS memungkinkan Anda membaca dan menulis ke pembuat bingkai tanpa risiko keamanan apa pun. Pengaburan dilakukan menggunakan GLSL shaders, itulah sebabnya ia bekerja dengan cepat.
bentford
7

Ini adalah solusi yang dapat Anda lihat di vidios WWDC. Anda harus melakukan Gaussian Blur, jadi hal pertama yang harus Anda lakukan adalah menambahkan file .m dan .h baru dengan kode yang saya tulis di sini, kemudian Anda harus membuat dan menembak layar, menggunakan efek yang diinginkan dan tambahkan ke tampilan Anda, lalu UITable UIView Anda atau apa pun yang harus transparan, Anda dapat bermain dengan applyBlurWithRadius, untuk mengarsipkan efek yang diinginkan, panggilan ini berfungsi dengan UIImage apa pun.

Pada akhirnya gambar yang buram akan menjadi latar belakang dan sisa kontrol di atas harus transparan.

Agar ini berfungsi, Anda harus menambahkan perpustakaan berikutnya:

Acelerate.framework, UIKit.framework, CoreGraphics.framework

Saya harap Anda menyukainya.

Selamat coding.

    //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;
    }
Marco Antonio Uzcategui Pescoz
sumber
7

Anda dapat menemukan solusi dari DEMO apel di halaman ini: WWDC 2013 , cari tahu dan unduh kode sampel UIImageEffects.

Kemudian dengan kode @Jeremy Fox. Saya mengubahnya menjadi

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

Semoga ini bisa membantu Anda.

Senry
sumber
7

Ini adalah cara yang sangat mudah untuk melakukannya: https://github.com/JagCesar/iOS-blur

Cukup salin lapisan UIToolbar dan Anda selesai, AMBlurView melakukannya untuk Anda. Oke, ini tidak buram seperti pusat kontrol, tapi cukup buram.

Ingat bahwa iOS7 berada di bawah NDA.

Simon
sumber
6

Setiap respons di sini menggunakan vImageBoxConvolve_ARGB8888 fungsi ini benar-benar lambat, itu baik, jika kinerjanya bukan persyaratan prioritas tinggi, tetapi jika Anda menggunakan ini untuk transisi antara dua Pengontrol Tampilan (misalnya) pendekatan ini berarti lebih dari 1 kali. kedua atau mungkin lebih, itu sangat buruk bagi pengalaman pengguna aplikasi Anda.

Jika Anda lebih suka menyerahkan semua pemrosesan gambar ini ke GPU (Dan Anda seharusnya), Anda bisa mendapatkan efek yang jauh lebih baik dan juga waktu yang luar biasa membulatkan 50ms (seandainya Anda memiliki waktu 1 detik dalam pendekatan pertama), jadi, mari kita lakukan .

Pertama-tama unduh GPUImage Framework (BSD Licensed) di sini .

Selanjutnya, Tambahkan kelas berikut (.m dan .h) dari GPUImage (Saya tidak yakin bahwa ini adalah minimum yang diperlukan untuk efek blur saja)

  • GPUImage.h
  • GPUImageAlphaBlendFilter
  • GPUImageFilter
  • GPUImageFilterGroup
  • GPUImageGaussianBlurPositionFilter
  • GPUImageGaussianSelectiveBlurFilter
  • GPUImageLuminanceRangeFilter
  • GPUImageOutput
  • GPUImageTwoInputFilter
  • Program GL
  • GPUImageBoxBlurFilter
  • GPUImageGaussianBlurFilter
  • GPUImageiOSBlurFilter
  • Filter Gambaraturatur GPU
  • GPUImageSolidColorGenerator
  • GPUImageTwoPassFilter
  • GPUImageTwoPassTextureSamplingFilter

  • iOS / GPUImage-Prefix.pch

  • iOS / GPUImageContext
  • iOS / GPUImageMovieWriter
  • Gambar iOS / GPUImage
  • iOS / GPUImageView

Selanjutnya, buat kategori di UIImage, yang akan menambahkan efek blur ke UIImage yang ada:

#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

Dan terakhir, tambahkan kerangka kerja berikut untuk proyek Anda:

AVFoundation CoreMedia CoreVideo OpenGLES

Ya, bersenang-senang dengan pendekatan yang jauh lebih cepat ini;)

D33pN16h7
sumber
4

Anda dapat mencoba menggunakan tampilan kustom saya, yang memiliki kemampuan untuk mengaburkan latar belakang. Ia melakukan ini dengan memalsukan mengambil potret latar belakang dan mengaburkannya, seperti yang ada dalam kode WWDC Apple. Sangat mudah digunakan.

Saya juga membuat beberapa perbaikan untuk memalsukan kekaburan dinamis tanpa kehilangan kinerja. Latar belakang tampilan saya adalah scrollView yang menggulir dengan tampilan, sehingga memberikan efek blur untuk sisa superview.

Lihat contoh dan kode di GitHub saya

Byte
sumber