Wie kann ich einen ähnlichen Effekt wie die Unschärfeansicht für iOS 7 erzielen?

219

Ich versuche, diesen unscharfen Hintergrund von Apples öffentlich veröffentlichtem iOS 7-Beispielbildschirm zu replizieren:

Screenshot des iOS 7 Control Centers

Diese Frage schlägt vor, einen CI-Filter auf die folgenden Inhalte anzuwenden, aber das ist ein ganz anderer Ansatz. Es ist offensichtlich, dass iOS 7 aus vielen Gründen den Inhalt der folgenden Ansichten nicht erfasst:

  1. Das Durchführen einiger grober Tests, das Aufnehmen eines Screenshots der folgenden Ansichten und das Anwenden eines CIGaussianBlur-Filters mit einem Radius, der groß genug ist, um den Unschärfestil von iOS 7 nachzuahmen, dauert selbst auf einem Simulator 1-2 Sekunden.
  2. Die Unschärfeansicht für iOS 7 kann dynamische Ansichten wie Videos oder Animationen ohne merkliche Verzögerung verwischen.

Kann jemand eine Hypothese aufstellen, mit welchen Frameworks er diesen Effekt erzeugen könnte und ob es möglich ist, mit aktuellen öffentlichen APIs einen ähnlichen Effekt zu erzielen?

Bearbeiten: (aus dem Kommentar) Wir wissen nicht genau, wie Apple es macht, aber gibt es grundlegende Annahmen, die wir treffen können? Wir können davon ausgehen, dass sie Hardware verwenden, oder?

Ist der Effekt in jeder Ansicht in sich geschlossen, sodass der Effekt nicht genau weiß, was dahinter steckt? Oder muss, basierend auf der Funktionsweise von Unschärfen, der Inhalt hinter der Unschärfe berücksichtigt werden?

Wenn die Inhalte hinter dem Effekt relevant sind, können wir davon ausgehen, dass Apple einen "Feed" der folgenden Inhalte empfängt und diese kontinuierlich verwischt?

Schneemann
quelle
(Ich denke, wir können davon ausgehen, dass Apple ohnehin reinen GL zum Rendern der Startbildschirme verwendet. Ich bezweifle, dass sie diese mit UIViews und anderen Dingen abstrahieren, die die Leistung beeinträchtigen würden, da dies ein so wichtiger Bestandteil des Betriebssystems ist.)
Dave
Wie ich in den Kommentaren zu meiner Antwort hier angegeben habe: stackoverflow.com/a/17048668/19679 haben sie das Betriebssystem geschrieben, daher haben sie natürlich einen beschleunigten Zugriff auf den Inhalt von Ebenen, die unter der aktuellen Ansicht zusammengefasst sind. In der privaten IOSurface-API können Sie sehen, was sie möglicherweise verwenden: stackoverflow.com/questions/14135215/… . Gaußsche Unschärfen können viel schneller als die verallgemeinerten Gaußschen Unschärfefälle gemacht werden, wenn sie einen festen Radius haben, oder sogar interessante Optimierungen wie integrale Bilder verwenden.
Brad Larson
@BradLarson - Um Jessica Simpson zu paraphrasieren ... Ich habe keine Ahnung, was das alles bedeutet, aber es klingt verdammt cool! Aber im Ernst, sagen Sie, dass Sie eine teilweise transparente Ansicht mit einem Unschärfefilter verwenden und über eine andere Ansicht legen können, um diesen Effekt zu erzielen?
Sangony
stackoverflow.com/a/25706250/2308190 funktionierte perfekt für mich, als ich es das erste Mal versuchte, und war prägnant
Ben Wheeler

Antworten:

134

Warum sollte man sich die Mühe machen, den Effekt zu wiederholen? Zeichnen Sie einfach eine UIToolbar hinter Ihre Ansicht.

