Memory 如何处理iOS 8照片扩展中的内存限制?

Memory 如何处理iOS 8照片扩展中的内存限制?,memory,ios8,ios8-extension,Memory,Ios8,Ios8 Extension,我在现有的照片编辑应用程序中添加了一个新的iOS 8照片扩展。我的应用程序有一个相当复杂的过滤管道,需要一次在内存中保存多个纹理。但是,在具有1GB RAM的设备上,我可以轻松处理8MP图像 然而,在扩展中,内存约束要高得多。我不得不将图像缩小到2 MP以下,以便在不破坏分机的情况下对其进行处理。我还认为,内存问题只会在没有将调试器连接到扩展时发生。有了它,一切都很好 我做了一些实验。我将a修改为在扩展中工作,并得出以下结果(显示崩溃前可以分配的RAM量(以MB为单位): 一些意见: 附加调试

我在现有的照片编辑应用程序中添加了一个新的iOS 8照片扩展。我的应用程序有一个相当复杂的过滤管道,需要一次在内存中保存多个纹理。但是,在具有1GB RAM的设备上,我可以轻松处理8MP图像

然而,在扩展中,内存约束要高得多。我不得不将图像缩小到2 MP以下,以便在不破坏分机的情况下对其进行处理。我还认为,内存问题只会在没有将调试器连接到扩展时发生。有了它,一切都很好

我做了一些实验。我将a修改为在扩展中工作,并得出以下结果(显示崩溃前可以分配的RAM量(以MB为单位):

一些意见:

  • 附加调试器后,扩展的行为与“普通”应用程序类似
  • 尽管与其他设备相比,4s的总内存量(512 MB)只有一半,但它从系统中获得的扩展内存量还是相同的~100 MB
现在我的问题是:我应该如何在照片编辑扩展中使用这么小的内存?一个包含8MP(相机分辨率)RGBA图像的纹理单独消耗约31MB。如果我必须告诉用户只有在使用主应用程序时才能进行全尺寸编辑,那么这种扩展机制有什么意义


你们中有人也到了那个障碍吗?您是否找到了绕过此限制的解决方案?

我正在为我的公司开发一个照片编辑扩展,我们面临着同样的问题。我们的内部图像处理引擎需要超过150mb的内存才能对图像应用某些效果。这还不包括全景图像,每一张全景图像大约需要100mb的内存

我们只找到了两个解决方法,但没有找到实际的解决方案

  • 缩小图像并应用过滤器。这将需要更少的内存,但图像效果很糟糕。至少扩展不会崩溃
  • 使用CoreImage或Metal进行图像处理。正如我们分析的,使用CoreImage的Apple可以处理非常大的图像,甚至全景图像,而不会降低质量或分辨率。实际上,我们无法通过加载非常大的图像使扩展崩溃。示例代码可以处理40mb内存的全景图,这非常令人印象深刻 根据苹果的第55页“处理内存限制”一章,解决扩展内存压力的方法是查看图像处理代码。到目前为止,我们正在将我们的图像处理引擎移植到CoreImage,结果远远好于我们以前的引擎

    我希望我能帮点忙。
    Marco Paiva

    如果你使用的是核心图像“配方”,你根本不需要担心内存,正如Marco所说。在图像对象返回到视图之前,不会渲染应用核心图像过滤器的图像

    这意味着你可以对一张高速公路广告牌大小的照片应用一百万个过滤器,而内存不是问题。过滤器规范将被简单地编译成一个卷积或内核,不管发生什么,它们都会降到相同的大小

    通过使用所选编程语言、开发环境和硬件平台的核心概念来引导自己,可以很容易地消除对内存管理和溢出等方面的误解


    苹果公司介绍核心图像过滤器编程的文档足以满足这一要求;如果您想具体参考文档中我认为与您的关注点相关的部分,请询问。

    以下是如何在Core Image中应用两个连续的卷积核,并在它们之间使用“中间结果”:

    - (CIImage *)outputImage { 
    
    const double g = self.inputIntensity.doubleValue;
    const CGFloat weights_v[] = { -1*g, 0*g, 1*g,
                                  -1*g, 0*g, 1*g,
                                  -1*g, 0*g, 1*g};
    
    CIImage *result = [CIFilter filterWithName:@"CIConvolution3X3" keysAndValues:
              @"inputImage", self.inputImage,
              @"inputWeights", [CIVector vectorWithValues:weights_v count:9],
              @"inputBias", [NSNumber numberWithFloat:1.0],
              nil].outputImage;
    
    CGRect rect = [self.inputImage extent];
    rect.origin = CGPointZero;
    
    CGRect cropRectLeft = CGRectMake(0, 0, rect.size.width, rect.size.height);
    CIVector *cropRect = [CIVector vectorWithX:rect.origin.x Y:rect.origin.y Z:rect.size.width W:rect.size.height];
    result = [result imageByCroppingToRect:cropRectLeft];
    
    result = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", result, @"inputRectangle", cropRect, nil].outputImage;
    
    
    const CGFloat weights_h[] = {-1*g, -1*g, -1*g,
        0*g,   0*g,   0*g,
        1*g,   1*g,     1*g};
    
    
    result = [CIFilter filterWithName:@"CIConvolution3X3" keysAndValues:
              @"inputImage", result,
              @"inputWeights", [CIVector vectorWithValues:weights_h count:9],
              @"inputBias", [NSNumber numberWithFloat:1.0],
              nil].outputImage;
    
    result = [result imageByCroppingToRect:cropRectLeft];
    
    result = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", result, @"inputRectangle", cropRect, nil].outputImage;
    
    result = [CIFilter filterWithName:@"CIColorInvert" keysAndValues:kCIInputImageKey, result, nil].outputImage;
    
    return result;
    

    }

    谢谢你,马可。我猜CoreImage在引擎盖下做瓷砖。我将尝试使用仪器来弄清楚它到底在做什么。我的问题是,我需要支持存储签名值的纹理,而据我所知,我现在无法使用CoreImage实现这一点。另一点是,自定义CoreImage过滤器仅在iOS 8中受支持,我仍然希望在我的主应用程序中支持iOS 7。我想我最终会自己实现一个平铺机制。但很高兴知道CoreImage可以处理大型图像。再次感谢。请注意,Core Image提供了几个插入您自己的图像处理的机会(同时受益于CI memory/GPU/color/etc管理)。除了能够编写自始至终都存在的自定义内核之外,iOS 10还引入了一种功能,它允许您将CI以外的技术插入到CI图像处理链中。很抱歉,这根本没有帮助。我知道核心图像是如何工作的,它能做什么。它可以通过将一些后续的过滤步骤编译成一个步骤来优化它们,但它不能总是这样做。例如,两个后续的卷积核不能编译成一个,因为您需要一个中间结果。正如我对Marco所说,Core Image不支持我的管道所需的所有功能。我已经优化了我的管道,一次“只”使用4个纹理,但对于扩展来说,内存仍然太多了…“一次四个纹理?”如何在核心图像中使用甚至一个“纹理”?这是没有道理的…正如我所说,我不能使用核心图像,因为它不能提供我所需要的一切。我使用OpenGL编写了自己的图像处理管道。我应该有OpenGL子集glslang。您必须完整地谈论OpenGL,如果您正在编写一个照片编辑扩展,您可能不会使用它。运行用glslang编写的OpenGL内核代码比不运行要容易;您只需将其作为捆绑资源加载到自定义核心映像过滤器中。核心图像并不局限于内置的过滤器,你是对的,它不会适用于所有的东西;我并不推荐它胜过OpenGL。OpenGL(glslang)内核可以加载到自定义核心图像过滤器中;然后,您可以将核心图像组合为fi
    - (CIImage *)outputImage { 
    
    const double g = self.inputIntensity.doubleValue;
    const CGFloat weights_v[] = { -1*g, 0*g, 1*g,
                                  -1*g, 0*g, 1*g,
                                  -1*g, 0*g, 1*g};
    
    CIImage *result = [CIFilter filterWithName:@"CIConvolution3X3" keysAndValues:
              @"inputImage", self.inputImage,
              @"inputWeights", [CIVector vectorWithValues:weights_v count:9],
              @"inputBias", [NSNumber numberWithFloat:1.0],
              nil].outputImage;
    
    CGRect rect = [self.inputImage extent];
    rect.origin = CGPointZero;
    
    CGRect cropRectLeft = CGRectMake(0, 0, rect.size.width, rect.size.height);
    CIVector *cropRect = [CIVector vectorWithX:rect.origin.x Y:rect.origin.y Z:rect.size.width W:rect.size.height];
    result = [result imageByCroppingToRect:cropRectLeft];
    
    result = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", result, @"inputRectangle", cropRect, nil].outputImage;
    
    
    const CGFloat weights_h[] = {-1*g, -1*g, -1*g,
        0*g,   0*g,   0*g,
        1*g,   1*g,     1*g};
    
    
    result = [CIFilter filterWithName:@"CIConvolution3X3" keysAndValues:
              @"inputImage", result,
              @"inputWeights", [CIVector vectorWithValues:weights_h count:9],
              @"inputBias", [NSNumber numberWithFloat:1.0],
              nil].outputImage;
    
    result = [result imageByCroppingToRect:cropRectLeft];
    
    result = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", result, @"inputRectangle", cropRect, nil].outputImage;
    
    result = [CIFilter filterWithName:@"CIColorInvert" keysAndValues:kCIInputImageKey, result, nil].outputImage;
    
    return result;