ios - 为什么应用程序在将 pdf 页面转换为 ios 中的高质量图像时由于内存警告而终止,在真实设备中 swift

标签 ios swift terminate pdfkit memory-warning

我正在尝试获取每个 pdf 页面的图像(高质量)。我正在使用下面的代码通过 for 循环运行直到页面计数并且它有效。

    guard let document = CGPDFDocument(pdfurl as CFURL) else { return }
    guard let page = document.page(at: i) else { return }
    let dpi: CGFloat = 300.0/72.0
    let pagerect = page.getBoxRect(.mediaBox)
    print(pagebounds)
    print(pagerect)
    let render = UIGraphicsImageRenderer(size: CGSize(width: pagerect.size.width * dpi, height: pagerect.size.height * dpi))

    let imagedata = render.jpegData(withCompressionQuality: 0.5, actions: { cnv in
        UIColor.white.set()
        cnv.fill(pagerect)
        cnv.cgContext.translateBy(x: 0.0, y: pagerect.size.height * dpi)
        cnv.cgContext.scaleBy(x: dpi, y: -dpi)
        cnv.cgContext.drawPDFPage(page)
    })
    let image = UIImage(data: imagedata)

我遇到了以下问题......

  • 有时 imagenil
  • 运行时,内存使用率非常高
  • 随着页数(页数)的增加,内存使用量非常非常高,有时会达到 1.4 GB,突然应用程序崩溃并显示警告:Terminate due内存警告。然后我尝试在 autoreleasepool 中运行上面的代码。它确实有效,但是当内存使用率更高时(当它接近 RAM 大小时),应用程序再次崩溃并显示上述警告。

如何避免此内存警告并从 pdf 页面获取高质量图像。希望有帮助。祝你有美好的一天。

最佳答案

如果您遇到此问题,请尝试以下操作:

           autoreleasepool {
                guard let page = document.page(at: i) else { return }
                
                // Fetch the page rect for the page we want to render.
                let pageRect = page.getBoxRect(.mediaBox)
                var dpi: CGFloat = 1.0
                if pageRect.size.width > pageRect.size.height {
                    dpi = 3508.0 / pageRect.size.width
                } else {
                    dpi = 3508.0 / pageRect.size.height
                }
                //dpi = 300
                let format = UIGraphicsImageRendererFormat()
                format.scale = 1
                let renderer = UIGraphicsImageRenderer(size: CGSize(width: pageRect.size.width * dpi, height: pageRect.size.height * dpi), format: format)
                let imagedata = renderer.jpegData(withCompressionQuality: 1.0, actions: { cnv in
                    UIColor.white.set()
                    cnv.fill(pageRect)
                    cnv.cgContext.translateBy(x: 0.0, y: pageRect.size.height * dpi)
                    cnv.cgContext.scaleBy(x: dpi, y: -dpi)
                    cnv.cgContext.drawPDFPage(page)
                })
                let image = UIImage(data: imagedata)
                
            }

autoreleasepool - 用于永久内存清除

缩放 - 这样就不会为不同的设备创建图像,这会将它们的分辨率提高 2 或 3 倍

更改了增加 dpi 的方式,因为它最初可以大于或小于 72

关于ios - 为什么应用程序在将 pdf 页面转换为 ios 中的高质量图像时由于内存警告而终止,在真实设备中 swift ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56072991/

相关文章:

ios - 如何使用 swinject 正确注入(inject)依赖项

ios - 快速在选项卡式 View 之间传递数据

ios - 另一个 Collection View 内的 Collection View 单元格的约束

c++ - 未处理的强制展开导致中止

ios - Realm 迁移枚举无法执行

ios - 什么是通过 Enum 进行可重用 UIAlertController 配置的 Swift 最佳实践

ios - 循环中的快速延迟

Java 程序在 ObjectMapper.writeValue(System.out, responseData) 之后终止 - Jackson Library

python - 从另一个 python 脚本终止一个 python 脚本

ios - NSOperationqueue后台,下载图片