减少iOS CoreGraphics中渲染PDF的文件大小

时间:2017-01-15 16:30:41

标签: ios iphone swift pdf

在我的应用程序中,我使用多个图像(10到15张图像)创建PDF并通过电子邮件发送。我的问题是,即使我使用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也太大了。图像是收据或发票的照片。

我的调试器向我显示了有关我想要放入PDF中的图像的以下信息(它们是使用内置摄像头在 iPhone 6 上拍摄的)

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   
}
}

我已经编写了用于创建PDF文件的协议扩展。这是我的代码:

  listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                    @Override
                    public void onItemClick(AdapterView<?> parent,
                                            View view, int position, long id) {

                        CheckBox chk = (CheckBox) view
                                .findViewById(R.id.contactcheck);
                        ContactObject bean = ContactsListClass.phoneList
                                .get(position);
                        if (bean.isSelected()) {
                            bean.setSelected(false);
                            chk.setChecked(false);

                        } else {
                            bean.setSelected(true);
                            chk.setChecked(true);


                        }

                    }
                });

如果我有11个图像,我的PDF会 11MB 大,所以我尝试通过使用上面的调整大小功能手动调整图像大小来缩小图像。然而,PDF变得更大,在我的情况下高达32MB(世界上如何可能,我已经使图像更小?)

如何减少生成的PDF的文件大小?如何确保解决方案适用于不同的屏幕分辨率(iPhone 6 + 1上iPhone 6:1点为2px)点是3px)。

1 个答案:

答案 0 :(得分:1)

您需要设置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
}
}