将滤镜应用于 CIImage [Core Image] 时获取 EXC_BAD_ACCESS

Getting EXC_BAD_ACCESS while Applying filter to CIImage [Core Image]

我正在处理 Imagebase 应用程序。我想在图像上应用一些过滤器。为此,我使用了 [Core Image]。

我在数组中存储了一些 FilterName 并显示过滤器效果作为预览我正在使用 UICollection 视图。当用户点击预览图像时,过滤器将应用于主图像视图。但是当我点击 preview cell 时,过滤器在 Main Imageview 上成功应用。但在那之后,当我拖动集合视图单元格以应用下一个预览时,我得到 BAD_ACCESS 过滤方法错误。

-(UIImage *) applyFilter: (UIImage*) picture withFilterName:(NSString*)Filtername

这是我应用过滤器的代码:-


过滤器数组和 RegisterCollectionview 单元格的初始设置:-

-(void)setUpDefaultUI{
    [self HideControlsAndSetupUI];

    arrFilter = @[ @"Original",
                   @"CILinearToSRGBToneCurve",
                   @"CIPhotoEffectChrome",
                   @"CIPhotoEffectFade",
                   @"CIPhotoEffectInstant",
                   @"CIPhotoEffectMono",
                   @"CIPhotoEffectNoir",
                   @"CIPhotoEffectProcess",
                   @"CIPhotoEffectTonal",
                   @"CIPhotoEffectTransfer",
                   @"CISRGBToneCurveToLinear",
                   @"CIVignette",
                   // @"CIVignetteEffect",
                   @"CISepiaTone",
                   ];

    [self.vwCollection registerClass:[ActivityCollectionViewCell class] forCellWithReuseIdentifier:@"ActivityCollectionViewCell"];
    [self.vwCollection registerNib:[UINib nibWithNibName:@"ActivityCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"ActivityCollectionViewCell"];
    _imgEdit.image=_stillImage; // To apply filter on this Image 
    _OriginalImage=_stillImage; // Original image if user declined to use filter

}


CollectionView 数据源:-

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {


    NSLog(@"filterAvailable");

    ActivityCollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"ActivityCollectionViewCell" forIndexPath:indexPath];

    if (cell == nil) {
        NSArray *xib = [[NSBundle mainBundle] loadNibNamed:@"ActivityCollectionViewCell" owner:self options:nil];
        cell = [xib objectAtIndex:0];
        [cell.imgVw setContentMode:UIViewContentModeScaleAspectFill];
    }
      if (indexPath.item==0) {
        cell.imgVw.image = _OriginalImage; //Original Image on 0 index
    }else{
         UIImage *img=[self applyFilter:_stillImage withFilterName:[arrFilter objectAtIndex:indexPath.row]]; // Apply filter on this method
        cell.imgVw.image=img;
}
    return cell;
}

Collectionview 委托:-

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    ActivityCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ActivityCollectionViewCell" forIndexPath:indexPath];
    if (cell == nil) {
        NSArray *xib = [[NSBundle mainBundle] loadNibNamed:@"ActivityCollectionViewCell" owner:self options:nil];
        cell = [xib objectAtIndex:0];
    }
 if (indexPath.item==0) {
        _imgEdit.image=_OriginalImage; // Set original image in main Imageview
    }else{
        UIImage *img=[self applyFilter:_stillImage withFilterName:[arrFilter objectAtIndex:indexPath.row]];
        _imgEdit.image = img;  // Apply filter on Main Imageview 
    }
    }

通过此方法应用过滤器:-

-(UIImage *) applyFilter: (UIImage*) picture withFilterName:(NSString*)Filtername
{
    UIImageOrientation originalOrientation = picture.imageOrientation;
    CGFloat originalScale = picture.scale;
    CIImage *beginImage = [CIImage imageWithCGImage:picture.CGImage];
    CIContext *context = [CIContext contextWithOptions:nil];
     CIFilter *filter = [CIFilter filterWithName:Filtername keysAndValues: kCIInputImageKey, beginImage, nil, [NSNumber numberWithFloat:0.7], nil];
    CIImage *outputImage = [filter outputImage];
    CGImageRef cgimg =
    [context createCGImage:outputImage fromRect:[outputImage extent]];
    UIImage *newImg = [UIImage imageWithCGImage:cgimg scale:originalScale orientation:originalOrientation];

    //CGImageRelease(CGImageRef) method.
    CGImageRelease(cgimg);
    return newImg;

}

错误图片:- - BAD_ACCESS

  1. 您确定 picture 是有效的 UIImage 对象吗?在 applyFilter:withFilterName: 的开头放置一个断点,并使用 Xcode 的快速查看来确认它是您认为的。
  2. 还要检查 Filtername 是否为有效字符串。

如果这些都是正确的,这看起来很可疑:

CIFilter *filter = [CIFilter filterWithName:Filtername keysAndValues: kCIInputImageKey, beginImage, nil, [NSNumber numberWithFloat:0.7], nil];

此处的键和值是一个以 nil 结尾的列表。尝试删除第一个 nil:

之后的所有内容

CIFilter *filter = [CIFilter filterWithName:Filtername keysAndValues: kCIInputImageKey, beginImage, nil];

另请注意,CIVignetteCISepiaTone 都有额外的输入参数(参见 Apple 的 Core Image Filter Reference

终于找到问题了。实际上问题是,我在两种方法中都对静止图像应用过滤器。

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {

 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{

所以,最终的解决方案是在两种方法中使用不同的图像。

这是代码:- //初始设置 -(void)setUpDefaultUI{ [自己隐藏ControlsAndSetupUI];

    arrFilter = @[ @"Original",
                   @"CILinearToSRGBToneCurve",
                   @"CIPhotoEffectChrome",
                   @"CIPhotoEffectFade",
                   @"CIPhotoEffectInstant",
                   @"CIPhotoEffectMono",
                   @"CIPhotoEffectNoir",
                   @"CIPhotoEffectProcess",
                   @"CIPhotoEffectTonal",
                   @"CIPhotoEffectTransfer",
                   @"CISRGBToneCurveToLinear",
                   @"CIVignette",
                   // @"CIVignetteEffect",
                   @"CISepiaTone",
                   ];

    [self.vwCollection registerClass:[ActivityCollectionViewCell class] forCellWithReuseIdentifier:@"ActivityCollectionViewCell"];
    [self.vwCollection registerNib:[UINib nibWithNibName:@"ActivityCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"ActivityCollectionViewCell"];
    _imgEdit.image=_stillImage;
    _OriginalImage=_stillImage;
    temp=_OriginalImage;
}

//Datasource 方法使用过滤器在集合视图中显示图像

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {


    NSLog(@"filterAvailable");

    ActivityCollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"ActivityCollectionViewCell" forIndexPath:indexPath];



    if (cell == nil) {
        NSArray *xib = [[NSBundle mainBundle] loadNibNamed:@"ActivityCollectionViewCell" owner:self options:nil];
        cell = [xib objectAtIndex:0];
        //[cell.imgVw setContentMode:UIViewContentModeScaleAspectFill];
        cell.imgVw.clipsToBounds = YES;

        cell.imgVw.layer.cornerRadius = 5;

    }
  if (indexPath.item==0) {
        cell.imgVw.image = _OriginalImage; //Set original image of 1st index

    }else{
        UIImage *img=[self applyFilter:temp withFilterName:[arrFilter objectAtIndex:indexPath.row]];    // Set temp image in place of stilimage
        cell.imgVw.image=img;

        }
 return cell;
}

//在主图像视图上应用滤镜。

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    if (_EnumPhotos==defaultPhotos) {

    if (indexPath.item==0) {
        _imgEdit.image=_OriginalImage; //If user click on 1st index then original filter applied on main image
    }else{

         UIImage *img=[self applyFilter:_stillImage withFilterName:[arrFilter objectAtIndex:indexPath.row]]; // Use still image here .
        _imgEdit.image = img; // Apply image on main image view
    }
    }
}

//应用过滤方法

-(UIImage *) applyFilter: (UIImage*) picture withFilterName:(NSString*)Filtername
{
    UIImageOrientation originalOrientation = picture.imageOrientation;
    CGFloat originalScale = picture.scale;
    CIImage *beginImage = [CIImage imageWithCGImage:picture.CGImage];
    CIContext *context = [CIContext contextWithOptions:nil];
     CIFilter *filter = [CIFilter filterWithName:Filtername keysAndValues: kCIInputImageKey, beginImage, nil, [NSNumber numberWithFloat:0.7], nil];
    CIImage *outputImage = [filter outputImage];
    CGImageRef cgimg =
    [context createCGImage:outputImage fromRect:[outputImage extent]];
    UIImage *newImg = [UIImage imageWithCGImage:cgimg scale:originalScale orientation:originalOrientation];

    //CGImageRelease(CGImageRef) method.
    CGImageRelease(cgimg);
    return newImg;

}