代码之家  ›  专栏  ›  技术社区  ›  Chewie The Chorkie

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

  •  0
  • Chewie The Chorkie  · 技术社区  · 6 年前

    我正在使用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!
    }
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   user7014451 user7014451    6 年前

    这个 第一 你应该做的是 CIContext 使其尽可能全球化。创建它是对内存的主要使用。

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

    把事情联系得更紧密——让下一个过滤器的输入成为前一个过滤器的输出。完成后进行裁剪。最重要的是 CIContexts 尽可能。