Память CIImage не освобождена - PullRequest
       99

Память CIImage не освобождена

0 голосов
/ 18 декабря 2018

Я пытаюсь взять последовательность изображений, смешать X изображений в то время и создать новое изображение.Вот код, который я должен выполнить:

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

И код для blend функции CIImage

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 завершает работу, память должным образом освобождается (однако это слишком поздно, поскольку код может проходить через сотни или тысячи изображений, заставляя приложение потреблять несколько ТБ данных перед тем, какэто освобождено).Если кто-нибудь увидит недостаток в моем коде и как сделать его более эффективным в использовании памяти, это будет очень цениться.

1 Ответ

0 голосов
/ 19 декабря 2018

Вы должны использовать функцию autoreleasepool для принудительного освобождения объектов внутри своей области видимости.Эта функция поможет вам более точно управлять объемом памяти.

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

Вы можете проверить эту запись , чтобы получить больше информации.

...