2

我正在尝试获取每个 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
  • 当它运行时,使用memory is very high.
  • 随着页数(页数),内存使用率非常高,有时它会1.4 GB突然崩溃并显示警告:Terminate due to memory waring。然后我尝试在里面运行上面的代码autoreleasepool。它确实有效,但是当内存使用率更高时(当它接近 RAM 大小时),应用程序再次崩溃并出现上述警告。

如何避免此内存警告并获得高质量的图像表单 pdf 页面。希望有任何帮助。祝你今天过得愉快。

4

2 回答 2

0

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

           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

于 2022-01-26T18:39:06.727 回答
0

1)有时图像为零。

  • 您是否有理由生成 jpeg 数据然后转换为UIImageVS 直接创建 uiimage(使用func image(actions: (UIGraphicsImageRendererContext) -> Void) -> UIImage)?
  • 如果你真的需要使用jpeg方法,那么不要直接从实例化UIImage(data:),使用CGImage的init?(jpegDataProviderSource source: CGDataProvider, decode: UnsafePointer<CGFloat>?, shouldInterpolate: Bool, intent: CGColorRenderingIntent)然后使用UIImage(cgImage:)来获取你的UIImage实例

2)这个运行时,内存使用率很高

  • 您是否存储了每页创建的所有图像?如果是,那么如果您有大量页面的 pdf,那么由于累积的图像,您将在某个时候消耗最大内存。为什么不将创建的每个图像存储到磁盘,然后再将其释放,这样您就不会累积将所有页面存储在内存中的内存。
  • 在此代码段之外共享循环(假设存在循环)可以帮助更多地解决您的问题
于 2019-05-10T09:08:31.877 回答