CIImage内存未释放 [英] CIImage memory not released

查看:503
本文介绍了CIImage内存未释放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试拍摄一系列图像,同时混合X个图像并生成一个新图像.这是我必须完成的代码:

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
    }
}

还有CIImage的blend函数的代码

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
    }
}

如代码注释中所述,我希望在创建它们的作用域末尾释放在firstImage和secondImage中分配的内存.由于它们都是在while循环中创建的,所以我希望它们在该循环结束时将其释放,但是,这似乎没有发生.但是这里没有内存泄漏,因为当blendImages函数完成时,内存已被适当地释放(但是,这太迟了,因为代码可以运行成百上千个图像,从而使该应用程序在使用之前消耗了数TB的数据)它被释放了). 如果有人能看到我的代码中的缺陷以及如何提高其内存效率,那将不胜感激.

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.

推荐答案

您应使用 autoreleasepool 函数可强制释放其作用域内的对象.此功能将帮助您更精确地管理内存占用.

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.

这篇关于CIImage内存未释放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