ImageProcess.swift 27 KB

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