myView.backgroundColor = [UIColor clearColor];
UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:myView.frame];
bgToolbar.barStyle = UIBarStyleDefault;
[myView.superview insertSubview:bgToolbar belowSubview:myView];
user2342340
quelle
8
Ich bin nicht einverstanden mit Crizzwald. Ich denke nicht, dass dies eine gute Interpretation der Erwartungsregeln für das ist, was APple tun wird.
Andrew Johnson
117
Ich habe diesen Ansatz diese Woche von einem Apple UIKit-Ingenieur in seinem Tech Talks-Labor durchgeführt. Obwohl er diesen Ansatz sicherlich nicht befürworten würde, erkannte er die Notwendigkeit des Effekts und das Fehlen einer echten öffentlichen API dafür und sagte, dass dieser Ansatz derzeit die "am wenigsten böse" Option sei und wie geschrieben ziemlich sicher sei. Insbesondere sagte er, versuche nicht, Animationen der frameoder transformdieser Symbolleiste / Ansicht oder ähnliches zu machen, sonst würden schlimme Dinge passieren. Er schlug außerdem dringend vor, Radar-Fehlerberichte zu diesem Thema einzureichen, um intern einen Fall zu erstellen, damit wir eine echte öffentliche API für diesen Effekt erhalten können!
Smileyborg
44
Interessant ... es sieht so aus, als ob das Konto @ user2342340 erstellt wurde, um diese Frage anonym zu beantworten. Sie wundern sich, ob dies kein inoffizieller Beitrag von jemandem ist, der mehr als der Rest von uns über diese Dinge weiß :)
Smileyborg
4
Dies funktioniert nicht auf dem iPhone 4 mit iOS 7. Dies liegt wahrscheinlich daran, dass das System auf dem iPhone 4, da die GPU-Leistung zu niedrig ist, nicht den üblichen Unschärfeeffekt hinzufügt UITabBar.
Ayush Goel
2
Wie mache ich es nicht weiß? Wenn ich die Hintergrundfarbe für die Symbolleiste ändere, wird die Unschärfe nicht angezeigt.
Nikita P
64

Apple hat auf der WWDC Code als Kategorie auf UIImage veröffentlicht, der diese Funktionalität enthält. Wenn Sie über ein Entwicklerkonto verfügen, können Sie die UIImage-Kategorie (und den Rest des Beispielcodes) über diesen Link abrufen: https://developer.apple. com / wwdc / Schedule / und suchen Sie nach Abschnitt 226 und klicken Sie auf Details. Ich habe noch nicht damit herumgespielt, aber ich denke, dass der Effekt unter iOS 6 viel langsamer sein wird. Es gibt einige Verbesserungen an iOS 7, die das Abrufen des ersten Screenshots, der als Eingabe für die Unschärfe verwendet wird, viel schneller machen.

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

FreaknBigPanda
quelle
1
Ich sehe das Video, kann es ansehen, kann aber nicht herausfinden, wo ich den Beispielcode herunterladen kann!
Nathan H
Ich habe keinen großen Unterschied zu einer einfachen Alpha-Änderung im Hintergrund gesehen. Vielleicht liegt es daran, dass ich Videos
anzeige
37

Eigentlich würde ich wetten, dass dies ziemlich einfach zu erreichen wäre. Es würde wahrscheinlich nicht genau so funktionieren oder aussehen wie Apple, könnte aber sehr nahe sein.

Zunächst müssen Sie den CGRect der UIView bestimmen, die Sie präsentieren möchten. Sobald Sie festgestellt haben, dass Sie nur ein Bild des Teils der Benutzeroberfläche aufnehmen müssen, damit es unscharf wird. Etwas wie das...

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

Gaußsche Unschärfe - Empfohlen

Wenn Sie die hierUIImage+ImageEffects bereitgestellte Kategorie Apple verwenden , erhalten Sie eine Gaußsche Unschärfe, die der Unschärfe in iOS 7 sehr ähnlich sieht.

Box Unschärfe

Sie können auch eine Box-Unschärfe mit der folgenden boxBlurImageWithBlur:UIImage-Kategorie verwenden. Dies basiert auf einem Algorithmus, den Sie hier finden können .

@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

Nachdem Sie den zu verwischenden Bildschirmbereich berechnet, ihn in die Kategorie "Unschärfe" übergeben und ein unscharfes UII-Bild zurückerhalten, müssen Sie nur noch das unscharfe Bild als Hintergrund für die Ansicht festlegen, die Sie präsentieren möchten. Wie ich bereits sagte, wird dies nicht perfekt zu dem passen, was Apple tut, aber es sollte trotzdem ziemlich cool aussehen.

Ich hoffe es hilft.

Jeremy Fox
quelle
Es scheint, dass die blaue und die rote Farbe des unscharfen Bildes vertauscht sind.
Henry
Es sieht so aus, als hätte jemand Ihren Code zum Erstellen dieses Projekts verwendet: github.com/alexdrone/ios-realtimeblur/blob/master/RealTimeBlur/…, aber leider gibt es keine Zuordnung, und er hat eine Copyright-Erklärung "Alle Rechte vorbehalten" hinzugefügt oben.
Mark Erdmann
@ Mark, danke für die Heads-Ups. Dieser Unschärfealgorithmus ist jedoch nicht mein eigener. Ich habe bereits in meinem Beitrag oben erwähnt, woher ich es habe. Wie es in meinem Beitrag heißt "Dies basiert auf einem Algorithmus, den Sie hier finden können." mit einem Link zu indieambitions.com/idevblogaday/… Ich werde dieser Person definitiv eine Nachricht senden und sie wissen lassen, dass ihnen die Zuschreibung fehlt. Vielen Dank
Jeremy Fox
@MarkErdmann werfen Sie einen Blick auf Ihre eigenen Dateien in xcode. Es hat "Alle Rechte vorbehalten". Es ist eine generische Sache, die xcode hinzufügt. Auch der Autor fügte hinzu, gerade eine Lizenz hinzugefügt.md, die sagt, dass es unter der Mit lisence
Santa Claus
Verwenden Sie nicht renderInContext, verwenden Sie das neue drawViewHierarchyInRect:oder snapshotView:. WWDC-Vortrag 216 "Implementieren der Benutzeroberfläche auf iOS7" behauptet eine 5-15-fache Leistungsverbesserung.
Vieh
25

iOS8 hat diese Fragen beantwortet.

UIVisualEffect

- (instancetype)initWithEffect:(UIVisualEffect *)effect

oder Swift:

init(effect effect: UIVisualEffect)

Adam Waite
quelle
Ich denke, diese Lösung ist meistens nutzlos, bis iOS 9 herauskommt. Die meisten Anwendungen unterstützen weiterhin iOS 7, und diese Lösung wird dort nicht unterstützt.
Dmitry Sobolev
wahr wahr, Sie können diese Art von Dingen
Adam Waite
Ich habe dies mit der Xcode 6-Toolchain unter iOS8 implementiert und es funktioniert hervorragend. Ich habe versucht, mit der CPU zu implementieren, arbeitet aber deutlich langsamer als diese Methode.
Jon
Warum codieren, wenn Xcode im Storyboard selbst bereitstellt !!!!! Danke @AdamWaite
Mihir Oza
20

Ich habe gerade meine kleine Unterklasse von UIView geschrieben, die in jeder benutzerdefinierten Ansicht native iOS 7-Unschärfe erzeugen kann. Es verwendet die UIToolbar, aber auf sichere Weise, um Rahmen, Grenzen, Farbe und Alpha mit Echtzeitanimation zu ändern.

Bitte lassen Sie mich wissen, wenn Sie Probleme bemerken.

https://github.com/ivoleko/ILTranslucentView

ILTranslucentView-Beispiele

Ivo Leko
quelle
Ich habe einige andere Ansätze ausprobiert (z. B. das Hinzufügen einer UIToolbar selbst oder die Kategorie UIImage + ImageEffects.h von Apple). Ihr war die beste und einfachste Lösung. Vielen Dank!
Yunus Nedim Mehel
4
Wie gut reagiert es auf den neuen Download von iOS 7.0.3? Andere Klassen, die diese Technik verwendet haben, rendern nicht mehr richtig: [
Achi
@achi, ich habe kein Problem mit iOS 7.0.3 bemerkt.
Ivo Leko
Wissen Sie, ob Apps, die mit Ihrem Ansatz animiert wurden und von Apple akzeptiert wurden?
Brad Goss
Hallo Leute. Ja, Apps, die diese Klasse verwenden, werden von Apple genehmigt!
Ivo Leko
10

Es gibt ein Gerücht, dass Apple-Ingenieure behaupteten, sie würden direkt aus dem GPU-Puffer lesen, um diese Leistung zu erbringen, was Sicherheitsprobleme aufwirft, weshalb es noch keine öffentliche API gibt, um dies zu tun.

Cody C.
quelle
6
Wenn dies zutrifft, ist dies bei weitem die schlechteste Lösung aller Zeiten.
Elslooo
2
aaaaaund die Unschärfe wird von iOS 7 entfernt.
Code Guru
3
Es wurde nur auf Geräten entfernt, bei denen Leistungsprobleme auftraten.
Cody C
24
Ist dieser Beitrag die Quelle des Gerüchts? :)
Jano
11
Dieses Gerücht ist wahrscheinlich eine Koje. Mit OpenGL ES 2.0 unter iOS können Sie ohne Sicherheitsrisiko in Framebuffer lesen und schreiben. Die Unschärfe erfolgt mit GLSL-Shadern, weshalb sie schnell ausgeführt wird.
Bentford
7

Dies ist eine Lösung, die Sie in den Videos des WWDC sehen können. Sie müssen eine Gaußsche Unschärfe ausführen. Als Erstes müssen Sie eine neue .m- und .h-Datei mit dem Code hinzufügen, den ich hier schreibe. Anschließend müssen Sie einen Screenshot erstellen, den gewünschten Effekt verwenden und Fügen Sie es Ihrer Ansicht hinzu, dann Ihre UITable UIView oder was auch immer transparent sein muss, Sie können mit applyBlurWithRadius spielen, um den gewünschten Effekt zu archivieren. Dieser Aufruf funktioniert mit jedem UIImage.

Am Ende ist das unscharfe Bild der Hintergrund und die restlichen Steuerelemente oben müssen transparent sein.

Damit dies funktioniert, müssen Sie die nächsten Bibliotheken hinzufügen:

Acelerate.framework, UIKit.framework, CoreGraphics.framework

Ich hoffe du magst es.

Viel Spaß beim Codieren.

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

Sie finden Ihre Lösung von Apple DEMO auf dieser Seite: WWDC 2013 Apples , finden Sie den UIImageEffects-Beispielcode heraus und laden Sie ihn herunter.

Dann mit dem Code von @Jeremy Fox. Ich habe es geändert in

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

Hoffe das wird dir helfen.

Senry
quelle
7

Hier ist eine wirklich einfache Möglichkeit: https://github.com/JagCesar/iOS-blur

Kopieren Sie einfach die Ebene der UIToolbar und fertig, AMBlurView erledigt das für Sie. Okay, es ist nicht so verschwommen wie das Kontrollzentrum, aber es ist verschwommen genug.

Denken Sie daran, dass iOS7 unter NDA steht.

Simon
quelle
6

Jede Antwort hier verwendet vImageBoxConvolve_ARGB8888 Diese Funktion ist sehr, sehr langsam. Das ist in Ordnung, wenn die Leistung keine hohe Priorität hat. Wenn Sie diese Funktion jedoch für den Übergang zwischen zwei View Controllern verwenden (z. B.), bedeutet dieser Ansatz Zeiten über 1 Zweitens oder vielleicht mehr, das ist sehr schlecht für die Benutzererfahrung Ihrer Anwendung.

Wenn Sie es vorziehen, die gesamte Bildverarbeitung der GPU zu überlassen (und Sie sollten es tun), können Sie einen viel besseren Effekt erzielen und auch fantastische Zeiten um 50 ms erzielen (vorausgesetzt, Sie haben beim ersten Ansatz eine Zeit von 1 Sekunde) .

Laden Sie zuerst das GPUImage Framework (BSD Licensed) hier herunter .

Fügen Sie als Nächstes die folgenden Klassen (.m und .h) aus dem GPUImage hinzu (ich bin nicht sicher, ob dies das Minimum ist, das nur für den Unschärfeeffekt benötigt wird).

  • GPUImage.h
  • GPUImageAlphaBlendFilter
  • GPUImageFilter
  • GPUImageFilterGroup
  • GPUImageGaussianBlurPositionFilter
  • GPUImageGaussianSelectiveBlurFilter
  • GPUImageLuminanceRangeFilter
  • GPUImageOutput
  • GPUImageTwoInputFilter
  • GLProgramm
  • GPUImageBoxBlurFilter
  • GPUImageGaussianBlurFilter
  • GPUImageiOSBlurFilter
  • GPUImageSaturationFilter
  • GPUImageSolidColorGenerator
  • GPUImageTwoPassFilter
  • GPUImageTwoPassTextureSamplingFilter

  • iOS / GPUImage-Prefix.pch

  • iOS / GPUImageContext
  • iOS / GPUImageMovieWriter
  • iOS / GPUImagePicture
  • iOS / GPUImageView

Erstellen Sie als Nächstes eine Kategorie in UIImage, die einem vorhandenen UIImage einen Unschärfeeffekt hinzufügt:

#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

Fügen Sie Ihrem Projekt zuletzt die folgenden Frameworks hinzu:

AVFoundation CoreMedia CoreVideo OpenGLES

Ja, ich habe Spaß mit diesem viel schnelleren Ansatz gehabt;)

D33pN16h7
quelle
4

Sie können versuchen, meine benutzerdefinierte Ansicht zu verwenden, mit der der Hintergrund verwischt werden kann. Dazu wird ein Schnappschuss des Hintergrunds vorgetäuscht und verwischt, genau wie im WWDC-Code von Apple. Es ist sehr einfach zu bedienen.

Ich habe auch einige Verbesserungen vorgenommen, um die dynamische Unschärfe vorzutäuschen, ohne die Leistung zu verlieren. Der Hintergrund meiner Ansicht ist eine scrollView, die mit der Ansicht scrollt und somit den Unschärfeeffekt für den Rest der Übersicht liefert.

Siehe das Beispiel und den Code auf meinem GitHub

Byte
quelle