2017-01-15 4 views
1

В моем приложении я создаю PDF из нескольких изображений (от 10 до 15 изображений) и отправляю их по электронной почте. Моя проблема в том, что созданный PDF слишком большой, даже если я использую JPG images. Изображения - это фотографии квитанций или счетов-фактур.Уменьшить размер рендеринга PDF в iOS CoreGraphics

Мой отладчик показывает мне следующую информацию об изображениях, которые я хочу, чтобы положить в 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 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 становится еще больше, в моем случае до 32 МБ (как это возможно в мире, я сделал меньше изображений?)

Что я могу сделать, чтобы уменьшить размер файла моего сгенерированного PDF-файла ? Как я могу убедиться, что решение работает на разных разрешениях экрана (iPhone 6: 1 точка - 2 пикселя на iPhone 6+ 1 точка - 3 пикселя).

ответ

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 
} 
} 
Смежные вопросы