【问题标题】:CIFilter is not working correctly when app is in background应用程序在后台时 CIFilter 无法正常工作
【发布时间】:2013-08-21 08:39:56
【问题描述】:

我们正在对少数图像应用“CIGaussianBlur”滤镜。该过程大部分时间都运行良好。但是当应用程序移动到后台时,该过程会在图像上产生白色条纹。 (下图,请注意图像的左侧和底部是白色条纹,与原始图像相比,图像有点尖叫)。

代码:

 - (UIImage*)imageWithBlurRadius:(CGFloat)radius
{
    UIImage *image = self;
    LOG(@"(1) image size before resize = %@",NSStringFromCGSize(image.size));
    NSData *imageData = UIImageJPEGRepresentation(self, 1.0);
    LOG(@"(2) image data length = %ul",imageData.length);

    //create our blurred image
    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *inputImage = [CIImage imageWithCGImage:image.CGImage];

    //setting up Gaussian Blur (we could use one of many filters offered by Core Image)
    CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [filter setValue:inputImage forKey:kCIInputImageKey];
    [filter setValue:[NSNumber numberWithFloat:radius] forKey:@"inputRadius"];
    CIImage *result = [filter valueForKey:kCIOutputImageKey];
    //CIGaussianBlur has a tendency to shrink the image a little, this ensures it matches up exactly to the bounds of our original image
    CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];
    UIImage *finalImage = [UIImage imageWithCGImage:cgImage];

    CGImageRelease(cgImage);
   LOG(@"(3) final image size after resize = %@",NSStringFromCGSize(finalImage.size));
    return finalImage;
}

过滤前 )

过滤后

【问题讨论】:

    标签: ios blur cifilter


    【解决方案1】:

    实际上,我刚刚遇到了这个确切的问题,并找到了与@RizwanSattar 描述的不同的解决方案。

    根据在 Apple 开发人员板上与“Rincewind”的交流,我所做的是首先在图像上应用 CIAffineClamp,并将变换值设置为标识。这将创建相同比例的图像,但范围无限。这会导致模糊正确地模糊边缘。

    然后在应用模糊之后,我将图像裁剪到原始范围,裁剪掉边缘发生的羽化。

    您可以在我发布在 github 上的 CI 过滤器演示应用中查看代码:

    CIFilter demo project on github

    这是一个处理所有不同 CI 过滤器的通用程序,但它有处理高斯模糊过滤器的代码。

    看一下方法showImage。在应用模糊滤镜之前,它有特殊情况代码来设置源图像的范围:

    if ([currentFilterName isEqualToString: @"CIGaussianBlur"])
    {
      // NSLog(@"new image is bigger");
      CIFilter *clampFilter = [self clampFilter];
    
      CIImage *sourceCIImage = [CIImage imageWithCGImage: imageToEdit.CGImage];
      [clampFilter setValue: sourceCIImage
                     forKey: kCIInputImageKey];
    
    
      [clampFilter setValue:[NSValue valueWithBytes: &CGAffineTransformIdentity
                                           objCType:@encode(CGAffineTransform)]
                     forKey:@"inputTransform"];
    
    
    
      sourceCIImage = [clampFilter valueForKey: kCIOutputImageKey];
      [currentFilter setValue: sourceCIImage
                       forKey: kCIInputImageKey];
    }
    

    (“clampFilter”方法只是延迟加载CIAffineClamp 过滤器。)

    然后我应用用户选择的过滤器:

    outputImage = [currentFilter valueForKey: kCIOutputImageKey];
    

    然后在应用选定的过滤器后,我会检查结果图像的范围,如果它更大,则将其裁剪回原始范围:

    CGSize newSize;
    
    newSize = outputImage.extent.size;
    
    if (newSize.width > sourceImageExtent.width || newSize.height > sourceImageExtent.height)
    {
      // NSLog(@"new image is bigger");
      CIFilter *cropFilter = [self cropFilter];  //Lazily load a CIAffineClamp filter
    
      CGRect boundsRect = CGRectMake(0, 0, sourceImageExtent.width, sourceImageExtent.height);
    
      [cropFilter setValue:outputImage forKey: @"inputImage"];
    
      CIVector *rectVector = [CIVector vectorWithCGRect: boundsRect];
    
      [cropFilter setValue: rectVector
                    forKey: @"inputRectangle"];
      outputImage = [cropFilter valueForKey: kCIOutputImageKey];
    }
    

    【讨论】:

    • 嘿邓肯!会喜欢这个的快速版本:)
    【解决方案2】:

    您在模糊图像中看到那些“白色条纹”的原因是生成的 CIImage 比原始图像更大,因为它具有模糊的模糊边缘。当您将生成的图像硬裁剪为与原始图像相同的大小时,它并没有考虑到模糊边缘。

    之后:

    CIImage *result = [filter valueForKey:kCIOutputImageKey];

    看看result.extent,它是一个CGRect,它显示了相对于原始图像的新边界框。 (即对于正半径,result.extent.origin.y 将是负数)

    这里有一些代码(你真的应该测试一下):

    CIImage *result = blurFilter.outputImage;
    
    // Blur filter will create a larger image to cover the "fuzz", but
    // we should cut it out since goes to transparent and it looks like a
    // vignette
    CGFloat imageSizeDifference = -result.extent.origin.x;
    // NOTE: on iOS7 it seems to generate an image that will end up still vignetting, so
    // as a hack just multiply the vertical inset by 2x
    CGRect imageInset = CGRectInset(result.extent, imageSizeDifference, imageSizeDifference*2);
    
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:result fromRect:imageInset];
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      • 2019-03-22
      • 2021-04-09
      • 1970-01-01
      • 2017-02-03
      • 1970-01-01
      相关资源
      最近更新 更多