ImageProcess.swift 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. //
  2. // ImageProcess.swift
  3. // KdanAuto
  4. //
  5. // Created by 朱东勇 on 2023/2/7.
  6. //
  7. import Foundation
  8. import AppKit
  9. import CoreImage
  10. import CryptoKit
  11. class ImageProcess : NSObject {
  12. // Image compare
  13. class func compareJPEG(_ resultPath:String, checkPath:String, processCover:Bool) -> Double {
  14. autoreleasepool {
  15. if !FileManager.default.fileExists(atPath: resultPath) || !FileManager.default.fileExists(atPath: checkPath) {
  16. return -1
  17. }
  18. let rImage = NSImage.init(contentsOfFile: resultPath) ?? nil
  19. let cImage = NSImage.init(contentsOfFile: checkPath) ?? nil
  20. if nil == rImage || nil == cImage {
  21. return -1
  22. }
  23. let resultImage = rImage!
  24. let checkImage = cImage!
  25. var resultImageRep = NSBitmapImageRep.init(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
  26. let checkImageRep = NSBitmapImageRep.init(cgImage: checkImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
  27. var rWidth = resultImageRep.pixelsWide
  28. var rHeight = resultImageRep.pixelsHigh
  29. // let rBitPerPixel = resultImageRep.bitsPerPixel / 8
  30. // let rBytePerRow = resultImageRep.bytesPerRow
  31. let cWidth = checkImageRep.pixelsWide
  32. let cHeight = checkImageRep.pixelsHigh
  33. // let cBitPerPixel = checkImageRep.bitsPerPixel / 8
  34. // let cBytePerRow = checkImageRep.bytesPerRow
  35. // 图像为等比例、且长宽比相同
  36. if rHeight*cHeight > 0 &&
  37. fabs(Double(rWidth-cWidth)) > 1 &&
  38. fabs(Double(rWidth)/Double(rHeight) - Double(cWidth)/Double(cHeight)) < 0.001 {
  39. var ciImage = CIImage(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
  40. ciImage = ciImage.transformed(by: CGAffineTransformMakeScale(Double(cWidth)/Double(rWidth), Double(cHeight)/Double(rHeight)))
  41. let context = CIContext()
  42. let cgImage = context.createCGImage(ciImage, from: ciImage.extent)
  43. if cgImage != nil {
  44. resultImageRep = NSBitmapImageRep(cgImage: cgImage!);
  45. rWidth = resultImageRep.pixelsWide
  46. rHeight = resultImageRep.pixelsHigh
  47. }
  48. }
  49. let maxWidth = min(rWidth, cWidth) - 1
  50. let maxHeight = min(rHeight, cHeight) - 1
  51. // check background color
  52. // 挑选图片 对角斜线 上的相素进行识别
  53. let markInfo = NSMutableDictionary.init()
  54. for w in 0...maxWidth {
  55. let x = Int(w)
  56. for mark in 0...1 {
  57. let color = checkImageRep.colorAt(x: min(x, cWidth-1), y: min(mark == 0 ? x : (maxWidth - x), (cHeight-1))) as! NSColor
  58. if (markInfo[color] != nil) {
  59. let count = (markInfo[color] as? NSNumber)!.intValue
  60. markInfo[color] = NSNumber.init(value: count + 1)
  61. }else {
  62. markInfo[color] = NSNumber.init(value: 1)
  63. }
  64. }
  65. }
  66. var maxCount = Int(0);
  67. var bgColor : NSColor = NSColor.clear
  68. for color in markInfo.allKeys {
  69. let count = (markInfo[color] as? NSNumber)!.intValue
  70. if count > maxCount {
  71. maxCount = count
  72. bgColor = color as! NSColor
  73. }
  74. }
  75. // if nil != bgColor {
  76. // NSLog(String("识别到背景色\(bgColor)"))
  77. // }
  78. // let bg_r = Int(bgColor.redComponent*255);
  79. // let bg_g = Int(bgColor.redComponent*255);
  80. // let bg_b = Int(bgColor.redComponent*255);
  81. // let bg_a = Int(bgColor.redComponent*255);
  82. //
  83. let data = NSMutableData.init(length: cWidth * cHeight * 4)
  84. // Compare
  85. let compareDifValue = DataModel.shared.comparativeDifference()
  86. var equalCount = 0 as Double
  87. var bgCount = 0 as Double
  88. let semaphore = DispatchSemaphore(value: 0)
  89. let operateQueue = OperationQueue()
  90. operateQueue.maxConcurrentOperationCount = 20;
  91. var processCount = Int(0)
  92. for w in 0...maxWidth {
  93. let x = Int(w)
  94. operateQueue.addOperation {
  95. autoreleasepool {
  96. for h in 0...maxHeight {
  97. let y = Int(h)
  98. objc_sync_enter(self)
  99. let cColor = checkImageRep.colorAt(x: x, y: y) as! NSColor
  100. let rColor = resultImageRep.colorAt(x: x, y: y) as! NSColor
  101. objc_sync_exit(self)
  102. let cr = Int(cColor.redComponent*255)
  103. let cg = Int(cColor.greenComponent*255)
  104. let cb = Int(cColor.blueComponent*255)
  105. let ca = Int(cColor.blueComponent*255)
  106. let rr = Int(rColor.redComponent*255)
  107. let rg = Int(rColor.greenComponent*255)
  108. let rb = Int(rColor.blueComponent*255)
  109. let ra = Int(rColor.blueComponent*255)
  110. // if (cColor.isEqual(to: rColor)) {
  111. if (abs(cr - rr) <= compareDifValue &&
  112. abs(cg - rg) <= compareDifValue &&
  113. abs(cb - rb) <= compareDifValue &&
  114. abs(ca - ra) <= compareDifValue) {
  115. equalCount = equalCount + 1
  116. if cColor.isEqual(to: bgColor) {
  117. objc_sync_enter(self)
  118. bgCount += 1
  119. objc_sync_exit(self)
  120. }
  121. }else if (processCover && nil != data){
  122. let addr = cWidth * 4 * y + x * 4
  123. objc_sync_enter(self)
  124. var r = uint8(255)
  125. data!.replaceBytes(in: NSRange.init(location: addr+0, length: 1), withBytes: &r)
  126. var g = uint8(255 * rColor.greenComponent/2)
  127. data!.replaceBytes(in: NSRange.init(location: addr+1, length: 1), withBytes: &g)
  128. var b = uint8(255 * rColor.blueComponent/2)
  129. data!.replaceBytes(in: NSRange.init(location: addr+2, length: 1), withBytes: &b)
  130. var a = uint8(255 * rColor.alphaComponent * 0.7)
  131. data!.replaceBytes(in: NSRange.init(location: addr+3, length: 1), withBytes: &a)
  132. objc_sync_exit(self)
  133. }
  134. }
  135. processCount = processCount+1
  136. if (processCount >= maxWidth) {
  137. semaphore.signal()
  138. }
  139. }
  140. }
  141. }
  142. semaphore.wait()
  143. let outDegree = Double(max(equalCount-bgCount, 1)/(max(Double(cWidth) * Double(cHeight)-bgCount, 1)) * 100.0)
  144. if (abs(outDegree - 100) > 0 && processCover && nil != data) {
  145. DispatchQueue.global().async {
  146. autoreleasepool {
  147. let cfData = CFDataCreate(kCFAllocatorDefault, data?.bytes, data!.length)
  148. let dataProvider = CGDataProvider.init(data: cfData!)
  149. let colorSpace = CGColorSpaceCreateDeviceRGB()
  150. let cgImage = CGImage.init(width: cWidth,
  151. height: cHeight,
  152. bitsPerComponent: 8,
  153. bitsPerPixel: 8 * 4,
  154. bytesPerRow: cWidth * 4,
  155. space: colorSpace,
  156. bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrderDefault.rawValue) ?? CGBitmapInfo.byteOrderDefault,
  157. provider: dataProvider!,
  158. decode: nil,
  159. shouldInterpolate: true,
  160. intent: CGColorRenderingIntent.defaultIntent)
  161. if nil != cgImage {
  162. let coverPath = NSString(format: "%@_cover.png", NSString(string: resultPath).deletingPathExtension) as! String
  163. let rep = NSBitmapImageRep.init(cgImage: cgImage!)
  164. if let saveData = rep.representation(using: .png, properties: [:]) {
  165. let url = URL.init(fileURLWithPath: coverPath, isDirectory: false)
  166. try? saveData.write(to: url)
  167. }
  168. }
  169. }
  170. }
  171. }
  172. NSLog(String("过滤点数目\(bgCount)"))
  173. return outDegree
  174. }
  175. }
  176. class func compareJPEG(_ resultPath:String, checkPath:String, processCover:Bool, complention:@escaping (_ degree:Double) -> ()) {
  177. autoreleasepool {
  178. if !FileManager.default.fileExists(atPath: resultPath) || !FileManager.default.fileExists(atPath: checkPath) {
  179. complention(-1)
  180. return
  181. }
  182. let rImage = NSImage.init(contentsOfFile: resultPath) ?? nil
  183. let cImage = NSImage.init(contentsOfFile: checkPath) ?? nil
  184. if nil == rImage || nil == cImage {
  185. complention(-1)
  186. return
  187. }
  188. if (ImageProcess.checkEqualFor(resultPath, checkPath: checkPath)) {
  189. complention(100)
  190. return
  191. }
  192. let resultImage = rImage!
  193. let checkImage = cImage!
  194. var resultImageRep = NSBitmapImageRep.init(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
  195. let checkImageRep = NSBitmapImageRep.init(cgImage: checkImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
  196. var rWidth = resultImageRep.pixelsWide
  197. var rHeight = resultImageRep.pixelsHigh
  198. // let rBitPerPixel = resultImageRep.bitsPerPixel / 8
  199. // let rBytePerRow = resultImageRep.bytesPerRow
  200. let cWidth = checkImageRep.pixelsWide
  201. let cHeight = checkImageRep.pixelsHigh
  202. // let cBitPerPixel = checkImageRep.bitsPerPixel / 8
  203. // let cBytePerRow = checkImageRep.bytesPerRow
  204. // 图像为等比例、且长宽比相同
  205. if rHeight*cHeight > 0 &&
  206. fabs(Double(rWidth-cWidth)) > 1 &&
  207. fabs(Double(rWidth)/Double(rHeight) - Double(cWidth)/Double(cHeight)) < 0.001 {
  208. var ciImage = CIImage(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
  209. ciImage = ciImage.transformed(by: CGAffineTransformMakeScale(Double(cWidth)/Double(rWidth), Double(cHeight)/Double(rHeight)))
  210. let context = CIContext()
  211. let cgImage = context.createCGImage(ciImage, from: ciImage.extent)
  212. if cgImage != nil {
  213. resultImageRep = NSBitmapImageRep(cgImage: cgImage!);
  214. rWidth = resultImageRep.pixelsWide
  215. rHeight = resultImageRep.pixelsHigh
  216. }
  217. }
  218. let maxWidth = min(rWidth, cWidth) - 1
  219. let maxHeight = min(rHeight, cHeight) - 1
  220. if (maxWidth == 0 || maxHeight == 0) {
  221. complention(-1)
  222. return
  223. }
  224. // check background color
  225. // 挑选图片 对角斜线 上的相素进行识别
  226. let markInfo = NSMutableDictionary.init()
  227. for w in 0...maxWidth {
  228. let x = Int(w)
  229. for mark in 0...1 {
  230. let color = checkImageRep.colorAt(x: min(x, cWidth-1), y: min(mark == 0 ? x : (maxWidth - x), (cHeight-1))) as! NSColor
  231. if (markInfo[color] != nil) {
  232. let count = (markInfo[color] as? NSNumber)!.intValue
  233. markInfo[color] = NSNumber.init(value: count + 1)
  234. }else {
  235. markInfo[color] = NSNumber.init(value: 1)
  236. }
  237. }
  238. }
  239. var maxCount = Int(0);
  240. var bgColor : NSColor = NSColor.clear
  241. for color in markInfo.allKeys {
  242. let count = (markInfo[color] as? NSNumber)!.intValue
  243. if count > maxCount {
  244. maxCount = count
  245. bgColor = color as! NSColor
  246. }
  247. }
  248. // if nil != bgColor {
  249. // NSLog(String("识别到背景色\(bgColor)"))
  250. // }
  251. // let bg_r = Int(bgColor.redComponent*255);
  252. // let bg_g = Int(bgColor.redComponent*255);
  253. // let bg_b = Int(bgColor.redComponent*255);
  254. // let bg_a = Int(bgColor.redComponent*255);
  255. //
  256. let data = NSMutableData.init(length: cWidth * cHeight * 4)
  257. // Compare
  258. let compareDifValue = DataModel.shared.comparativeDifference()
  259. var equalCount = 0 as Double
  260. var bgCount = 0 as Double
  261. var processCount = Int(0)
  262. for w in 0...maxWidth {
  263. let x = Int(w)
  264. for h in 0...maxHeight {
  265. let y = Int(h)
  266. let cColor = checkImageRep.colorAt(x: x, y: y) as! NSColor
  267. let rColor = resultImageRep.colorAt(x: x, y: y) as! NSColor
  268. let cr = Int(cColor.redComponent*255)
  269. let cg = Int(cColor.greenComponent*255)
  270. let cb = Int(cColor.blueComponent*255)
  271. let ca = Int(cColor.blueComponent*255)
  272. let rr = Int(rColor.redComponent*255)
  273. let rg = Int(rColor.greenComponent*255)
  274. let rb = Int(rColor.blueComponent*255)
  275. let ra = Int(rColor.blueComponent*255)
  276. // if (cColor.isEqual(to: rColor)) {
  277. if (abs(cr - rr) <= compareDifValue &&
  278. abs(cg - rg) <= compareDifValue &&
  279. abs(cb - rb) <= compareDifValue &&
  280. abs(ca - ra) <= compareDifValue) {
  281. equalCount = equalCount + 1
  282. if cColor.isEqual(to: bgColor) {
  283. bgCount += 1
  284. }
  285. }else if (processCover && nil != data){
  286. let addr = cWidth * 4 * y + x * 4
  287. var r = uint8(255)
  288. data!.replaceBytes(in: NSRange.init(location: addr+0, length: 1), withBytes: &r)
  289. var g = uint8(255 * rColor.greenComponent/2)
  290. data!.replaceBytes(in: NSRange.init(location: addr+1, length: 1), withBytes: &g)
  291. var b = uint8(255 * rColor.blueComponent/2)
  292. data!.replaceBytes(in: NSRange.init(location: addr+2, length: 1), withBytes: &b)
  293. var a = uint8(255 * rColor.alphaComponent * 0.7)
  294. data!.replaceBytes(in: NSRange.init(location: addr+3, length: 1), withBytes: &a)
  295. }
  296. }
  297. }
  298. let outDegree = Double(max(equalCount-bgCount, 1)/(max(Double(cWidth) * Double(cHeight)-bgCount, 1)) * 100.0)
  299. if (abs(outDegree - 100) > 0 && processCover && nil != data) {
  300. DispatchQueue.global().async {
  301. autoreleasepool {
  302. let cfData = CFDataCreate(kCFAllocatorDefault, data?.bytes, data!.length)
  303. let dataProvider = CGDataProvider.init(data: cfData!)
  304. let colorSpace = CGColorSpaceCreateDeviceRGB()
  305. let cgImage = CGImage.init(width: cWidth,
  306. height: cHeight,
  307. bitsPerComponent: 8,
  308. bitsPerPixel: 8 * 4,
  309. bytesPerRow: cWidth * 4,
  310. space: colorSpace,
  311. bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrderDefault.rawValue) ?? CGBitmapInfo.byteOrderDefault,
  312. provider: dataProvider!,
  313. decode: nil,
  314. shouldInterpolate: true,
  315. intent: CGColorRenderingIntent.defaultIntent)
  316. if nil != cgImage {
  317. let coverPath = NSString(format: "%@_cover.png", NSString(string: resultPath).deletingPathExtension) as! String
  318. let rep = NSBitmapImageRep.init(cgImage: cgImage!)
  319. if let saveData = rep.representation(using: .png, properties: [:]) {
  320. let url = URL.init(fileURLWithPath: coverPath, isDirectory: false)
  321. try? saveData.write(to: url)
  322. }
  323. }
  324. }
  325. }
  326. }
  327. DispatchQueue.global().async {
  328. autoreleasepool {
  329. NSLog(String("过滤点数目\(bgCount)"))
  330. complention(outDegree)
  331. }
  332. }
  333. }
  334. }
  335. //Genera Image
  336. class func processImage(_ resultPath:String, checkPath:String) -> NSImage? {
  337. autoreleasepool {
  338. if !FileManager.default.fileExists(atPath: resultPath) || !FileManager.default.fileExists(atPath: checkPath) {
  339. return nil
  340. }
  341. let rImage = NSImage.init(contentsOfFile: resultPath) ?? nil
  342. let cImage = NSImage.init(contentsOfFile: checkPath) ?? nil
  343. if nil == rImage || nil == cImage {
  344. return nil
  345. }
  346. if (ImageProcess.checkEqualFor(resultPath, checkPath: checkPath)) {
  347. return nil
  348. }
  349. let resultImage = rImage as! NSImage
  350. let checkImage = cImage as! NSImage
  351. let resultImageRep = NSBitmapImageRep.init(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
  352. let checkImageRep = NSBitmapImageRep.init(cgImage: checkImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
  353. let rWidth = resultImageRep.pixelsWide
  354. let rHeight = resultImageRep.pixelsHigh
  355. let rBitPerPixel = resultImageRep.bitsPerPixel / 8
  356. let rBytePerRow = resultImageRep.bytesPerRow
  357. let cWidth = checkImageRep.pixelsWide
  358. let cHeight = checkImageRep.pixelsHigh
  359. let cBitPerPixel = checkImageRep.bitsPerPixel / 8
  360. let cBytePerRow = checkImageRep.bytesPerRow
  361. let data = NSMutableData.init(length: cWidth * cHeight * 4)
  362. if nil == data {
  363. return nil
  364. }
  365. let maxWidth = min(rWidth, cWidth) - 1
  366. let maxHeight = min(rHeight, cHeight) - 1
  367. // check background color
  368. // 挑选图片 对角斜线 上的相素进行识别
  369. var markInfo = NSMutableDictionary.init()
  370. for w in 0...maxWidth {
  371. let x = Int(w)
  372. for mark in 0...1 {
  373. let color = checkImageRep.colorAt(x: min(x, cWidth-1), y: min(mark == 0 ? x : (maxWidth - x), (cHeight-1))) as! NSColor
  374. if (markInfo[color] != nil) {
  375. let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
  376. markInfo[color] = NSNumber.init(value: count + 1)
  377. }else {
  378. markInfo[color] = NSNumber.init(value: 1)
  379. }
  380. }
  381. }
  382. var maxCount = Int(0);
  383. var bgColor : NSColor? = nil
  384. for color in markInfo.allKeys {
  385. let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
  386. if count > maxCount {
  387. maxCount = count
  388. bgColor = color as! NSColor
  389. }
  390. }
  391. if nil != bgColor {
  392. NSLog(String("识别到背景色\(bgColor)"))
  393. }
  394. // Compare
  395. let compareDifValue = DataModel.shared.comparativeDifference()
  396. for w in 0...maxWidth {
  397. let x = Int(w)
  398. for h in 0...maxHeight {
  399. let y = Int(h)
  400. let cColor = checkImageRep.colorAt(x: x, y: y) as! NSColor
  401. let rColor = resultImageRep.colorAt(x: x, y: y) as! NSColor
  402. let cr = Int(cColor.redComponent*255)
  403. let cg = Int(cColor.greenComponent*255)
  404. let cb = Int(cColor.blueComponent*255)
  405. let ca = Int(cColor.blueComponent*255)
  406. let rr = Int(rColor.redComponent*255)
  407. let rg = Int(rColor.greenComponent*255)
  408. let rb = Int(rColor.blueComponent*255)
  409. let ra = Int(rColor.blueComponent*255)
  410. // if (cColor.isEqual(to: rColor)) {
  411. if (abs(cr - rr) <= compareDifValue &&
  412. abs(cg - rg) <= compareDifValue &&
  413. abs(cb - rb) <= compareDifValue &&
  414. abs(ca - ra) <= compareDifValue) {
  415. if bgColor != nil &&
  416. cColor.isEqual(to: bgColor) {
  417. }
  418. }else {
  419. // NSLog("(\(cr),\(cg),\(cb),\(cr))=(\(rr),\(rg),\(rb),\(rr))")
  420. let addr = cWidth * 4 * y + x * 4
  421. var r = uint8(255)
  422. data!.replaceBytes(in: NSRange.init(location: addr+0, length: 1), withBytes: &r)
  423. var g = uint8(255 * rColor.greenComponent/2)
  424. data!.replaceBytes(in: NSRange.init(location: addr+1, length: 1), withBytes: &g)
  425. var b = uint8(255 * rColor.blueComponent/2)
  426. data!.replaceBytes(in: NSRange.init(location: addr+2, length: 1), withBytes: &b)
  427. var a = uint8(255 * rColor.alphaComponent * 0.7)
  428. data!.replaceBytes(in: NSRange.init(location: addr+3, length: 1), withBytes: &a)
  429. }
  430. }
  431. }
  432. let cfData = CFDataCreate(kCFAllocatorDefault, data?.bytes, data!.length)
  433. let dataProvider = CGDataProvider.init(data: cfData!)
  434. let colorSpace = CGColorSpaceCreateDeviceRGB()
  435. let cgImage = CGImage.init(width: cWidth,
  436. height: cHeight,
  437. bitsPerComponent: 8,
  438. bitsPerPixel: 8 * 4,
  439. bytesPerRow: cWidth * 4,
  440. space: colorSpace,
  441. bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrderDefault.rawValue) ?? CGBitmapInfo.byteOrderDefault,
  442. provider: dataProvider!,
  443. decode: nil,
  444. shouldInterpolate: true,
  445. intent: CGColorRenderingIntent.defaultIntent)
  446. if nil != cgImage {
  447. return NSImage.init(cgImage: cgImage!, size: NSSize.init(width: cWidth, height: cHeight))
  448. }
  449. return nil
  450. }
  451. }
  452. class func checkEqualFor(_ resultPath:String, checkPath:String) -> Bool {
  453. // 先通过文件属性 + MD5 码进行快速对比,排除大部分,已经相同的文件
  454. let rfs = try! FileManager.default.attributesOfItem(atPath: resultPath)[FileAttributeKey.size] as! NSNumber
  455. let cfs = try! FileManager.default.attributesOfItem(atPath: checkPath)[FileAttributeKey.size] as! NSNumber
  456. if rfs.int64Value != cfs.int64Value {
  457. //文件大小不一致,反回不一致
  458. return false
  459. }
  460. let rmd5 = ImageProcess.md5StringOfPath(resultPath);
  461. let cmd5 = ImageProcess.md5StringOfPath(checkPath);
  462. if (nil != rmd5 && nil != cmd5 &&
  463. NSString(string: rmd5!).isEqual(to: cmd5!)) {
  464. // 文件大小一致,且文件 MD5码完全一致
  465. return true;
  466. }
  467. return false
  468. }
  469. class func md5StringOfPath(_ path:String) -> String? {
  470. if FileManager.default.fileExists(atPath: path) {
  471. let data = NSData(contentsOfFile: path);
  472. if (nil == data) {
  473. return nil;
  474. }
  475. return String(format: "%X", data.hashValue);
  476. }
  477. return nil;
  478. }
  479. }