Swift 为什么这个快速UIImage函数会溢出我的内存?

Swift 为什么这个快速UIImage函数会溢出我的内存?,swift,memory,crash,uiimage,cifilter,Swift,Memory,Crash,Uiimage,Cifilter,我正在使用Swift 4为iPhone构建一个应用程序。我有一些测试过滤器。通过相机的输出,两者都可以正常工作,但当我从更复杂的图像中创建一组图像时,我的内存溢出到灾难性的程度,并使我的应用程序崩溃 我在一个循环中调用下面的一个,它溢出了我的内存: func rotateHue2(with ciImage: CIImage, rotatedByHue deltaHueRadians: CGFloat, orientation:UIIma

我正在使用Swift 4为iPhone构建一个应用程序。我有一些测试过滤器。通过相机的输出,两者都可以正常工作,但当我从更复杂的图像中创建一组图像时,我的内存溢出到灾难性的程度,并使我的应用程序崩溃

我在一个循环中调用下面的一个,它溢出了我的内存:

func rotateHue2(with ciImage: CIImage,
               rotatedByHue deltaHueRadians: CGFloat,
               orientation:UIImageOrientation?,
               screenWidth:CGFloat,
               screenHeight:CGFloat) -> UIImage {


    let sourceCore = ciImage


    let transBG = UIImage(color: .clear, size: CGSize(width: screenWidth, height: screenHeight))

    let transBGCI = CIImage(cgImage: (transBG?.cgImage)!)



    // Part 1

    let gradientPoint0Pos: [CGFloat] = [0, 0]
    let inputPoint0Vector = CIVector(values: gradientPoint0Pos, count: gradientPoint0Pos.count)

    var gradientPoint1Pos: [CGFloat]
    if(orientation == nil){

        gradientPoint1Pos = [0, screenWidth*2]

    }else{

        gradientPoint1Pos = [screenHeight*2, 0]

    }

    let inputPoint1Vector = CIVector(values: gradientPoint1Pos, count: gradientPoint1Pos.count)


    let gradientFilter = CIFilter(name: "CISmoothLinearGradient")
    gradientFilter?.setDefaults()
    gradientFilter?.setValue(inputPoint0Vector, forKey: "inputPoint0")
    gradientFilter?.setValue(inputPoint1Vector, forKey: "inputPoint1")


    gradientFilter?.setValue(CIColor.clear, forKey:"inputColor0")
    gradientFilter?.setValue(CIColor.black, forKey:"inputColor1")


    let gradient = gradientFilter?.outputImage?
        .cropped(to: sourceCore.extent)



    let hue1 = sourceCore
        .applyingFilter("CIHueAdjust", parameters: [kCIInputImageKey: sourceCore,
                                                    kCIInputAngleKey: deltaHueRadians])
        .cropped(to: sourceCore.extent)


    let alphaMaskBlend1 = CIFilter(name: "CIBlendWithAlphaMask",
                                   withInputParameters: [kCIInputImageKey: hue1,
                                                         kCIInputBackgroundImageKey: transBGCI,
                                                         kCIInputMaskImageKey:gradient!])?.outputImage?
        .cropped(to: sourceCore.extent)


    // Part 2


    let hue2 = sourceCore
        .applyingFilter("CIHueAdjust", parameters: [kCIInputImageKey: sourceCore,
                                                    kCIInputAngleKey: deltaHueRadians+1.5707])
        .cropped(to: sourceCore.extent)


    let blendedMasks = hue2
        .applyingFilter(compositeOperationFilters[compositeOperationFiltersIndex], parameters: [kCIInputImageKey: alphaMaskBlend1!,
                                                                                                kCIInputBackgroundImageKey: hue2])
        .cropped(to: sourceCore.extent)




    // Convert the filter output back into a UIImage.
    let context = CIContext(options: nil)
    let resultRef = context.createCGImage(blendedMasks, from: blendedMasks.extent)

    var result:UIImage? = nil

    if(orientation != nil){

        result = UIImage(cgImage: resultRef!, scale: 1.0, orientation: orientation!)

    }else{

        result = UIImage(cgImage: resultRef!)

    }
    return result!
}
根据手机的方位,每个图像的大小可调至1280或720宽。当我的其他图像过滤器工作正常时,为什么这会给我一个内存警告

只是为了好玩,这里有另一个不会让它崩溃的:

func rotateHue(with ciImage: CIImage,
                rotatedByHue deltaHueRadians: CGFloat,
                orientation:UIImageOrientation?,
                screenWidth:CGFloat,
                screenHeight:CGFloat) -> UIImage {


    // Create a Core Image version of the image.
    let sourceCore = ciImage
    // Apply a CIHueAdjust filter
    let hueAdjust = CIFilter(name: "CIHueAdjust")
    hueAdjust?.setDefaults()
    hueAdjust?.setValue(sourceCore, forKey: "inputImage")
    hueAdjust?.setValue(deltaHueRadians, forKey: "inputAngle")

    let resultCore = CIFilter(name: "CIHueAdjust",
                              withInputParameters: [kCIInputImageKey: sourceCore,
                                                    kCIInputAngleKey: deltaHueRadians])?.outputImage?
        .cropped(to: sourceCore.extent)


    // Convert the filter output back into a UIImage.
    let context = CIContext(options: nil)
    let resultRef = context.createCGImage(resultCore!, from: (resultCore?.extent)!)

    var result:UIImage? = nil

    if(orientation != nil){

        result = UIImage(cgImage: resultRef!, scale: 1.0, orientation: orientation!)

    }else{

        result = UIImage(cgImage: resultRef!)

    }
    return result!
}
您应该做的第一件事是将您的
CIContext
移出函数,并使其尽可能全局化。创建它是对内存的主要使用

少一点问题,为什么每个图像要裁剪五次?这可能不是问题所在,但我“感觉”不对。
CIImage
不是图像,它更接近于“配方”

把事情联系得更紧密——让下一个过滤器的输入成为上一个过滤器的输出。完成后进行修剪。最重要的是,创建尽可能少的
CIContext

您应该做的第一件事是将您的
CIContext
移出函数并使其尽可能全局。创建它是对内存的主要使用

少一点问题,为什么每个图像要裁剪五次?这可能不是问题所在,但我“感觉”不对。
CIImage
不是图像,它更接近于“配方”


把事情联系得更紧密——让下一个过滤器的输入成为上一个过滤器的输出。完成后进行修剪。最重要的是,创建尽可能少的
ciContext

这确实有帮助,但我仍然看到内存峰值高达1.5GB!为什么?可能是锁链,但我不知道如何把它们锁得更紧。也许是因为我也在重新制作transBGCI,这在循环中以某种方式建立起来?高水平,你到底想做什么?另外,在技术层面上,
rotateHue2(带:)
在做什么?在不知道这一点的情况下,我无法使用“更紧密”的代码进行编辑。例如,为什么函数要创建UIImage,
transBG
,将其转换为CIImage,然后执行其他所有操作?至少-将上下文移出函数后,将其分解为组件函数并进行计时。根据您尝试执行的操作,您可能会发现您可以将内容传递到使用链接CIFilter的函数中。最后一点注意。通过紧密链接,我只是想将每个
kCIInputImageKey
直接设置为前一个过滤器的
outputImage
CIFilter.crapped(to:)
很可能是问题所在-第一个函数有五个,第二个函数只有一个。另外,尝试使
CIFilter
调用更全局。如果要重复使用四个“命名”过滤器,可以在函数外部创建它们,以免每次调用函数时都实例化它们。(你从来没有说过这个图像数组有多大。)好的建议,我周一会试试。图像数组是31个图像。它们将相机的输出转换为两幅具有不同颜色变化的图像,每次捕捉相机的输出或用户拍照并在for循环中更改时,这些图像都会发生变化。我正在制作一个透明的图像作为遮罩的背景,这样一个图像可以淡入0 alpha,这是另一个不同颜色的图像的叠加,因此它看起来有一个梯度。这确实有帮助,但我仍然看到高达1.5 GB的内存峰值!为什么?可能是锁链,但我不知道如何把它们锁得更紧。也许是因为我也在重新制作transBGCI,这在循环中以某种方式建立起来?高水平,你到底想做什么?另外,在技术层面上,
rotateHue2(带:)
在做什么?在不知道这一点的情况下,我无法使用“更紧密”的代码进行编辑。例如,为什么函数要创建UIImage,
transBG
,将其转换为CIImage,然后执行其他所有操作?至少-将上下文移出函数后,将其分解为组件函数并进行计时。根据您尝试执行的操作,您可能会发现您可以将内容传递到使用链接CIFilter的函数中。最后一点注意。通过紧密链接,我只是想将每个
kCIInputImageKey
直接设置为前一个过滤器的
outputImage
CIFilter.crapped(to:)
很可能是问题所在-第一个函数有五个,第二个函数只有一个。另外,尝试使
CIFilter
调用更全局。如果要重复使用四个“命名”过滤器,可以在函数外部创建它们,以免每次调用函数时都实例化它们。(你从来没有说过这个图像数组有多大。)好的建议,我周一会试试。图像数组是31个图像。它们将相机的输出转换为两幅具有不同颜色变化的图像,每次捕捉相机的输出或用户拍照并在for循环中更改时,这些图像都会发生变化。我将透明图像作为遮罩的背景,这样一个图像可以淡入0 alpha,这是另一个具有不同颜色的图像的顶部,因此它看起来有一个渐变。