我有以下函数将PDF文件转换为一系列图像(每页一个图像):
import Quartz
func convertPDF(at sourceURL: URL, to destinationURL: URL, fileType: NSBitmapImageFileType, dpi: CGFloat = 200) throws -> [URL] {
let fileExtension: String
switch fileType {
case .BMP: fileExtension = "bmp"
case .GIF: fileExtension = "gif"
case .JPEG, .JPEG2000: fileExtension = "jpeg"
case .PNG: fileExtension = "png"
case .TIFF: fileExtension = "tiff"
}
let data = try Data(contentsOf: sourceURL)
let pdfImageRep = NSPDFImageRep(data: data)!
var imageURLs = [URL]()
for i in 0..<pdfImageRep.pageCount {
pdfImageRep.currentPage = i
let width = pdfImageRep.size.width / 72 * dpi
let height = pdfImageRep.size.height / 72 * dpi
let image = NSImage(size: CGSize(width: width, height: height), flipped: false) { dstRect in
pdfImageRep.draw(in: dstRect)
}
let bitmapImageRep = NSBitmapImageRep(data: image.tiffRepresentation!)!
let bitmapData = bitmapImageRep.representation(using: fileType, properties: [:])!
let imageURL = destinationURL.appendingPathComponent("\(sourceURL.deletingPathExtension().lastPathComponent)-Page\(i+1).\(fileExtension)")
try bitmapData.write(to: imageURL, options: [.atomic])
imageURLs.append(imageURL)
}
return imageURLs
}
这个工作很好,性能不是非常快,但这并不是关键。我的问题与内存消耗有关。假设我正在转换一个长PDF(苹果的10-Q,51页长):
let sourceURL = URL(string: "http://files.shareholder.com/downloads/AAPL/4907179320x0x952191/4B5199AE-34E7-47D7-8502-CF30488B3B05/10-Q_Q3_2017_As-Filed_.pdf")!
let destinationURL = URL(fileURLWithPath: "/Users/mike/PDF")
let _ = try convertPDF(at: sourceURL, to: destinationURL, fileType: .PNG, dpi: 200)
最后一页时,内存使用量达到了约11GB!
我还注意到以下几点:
- 当我通过Instruments运行它时,令人惊讶的是没有泄漏。两个大内存消耗者是
bitmapImageRep
和bitmapData
。它们在迭代之间似乎没有被释放。 - 分析它会使性能变差,即使与Debug版本相比也是如此。
- 降低DPI显然会减少内存占用,但行为仍然相同。内存随页面数量线性增加。
- 无论是将51页PDF转换为单个PDF还是将51个单独的单页PDF转换为图像,情况都是一样的。
那么如何减少内存占用?有更好的将PDF转换为图像的方法吗?