高斯模糊滤镜反转:iOS

Posted

技术标签:

【中文标题】高斯模糊滤镜反转:iOS【英文标题】:Gaussian Blur Filter Reversal: iOS 【发布时间】:2013-01-25 05:41:59 【问题描述】:

我正在为一个应用程序做一个高斯模糊。

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

效果很好,但我希望能够反转它并使视图恢复正常。

我该如何做到这一点,因为试图简单地从它的超级视图中删除模糊视图是行不通的。我也尝试过将各种属性设置为零,但没有运气。

【问题讨论】:

你不能在应用模糊之前复制 viewImage 并在你想反转时恢复吗? 如何在应用模糊后不更改两个副本的情况下制作副本? 试试这个***.com/a/50140306/4124168 【参考方案1】:

在属性中保留指向 viewImage 的指针

@property (nonatomic, strong) UIImage* originalImage;

之后

UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();

添加

self.originalImage = viewImage;

要还原您的图像:

newView.image = self.originalImage;

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

【讨论】:

这让我意识到我所做的总体上是不正确的。我正在尝试使 self.view 模糊,因为我将一些对象暂时放在它的顶部。我不想要原始图像,而是回到我最初所在的视图。你的答案是正确的,但你认为你可以编辑你的答案来反映这一点吗?我希望我能给你两个复选标记:P 我最终只是创建了一个带有模糊的 UIView,然后以这种方式摆脱它。谢谢!【参考方案2】: 我在您的代码中看到的第一件事是您没有在异步任务中应用过滤器。模糊图像需要时间,所以如果你不想冻结你应该使用的主线程:
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 来设置模糊图像,并在我想反转时设置为 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];
                     ];

【讨论】:

【参考方案3】:

就像我在之前的评论中所说,您可以创建一个属性/iVar,在应用效果之前保存图像并在您想要撤消时恢复。

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 答案的评论,您不应该完全模糊视图。如果视图变得模糊,则说明您在程序的其他地方做错了其他事情。

【讨论】:

以上是关于高斯模糊滤镜反转:iOS的主要内容,如果未能解决你的问题,请参考以下文章

GPUImage 动画高斯模糊滤镜

仅在 xCode 中的触摸区域应用高斯模糊滤镜

详析数字图像中高斯模糊理论及实现

高斯模糊

❤️Android 12 高斯模糊-RenderEffect❤️

❤️Android 12 高斯模糊-RenderEffect❤️