简体   繁体   中英

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

I'm trying to get the image(high quality) of each pdf page. I'm using below code running through a for loop until page count and it works.

    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)

I'm getting following issues with this ...

  • sometimes the image is nil .
  • When this runs, the usage of memory is very high .
  • With the page count(number of pages), usage of memory is very very high, and sometimes it goes to 1.4 GB and suddenly it crashes the app with the warning : Terminate due to memory waring . then I tried to run above code inside autoreleasepool . it did work but when the memory usage is more high (when it near to RAM size), again app crashes with above warning.

How can I avoid this memory warning and get the quality image form pdf page. hope any help. have a nice day.

1) sometimes the image is nil.

  • <\/li>
  • <\/li><\/ul>

    2) When this runs, the usage of memory is very high

      If yes, then if you have a pdf of high number of pages then you will consume max memory at some point because of accumulated images. Why don't you store to disk each image created then releasing it afterwards so you don't accumulate the memory of storing all pages in memory.<\/li>
    • <\/li><\/ul>"

If you are facing this issue then try this:

           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 - for permanent memory clearing

scale - so that images for different devices are not created, which increases their resolution by 2 or 3 times

changed the way to increase dpi as it can be initially more or less than 72

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM