【问题标题】:Why isn't UIImageWriteToSavedPhotosAlbum() working when using CIImage?为什么使用 CIImage 时 UIImageWriteToSavedPhotosAlbum() 不起作用?
【发布时间】:2016-02-24 05:11:42
【问题描述】:

我正在使用一些链式过滤器生成一个 CIImage,并尝试在用户相册中输出生成的图像以用于某些调试目的。我提供给UIImageWriteToSavedPhotosAlbum() 的回调总是返回一个 nil 错误,所以我认为没有任何问题。但图像似乎从未出现过。

我过去曾使用此功能将 OpenGL 缓冲区转储到相册以进行调试,但我意识到情况并非如此。我应该做些不同的事情吗?

-(void)cropAndSaveImage:(CIImage *)inputImage fromFeature:(CIFaceFeature *)feature
{
    // First crop out the face.
    [_cropFilter setValue:inputImage forKey:@"inputImage"];
    [_cropFilter setValue:[CIVector vectorWithCGRect:feature.bounds] forKey:@"inputRectangle"];
    CIImage * croppedImage = _cropFilter.outputImage;
    __block CIImage * outImage = croppedImage;

    dispatch_async(dispatch_get_main_queue(), ^{
        UIImage * outUIImage = [UIImage imageWithCIImage:outImage];
        UIImageWriteToSavedPhotosAlbum(outUIImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    });
}

-(void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    NSLog(@"debug LBP output face.  error: %@", error);
}

我已验证边界永远不会为 0。

回调输出总是

调试 LBP 输出面。错误:(空)

【问题讨论】:

  • 您需要权限才能访问这些照片。 Permission to camera roll
  • 不,不是这样。我的代码第一次尝试访问它时,通常会通过提示授予访问相机胶卷的权限。我弄清楚了实际的问题。看来我需要实际渲染图像并直接使用 CGImageRef 来实例化 UIImage。不知道为什么这是必要的,可能是 iOS 9 中的错误或兼容性更改?我看过较早的帖子,表明我使用的方法是正确的。请参阅下面的答案。

标签: ios uikit core-image photosframework


【解决方案1】:

我自己解决了这个问题并删除了这个问题,但后来我想也许有人会从中得到一些用处。我这样说是因为我遇到了一个较旧的答案,该答案表明原始实现有效。但实际上必须执行以下操作才能使其正常工作。

     __block CIImage * outImage = _lbpFilter.outputImage;
dispatch_async(dispatch_get_main_queue(), ^{
    CGImageRef imgRef = [self renderCIImage:outImage];
    UIImage * uiImage = [UIImage imageWithCGImage:imgRef];

    UIImageWriteToSavedPhotosAlbum(uiImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
});

+ (CGImageRef)renderCIImage:(CIImage *)img
{
    if ( !m_ctx ) {
        NSDictionary * options = @{kCIContextOutputColorSpace:[NSNull null], kCIContextWorkingColorSpace:[NSNull null]};
        m_ctx = [CIContext contextWithOptions:options];
    }

    return [m_ctx createCGImage:img fromRect:img.extent];
}

【讨论】:

  • 我不明白为什么这整件事不是重复的,比如说:stackoverflow.com/questions/15878060/… 或这个:stackoverflow.com/questions/30558516/… 和许多其他的。 imageWithCIImage 没有生成位图支持的 UIImage 的事实已经在这里重复了很多很多次。我并不是要以任何方式贬低您自己解决了这个问题,但我确实认为这只是重复。
  • 我现在看到这个答案恰好在另一个问题中,尽管我不同意它是那个问题的副本。我是这个领域的新手,对于一个给定对象的 API 来说似乎不太正确.我认为这很容易忽略 UIImageWriteToSavedPhotosAlbum 和 UIImage 的细微差别。它有能力渲染它,而且没有理由不这样做。所以除非有一个确切的问题,否则我一定不同意你的观点。
  • 好的,我愿意将其取消标记为重复。我也没有关于 API 的任何争吵,这有点误导。尽管如此,我也是对的:您需要知道的一般事实,即 CIImage 支持的 UIImage 与位图支持的 UIImage 不同,并且您不能神奇地将一种类型视为另一种类型,这很好记录在 Stack Overflow 上,甚至,如果你仔细想想,在 Apple 的文档中。
  • 我同意你也是正确的,这是我不理解的一个方面。传递的 UIImage 可以是任何类型的 UIImage,假设它必须由专门创建的 UIImage 支持似乎很愚蠢,尽管它是相同的接口。无论 UIImage 参数是如何创建的,将它传递到管道中并期望它呈现并写入文件似乎非常直观。这就是为什么当它没有发生时,它是有问题的。
【解决方案2】:

使用filter.outputImage通过CIContext.createCGImage()转换成CGImage,再将CGImage转换成UIImage就可以成功保存图片了。

【讨论】:

  • 请提供更多代码以使此答案更有用。
猜你喜欢
  • 2021-11-08
  • 2014-05-25
  • 2021-11-14
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 2015-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多