KMCompressManager.swift 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. //
  2. // KMCompressManager.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lizhe on 2024/12/17.
  6. //
  7. import Cocoa
  8. import ComPDFKit
  9. class KMCompressManager: NSObject {
  10. static let shared = KMCompressManager()
  11. func compress(documentURL: URL,
  12. fileURL: URL,
  13. password: String = "",
  14. model: KMCompressSettingModel,
  15. tProgressHandler: (@escaping (Float, Float) -> Void),
  16. tCancelHandler: (@escaping () -> Bool),
  17. tCompletionHandler: (@escaping (Bool) -> Void)) {
  18. DispatchQueue.global().async {
  19. let docuemt = CPDFDocument.init(url: documentURL)
  20. if (docuemt?.isLocked)! && password.count != 0 {
  21. docuemt?.unlock(withPassword: password)
  22. }
  23. self.compress(document: docuemt!,
  24. fileURL: fileURL,
  25. model: model,
  26. tProgressHandler: tProgressHandler,
  27. tCancelHandler: tCancelHandler,
  28. tCompletionHandler: tCompletionHandler)
  29. }
  30. }
  31. func compress(document: CPDFDocument,
  32. fileURL: URL,
  33. model: KMCompressSettingModel,
  34. tProgressHandler: (@escaping (Float, Float) -> Void),
  35. tCancelHandler: (@escaping () -> Bool),
  36. tCompletionHandler: (@escaping (Bool) -> Void)) {
  37. let url = fileURL
  38. // 创建 imageOption 对象
  39. var imageOption = CPDFOptimizeImageOption()
  40. imageOption.uperPpi = Int32(model.ppi);
  41. imageOption.targetPpi = Int32(model.maxPpi);
  42. imageOption.compAlg = .CPDFCOMP_ALG_JPEG2000
  43. imageOption.blockSize = 256
  44. if model.imageQualityType == .hight {
  45. imageOption.quality = 100;
  46. } else if model.imageQualityType == .medium {
  47. imageOption.quality = 60;
  48. } else if model.imageQualityType == .low {
  49. imageOption.quality = 20;
  50. }
  51. // 创建 optimizeFlag
  52. var optimizeFlag: Int = 0
  53. model.objectOptions.contains(.formAndAction) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMFORMCOMMITIMPORTRESETACTION.rawValue) : nil
  54. model.objectOptions.contains(.javaScript) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMJSACTION.rawValue) : nil
  55. model.objectOptions.contains(.thumbnails) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMPAGETHUMBNAIL.rawValue) : nil
  56. model.objectOptions.contains(.documentTags) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMLABEL.rawValue) : nil
  57. model.objectOptions.contains(.bookmarks) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMBK.rawValue) : nil
  58. if model.userDataOptions.contains(.commentsFormAndMultimedia) {
  59. optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMMULMEDIA.rawValue)
  60. optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMFORM.rawValue)
  61. optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMANNOT.rawValue)
  62. }
  63. if model.userDataOptions.contains(.documentInfomationAndMetadata) {
  64. optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMDOCINFO.rawValue)
  65. optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMMEDTADATA.rawValue)
  66. }
  67. model.userDataOptions.contains(.allObject) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMOBJDATA.rawValue) : nil
  68. model.userDataOptions.contains(.fileAttachments) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMFILEATTACHMENT.rawValue) : nil
  69. if model.userDataOptions.contains(.hiddenLayerContentAndFlattenVisibleLayers) {
  70. optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMHIDERLAYER.rawValue)
  71. optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_MERGEVISIBLELAYER.rawValue)
  72. }
  73. model.otherDataOptions.contains(.invalidBookmarks) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMINVABK.rawValue) : nil
  74. model.otherDataOptions.contains(.invalidLinks) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMINVALINK.rawValue) : nil
  75. model.otherDataOptions.contains(.unrefrencedNamedDestinations) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMBK.rawValue) : nil
  76. model.otherDataOptions.contains(.pageContent) ? optimizeFlag |= Int(CPDF_OPTIMIZE_FLAG.CPDFOPTIMIZE_FLAG_RMUNUSEDTARGET.rawValue) : nil
  77. //数据转换
  78. var imageOptionValue: NSValue?
  79. // 使用 `withUnsafeBytes` 获取 UnsafeRawPointer
  80. withUnsafeBytes(of: imageOption) { rawBufferPointer in
  81. guard let baseAddress = rawBufferPointer.baseAddress else {
  82. return
  83. }
  84. // 获取结构体的 Objective-C 类型编码
  85. let objCType = KMCompressTool.encodeForStruct()
  86. // let objCType = "{CPDFOptimizeImageOption=iiiii}"
  87. imageOptionValue = NSValue(bytes: baseAddress, objCType: objCType)
  88. }
  89. // 创建字典
  90. let options: [String: Any] = [
  91. CPDFOptimizeCOLImageOptionKey: imageOptionValue as Any,
  92. CPDFOptimizeFlagKey: NSNumber(value: optimizeFlag)
  93. ]
  94. // 调用方法
  95. document.writeOptimize(to: url, withOptimizeOptions: options,
  96. progressHandler: { (currentPage, totalPages) in
  97. // 进度处理
  98. print("当前页:\(currentPage), 总页数:\(totalPages)")
  99. tProgressHandler(currentPage, totalPages)
  100. },
  101. cancelHandler: {
  102. // 返回是否取消
  103. let shouldCancel = false
  104. return shouldCancel
  105. // return tCancelHandler()
  106. },
  107. completionHandler: { (finished) in
  108. // 完成处理
  109. if finished {
  110. print("优化完成")
  111. } else {
  112. print("优化未完成")
  113. }
  114. tCompletionHandler(finished)
  115. })
  116. }
  117. }