在我的应用程序中,我用多张图片(10 到 15 张图片)创建了一个 PDF,并通过电子邮件发送。我的问题是创建的 PDF 太大了,即使我使用 JPG 图像
。图片是收据或发票的照片。
我的调试器向我显示了有关我要放入 PDF 中的图像的以下信息(它们是使用 iPhone 6 上的内置相机拍摄的)
print("UIScreen.main.scale = \(UIScreen.main.scale)") //prints 2
print("image.size = \(image.size)") //prints (2448.0, 3264.0)
print("image.scale = \(image.scale)") //prints image.scale = 1
let imgDataJpg: NSData = NSData(data: UIImageJPEGRepresentation(image, 0.5)!)
let imageSizeJpg = Double(imgDataJpg.length)
print("image size on disk in KB: %f ", imageSizeJpg / 1024.0) //prints 899.5888671875
我已经编写了用于创建 PDF 文件的协议(protocol)扩展。这是我的代码:
protocol RendersPdf {
var realm: Realm { get }
func renderPdf() -> URL?
}
extension RendersPdf {
//this is the default size of a PDF page
fileprivate var pageFrame: CGRect {
get {
return CGRect(x: 0, y: 0, width: 612, height: 792)
}
}
func renderPdf(images: [UIImage]) -> URL? {
let pdfUrl = startPdf()
let context = UIGraphicsGetCurrentContext()
defer {
UIGraphicsEndPDFContext()
}
for image in images {
draw(image: image)
}
}
func startPdf() -> URL {
let pdfUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("somePdfName").appendingPathExtension("pdf")
let success = UIGraphicsBeginPDFContextToFile(pdfUrl.path, CGRect.zero, nil)
assert(success, "could not create pdf graphics context")
return pdfUrl
}
fileprivate func draw(image: UIImage) {
UIGraphicsBeginPDFPageWithInfo(pageFrame, nil)
let imageFrame = pageFrame
image.draw(in: imageFrame)
}
fileprivate func resize(image: UIImage) -> UIImage {
UIGraphicsBeginImageContextWithOptions(pageFrame.size, false, 0.0);
image.draw(in: CGRect(x: 0, y: 0, width: pageFrame.size.width, height: pageFrame.size.height))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() ?? image
UIGraphicsEndImageContext()
return newImage
}
}
如果我有 11 张图片,我的 PDF 会变得 11MB 大,所以我尝试使用上面的调整大小功能手动调整图像大小来缩小它。但是,PDF 变得更大,在我的情况下高达 32MB(这怎么可能,我把图像变小了?)
如何减小生成的 PDF 的文件大小?如何确保该解决方案适用于不同的屏幕分辨率(iPhone 6:1 点在 iPhone 6+ 1 上为 2px点是 3px)。
最佳答案
您需要设置 pdf 的最大文件大小,并根据此大小降低图像质量。检查此示例,并根据需要随意使用和修改它:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//choose the size you want or use your own size
let MB_10 = 10485760
let MB_5 = 5242880
let MB_3 = 3145728
let images : [UIImage] = [] //<---- insert your images here
if self.createPDF(images: images, maxSize: MB_5, quality: 100) != nil {
print("worked check pdfFilePath")
}
}
func createPDF(images:[UIImage], maxSize:Int, quality:Int) -> NSData? {
if quality > 0 {
guard let pdfFilePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first?.appending("someName.pdf") else {
print("Error creating pdf path")
return nil
}
var largestImageSize = CGSize.zero
for image in images {
if image.size.width > largestImageSize.width {
largestImageSize.width = image.size.width
}
if image.size.height > largestImageSize.height {
largestImageSize.height = image.size.height
}
}
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRect(x: 0, y: 0, width: largestImageSize.width, height: largestImageSize.height), nil)
let context = UIGraphicsGetCurrentContext()
for image in images {
UIGraphicsBeginPDFPage()
UIGraphicsPushContext(context!)
if quality != 100 {
guard let imageData = UIImageJPEGRepresentation(image, CGFloat(quality) / 100.0) else {
print("Error reducing image size")
return nil
}
guard let newImage = UIImage(data: imageData) else {
print("Error creating image from data")
return nil
}
newImage.draw(at: CGPoint.zero)
} else {
image.draw(at: CGPoint.zero)
}
UIGraphicsPopContext()
}
UIGraphicsEndPDFContext();
if (pdfData.length > maxSize) {
print("reduces quality to \(quality - 10)")
return self.createPDF(images: images, maxSize: maxSize, quality: quality - 10)
}
if !pdfData.write(toFile: pdfFilePath, atomically: true) {
print("write to pdfFilePath failed")
}
return NSData(contentsOfFile: pdfFilePath)
}
return nil
}
}
关于ios - 在 iOS CoreGraphics 中减小渲染 PDF 的文件大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41663432/