高斯模糊滤镜的反转:iOS

5

我正在为一个应用程序实现高斯模糊效果。

    //Get a UIImage from the UIView
    UIGraphicsBeginImageContext(self.view.bounds.size);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    //Blur the UIImage
    CIImage *imageToBlur = [CIImage imageWithCGImage:viewImage.CGImage];
    CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [gaussianBlurFilter setValue:imageToBlur forKey:@"inputImage"];
    [gaussianBlurFilter setValue:[NSNumber numberWithFloat:2] forKey:@"inputRadius"];
    CIImage *resultImage = [gaussianBlurFilter valueForKey:@"outputImage"];
    UIImage *endImage = [[UIImage alloc] initWithCIImage:resultImage];

    //Place the UIImage in a UIImageView
    newView = [[UIImageView alloc] initWithFrame:self.view.bounds];
    newView.image = endImage;
    [self.view addSubview:newView];

它的效果非常好,但我希望能够将其反转并将视图返回到正常状态。

我该如何做到这一点?尝试仅仅从其父视图中删除模糊视图并没有起作用。我也尝试了将各种属性设置为nil,但没有成功。


你不能在应用模糊之前复制viewImage并在需要恢复时还原吗? - Ravi
如何在应用模糊效果后,制作一份副本而不会随后更改两个副本? - jakenberg
尝试这个 https://stackoverflow.com/a/50140306/4124168 - Leojin Bose
3个回答

3
将viewImage的指针保存在属性中。
@property (nonatomic, strong) UIImage* originalImage;

那么在之后。
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();

添加

self.originalImage = viewImage;

要恢复图像:

newView.image = self.originalImage;

当您应用模糊时,它不会改变viewImage。您已经创建了一个单独的CIImage,该CIImage被模糊,然后您从模糊的CIImage创建了一个新的UIImage。

这让我意识到我的整体做法是错误的。我试图使self.view模糊,因为我暂时将一些对象放在其上方。我不想要原始图像,而是要回到最初的视图。你的答案是正确的,但你能否编辑一下以反映这一点呢?我希望我能为此给你两个勾勾 :P - jakenberg
我最终只是创建了一个带模糊效果的UIView,然后通过这种方式将其去除。谢谢! - jakenberg

1
  • 我在你的代码中看到的第一件事是,你没有在异步任务中应用过滤器。模糊图像需要时间,所以如果你不想冻结主线程,你应该使用:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //blur the image in a second thread
    dispatch_async(dispatch_get_main_queue(), ^{
        //set the blurred image to your imageView in the main thread
    });
});

  • 要想翻转原始图像,只需将模糊的副本放置在另一个imageView中,该imageView会出现在原始图像上方。在我的情况下,原始图像不是imageView,而是视图本身。因此,我只需在我的视图中添加一个imageView来设置模糊图像,并在需要翻转时将其设置为nil。

  • 最后,如果你想避免在设置模糊图像时出现闪烁,你可以在动画中调整alpha值以实现柔和的过渡:

[self.blurredImageView setAlpha: 0.0]; //make the imageView invisible
[self.blurredImageView setImage:blurredImage];
//and after set the image, make it visible slowly.
[UIView animateWithDuration:0.5 delay:0.1
                            options:UIViewAnimationOptionCurveEaseInOut
                         animations:^{
                             [self.blurredImageView setAlpha: 1.0]; 
                         }
                         completion:nil];

以下是我的完整方法:

- (void)makeBlurredScreenShot{
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *imageView = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CIContext *context   = [CIContext contextWithOptions:nil];
    CIImage *sourceImage = [CIImage imageWithCGImage:imageView.CGImage];

    // Apply clamp filter:
    // this is needed because the CIGaussianBlur when applied makes
    // a trasparent border around the image
    NSString *clampFilterName = @"CIAffineClamp";
    CIFilter *clamp = [CIFilter filterWithName:clampFilterName];
    if (!clamp)
        return;

    [clamp setValue:sourceImage forKey:kCIInputImageKey];
    CIImage *clampResult = [clamp valueForKey:kCIOutputImageKey];

    // Apply Gaussian Blur filter
    NSString *gaussianBlurFilterName = @"CIGaussianBlur";
    CIFilter *gaussianBlur           = [CIFilter filterWithName:gaussianBlurFilterName];
    if (!gaussianBlur)
        return;

    [gaussianBlur setValue:clampResult forKey:kCIInputImageKey];
    [gaussianBlur setValue:[NSNumber numberWithFloat:8.0] forKey:@"inputRadius"];

    CIImage *gaussianBlurResult = [gaussianBlur valueForKey:kCIOutputImageKey];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        CGImageRef cgImage = [context createCGImage:gaussianBlurResult fromRect:[sourceImage extent]];

        UIImage *blurredImage = [UIImage imageWithCGImage:cgImage];
        CGImageRelease(cgImage);

        dispatch_async(dispatch_get_main_queue(), ^{
            [self.blurredImageView setAlpha: 0.0];
            [self.blurredImageView setImage:blurredImage];
            [UIView animateWithDuration:0.5 delay:0.1
                                options:UIViewAnimationOptionCurveEaseInOut
                             animations:^{
                                 [self.blurredImageView setAlpha: 1.0]; 
                             }
                             completion:nil];
        });
    });
}

- (void)removeBlurredScreenShot{
    [UIView animateWithDuration:0.5 delay:0.1
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                          [self.blurredImageView setAlpha: 0.0];
                             }
                     completion:^(BOOL finished) {
                          [self.blurredImageView setImage:nil];
                     }];
}

0
就像我在之前的评论中说的那样,你可以创建一个属性/变量来保存在应用效果之前的图像,并在需要撤销时恢复原样。
if(!_originalImage)
    _originalImage = [[UIImage alloc] init];

_originalImage = viewImage; //(Creates a copy, not a C-Type pass-by-reference)

// Do your Blur Stuff

// Now somewhere down the line in your program, if you don't like the blur and the user would like to undo:

viewImage = _originalImage;

根据您在@HeWas答案中的评论,您不应完全模糊视图。如果视图变得模糊,那么您在程序的其他地方可能做错了什么。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接