调整图像大小时内存泄漏

问题描述 投票:0回答:2

我有一种方法将 PDF 转换为图像(每个页面都转换为 UIImage),并调整每个图像的大小。方法正在以 QOS = 背景调用自定义队列。

当我尝试处理超过 90 页的 PDF 时,出现错误并且我的应用程序崩溃了:

Message from debugger: Terminated due to memory issue

这是我的方法:

func convertPDFToImages(pdfURL: URL) -> ContiguousArray<UIImage>? {
    guard let pdfDocument = PDFDocument(url: pdfURL) else {
      return nil
    }

    var images: ContiguousArray<UIImage> = []
    autoreleasepool {
      for pageNum in 0..<pdfDocument.pageCount {
        if let pdfPage = pdfDocument.page(at: pageNum) {
          let pdfPageSize = pdfPage.bounds(for: .mediaBox)
          let renderer = UIGraphicsImageRenderer(size: pdfPageSize.size)
          
          var image = renderer.image { ctx in
            UIColor.white.set()
            ctx.fill(pdfPageSize)
            ctx.cgContext.translateBy(x: 0.0, y: pdfPageSize.size.height)
            ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
            
            pdfPage.draw(with: .mediaBox, to: ctx.cgContext)
          }
          
          image = scalePreservingAspectRatio(image, newWidth: newWidth)             
          
          images.append(image)
        }
      }
    }

    return images
  }

func scalePreservingAspectRatio(_ image: UIImage, newWidth: CGFloat) -> UIImage {
    let scaleFactor = newWidth / image.size.width
    let scaledImageSize = CGSize(
      width: newWidth,
      height: image.size.height * scaleFactor
    )
    let renderer = UIGraphicsImageRenderer(
      size: scaledImageSize
    )

    let scaledImage = renderer.image { _ in
      image.draw(in: CGRect(
        origin: .zero,
        size: scaledImageSize
      ))
    }

    return scaledImage
  }

我尝试过的:

  • 注释掉调用
    scalePreservingAspectRatio
    获取图像 - 仍然是一个错误
  • 使用 ContigouslyArray 而不是 Array - 出现错误
  • 使用 autoreleasepool 进行循环 - 仍然出现错误

据我了解,问题在于多次创建 UIGraphicsImageRenderer 和中间图像实例 enter image description here

swift memory-management core-graphics
2个回答
0
投票

好吧,我自己的问题得到了答案)

首先,基于这个答案我已经将

autorelease pool
移动到循环内

作为第二步,我将格式添加到比例因子为 1 的渲染器(基于 这个很棒的解释

          let format = UIGraphicsImageRendererFormat()
          format.scale = 1

          let renderer = UIGraphicsImageRenderer(size: pdfPageSize.size, format: format)

0
投票
func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
    // Calculate the aspect ratio of the original image
    let aspectWidth = targetSize.width / image.size.width
    let aspectHeight = targetSize.height / image.size.height
    
    // Use the smaller scale factor to maintain the aspect ratio
    let aspectRatio = min(aspectWidth, aspectHeight)
    enter code here
    // Calculate the new size based on the aspect ratio
    let scaledSize = CGSize(width: image.size.width * aspectRatio, height: image.size.height * aspectRatio)

    // Use an autorelease pool to help manage memory efficiently
    return autoreleasepool {
        let format = UIGraphicsImageRendererFormat()
        format.scale = 1
        let renderer = UIGraphicsImageRenderer(size: scaledSize, format: format)
        let resizedImage = renderer.image { _ in
            image.draw(in: CGRect(origin: .zero, size: scaledSize))
        }

        return resizedImage
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.