CIImage memory not released

橙三吉。 提交于 2019-12-08 07:16:32

问题


I am trying to take a sequence of images, blend X images at the time and produce a new image. This is the code I have to accomplish this:

static func blendImages(blendFrames: Int, blendMode: CIImage.BlendMode, imagePaths: [URL], completion: @escaping (_ progress: Double) -> Void) {
    var currentIndex = 0

    while currentIndex + blendFrames < imagePaths.count {            
        let currentSubset = Array(imagePaths[currentIndex..<(currentIndex + blendFrames)])

        var currentSubsetIndex = 0

        var firstImage: CIImage?

        while currentSubset.count > currentSubsetIndex + 1 {                
            if firstImage == nil { firstImage = CIImage(contentsOf: currentSubset[currentSubsetIndex]) } //First image allocated in memory

            if let secondImage = CIImage(contentsOf: currentSubset[currentSubsetIndex + 1]) {//Second image allocated in memory
                firstImage = firstImage?.blend(with: secondImage, blendMode: blendMode)
            } //Would expect secondImage to be freed from memory at this point, but it does not happen

            currentSubsetIndex += 1
        } 

        if let finalImage = firstImage {
            let bitMapRep = NSBitmapImageRep(ciImage: finalImage)
            let data = bitMapRep.representation(using: .jpeg, properties: [:])

            do {
                try data?.write(to: URL(fileURLWithPath: "Final-" + String(format: "%03d", currentIndex) + ".jpg"))
            } catch let error as NSError {
                print("Failed to write to disk: \(error)")
            }

        }

        firstImage = nil //Would expect firstImage to be freed from memory at this point (or at beginning of next cycle in while-loop), but it does not happen

        currentIndex += 1
    }
}

And the code for CIImage's blend function

extension CIImage {

    enum BlendMode: String {
        case Lighten = "CILightenBlendMode"
        case Darken = "CIDarkenBlendMode"
    }

    func blend(with image: CIImage, blendMode: BlendMode) -> CIImage? {
        let filter = CIFilter(name: blendMode.rawValue)!
        filter.setDefaults()

        filter.setValue(self, forKey: "inputImage")
        filter.setValue(image, forKey: "inputBackgroundImage")

        return filter.outputImage
    }
}

As detailed in the comments in the code I would expect the memory allocated in firstImage and secondImage to be freed up at the end of the scope they are created in. Since they are both created within a while-loop I would expect them to be freed up at the end of that loop, however, that appears not to happen. But there is no memory leak here, because when the blendImages function finishes the memory is appropriately freed up (however, this is too late as the code could run through hundreds or thousands of images, making the app consume several TBs of data before it is freed up). If anyone can see the flaw in my code and how to make it more memory-efficient that would be very much appreciated.


回答1:


You should use the autoreleasepool function to force the release of the objects inside its scope. This function will help you to manage the memory footprint more precisely.

static func blendImages(blendFrames: Int, blendMode: CIImage.BlendMode, imagePaths: [URL], completion: @escaping (_ progress: Double) -> Void) {
    var currentIndex = 0

    while currentIndex + blendFrames < imagePaths.count {
        autorelease {
            // your code
        }

        currentIndex += 1
    }
}

You can check this post to have more informations.



来源:https://stackoverflow.com/questions/53839394/ciimage-memory-not-released

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!