簡體   English   中英

"為什么應用程序在ios中將pdf頁面轉換為高質量圖像時由於內存警告而終止,在真實設備中快速"

[英]Why app Terminates due to memory waring when convert pdf page to high quality image in ios, swift in real device

我正在嘗試獲取每個 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 頁面。 希望有任何幫助。 祝你今天過得愉快。

1)有時圖像為零。

  • 是否有理由生成 jpeg 數據然后轉換為UIImage<\/code> VS 直接創建 uiimage(使用func image(actions: (UIGraphicsImageRendererContext) -> Void) -> UIImage<\/code> )?<\/li>
  • 如果真的需要使用jpeg方法,那么不要直接從UIImage(data:)<\/code>實例化,使用CGImage的init?(jpegDataProviderSource source: CGDataProvider, decode: UnsafePointer<CGFloat>?, shouldInterpolate: Bool, intent: CGColorRenderingIntent)<\/code>然后使用UIImage(cgImage:)<\/code>來獲取你的UIImage<\/code>實例<\/li><\/ul>

    2)這個運行時,內存使用率很高

      您是否存儲了每頁創建的所有圖像? 如果是,那么如果您有大量頁面的 pdf,那么由於累積的圖像,您將在某個時候消耗最大內存。 為什么不將創建的每個圖像存儲到磁盤,然后再將其釋放,這樣您就不會累積將所有頁面存儲在內存中的內存。<\/li>
    • 在此代碼段之外共享循環(假設存在循環)可以幫助更多地解決您的問題<\/li><\/ul>"

如果您遇到此問題,請嘗試以下操作:

           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 = 2480.0 / pageRect.size.width
                } else {
                    dpi = 2480.0 / pageRect.size.height
                }
                //dpi = 150
                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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM