Objective c 在转换为 UIImage 时丢失了 CIImage 内存

Posted

技术标签:

【中文标题】Objective c 在转换为 UIImage 时丢失了 CIImage 内存【英文标题】:Objective c lost CIImage memory when converting to UIImage 【发布时间】:2016-04-28 17:22:29 【问题描述】:

我有以下代码:

- (void)applySepiaFilter 
    // Set previous image
    NSData *buffer = [NSKeyedArchiver archivedDataWithRootObject: self.mainImage.image];
    [_images push:[NSKeyedUnarchiver unarchiveObjectWithData: buffer]];

    [_images push:[NSKeyedUnarchiver unarchiveObjectWithData: buffer]];


    UIImage* u = [_images pop];
    CIImage *image = [[CIImage alloc] initWithCGImage:u.CGImage];//[CIImage imageWithContentsOfURL:fileNameAndPath];
    CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"
                                  keysAndValues: kCIInputImageKey, image,
                        @"inputIntensity", @0.8, nil];
    CIImage *outputImage = [filter outputImage];
    //UIImage *newImage =
    self.mainImage.image = [UIImage imageWithCIImage:outputImage];

其中 _images 是一个堆栈:

#import "Stack.h"

@implementation Stack
    NSMutableArray *stack;


-(id)init
    self = [super init];
    if(self!=nil)
        stack = [[NSMutableArray alloc] init];
    
    return self;


-(void)push:(id)obj
    [stack addObject:obj];


-(id)pop
    id lastObj = [stack lastObject];
    if (stack.count > 1) 
        [stack removeLastObject];
    
    return lastObj;


-(NSUInteger)size
    return stack.count;


@end

self.mainImage 是一个 UIImageView。

第一次运行该方法时,我得到了所需的棕褐色过滤器。我相信它没有正确保存 self.mainImage.image,因为如果我连续两次运行该方法,我会得到 self.mainImage.image 的空白图像,如果我第三次运行它,我会收到 SIGABRT 错误。 我添加了一个断点并开始遍历代码。我注意到在 self.mainImage.image 方法的第一遍结束时是一个 CIImage *。这让我很困惑,因为它应该是 UIImage *(见图)。Screenshot during debug

让我担心的另一件事是,我注意到缓冲区大小明显小于第二遍时的大小。这让我相信图像没有被保存。同样在第二遍期间,调试器说 *imge 为空。 (见截图)Debugging screenshot during second pass

【问题讨论】:

将图像转换回CGImage 并从中创建UIImage 【参考方案1】:

并不是 mainImage.image 没有被正确保存,而是 UIImageView——就像任何与 CoreGraphics 相关的东西——使用了它的 UIImageCGImage。在documentation for which我们看到

如果 UIImage 对象是使用 CIImage 对象初始化的,则该属性的值为 NULL。

所以你在这里要做的是制作一个CGImage-backed UIImage,然后摆脱所有CoreImage数据分配;将self.imageView.image 分配给类似的东西

- (UIImage *)imageFromCIImage:(CIImage *)ciImage 
    CIContext *ciContext = [CIContext contextWithOptions:nil];    
    CGImageRef cgImage = [ciContext createCGImage:ciImage fromRect:[ciImage extent]];
    UIImage *image = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    return image;

【讨论】:

不要在主线程中进行这种转换,这会耗费大量时间。

以上是关于Objective c 在转换为 UIImage 时丢失了 CIImage 内存的主要内容,如果未能解决你的问题,请参考以下文章

Objective C - 将 UIImage 保存为 BMP 文件

Objective- C:在 UIImage 上绘制边框

如何在Objective C中像Marquee Tag一样为UIImage设置动画

如何在objective-c中使UIImage为NULL

使用 Objective C 自定义相机捕捉图像和裁剪

Objective C - 从这个 PaintCode 代码创建 UIImage