Swift 为什么这个快速UIImage函数会溢出我的内存?
我正在使用Swift 4为iPhone构建一个应用程序。我有一些测试过滤器。通过相机的输出,两者都可以正常工作,但当我从更复杂的图像中创建一组图像时,我的内存溢出到灾难性的程度,并使我的应用程序崩溃 我在一个循环中调用下面的一个,它溢出了我的内存: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
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,这是另一个具有不同颜色的图像的顶部,因此它看起来有一个渐变。