|
@@ -0,0 +1,257 @@
|
|
|
+//
|
|
|
+// ImageProcess.swift
|
|
|
+// KdanAuto
|
|
|
+//
|
|
|
+// Created by 朱东勇 on 2023/2/7.
|
|
|
+//
|
|
|
+
|
|
|
+import Foundation
|
|
|
+import AppKit
|
|
|
+
|
|
|
+class ImageProcess : NSObject {
|
|
|
+
|
|
|
+ // Image compare
|
|
|
+ class func compareJPEG(_ resultPath:String, checkPath:String) -> Double {
|
|
|
+ if !FileManager.default.fileExists(atPath: resultPath) || !FileManager.default.fileExists(atPath: checkPath) {
|
|
|
+ return -1
|
|
|
+ }
|
|
|
+
|
|
|
+ let rImage = NSImage.init(contentsOfFile: resultPath) ?? nil
|
|
|
+ let cImage = NSImage.init(contentsOfFile: checkPath) ?? nil
|
|
|
+
|
|
|
+ if nil == rImage || nil == cImage {
|
|
|
+ return -1
|
|
|
+ }
|
|
|
+
|
|
|
+ let resultImage = rImage as! NSImage
|
|
|
+ let checkImage = cImage as! NSImage
|
|
|
+
|
|
|
+ let resultImageRep = NSBitmapImageRep.init(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
|
|
|
+ let checkImageRep = NSBitmapImageRep.init(cgImage: checkImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
|
|
|
+
|
|
|
+ let rWidth = resultImageRep.pixelsWide
|
|
|
+ let rHeight = resultImageRep.pixelsHigh
|
|
|
+ let rBitPerPixel = resultImageRep.bitsPerPixel / 8
|
|
|
+ let rBytePerRow = resultImageRep.bytesPerRow
|
|
|
+
|
|
|
+ let cWidth = checkImageRep.pixelsWide
|
|
|
+ let cHeight = checkImageRep.pixelsHigh
|
|
|
+ let cBitPerPixel = checkImageRep.bitsPerPixel / 8
|
|
|
+ let cBytePerRow = checkImageRep.bytesPerRow
|
|
|
+
|
|
|
+ let maxWidth = min(rWidth, cWidth) - 1
|
|
|
+ let maxHeight = min(rHeight, cHeight) - 1
|
|
|
+
|
|
|
+ // check background color
|
|
|
+ // 挑选图片 对角斜线 上的相素进行识别
|
|
|
+ var markInfo = NSMutableDictionary.init()
|
|
|
+ for w in 0...maxWidth {
|
|
|
+ let x = Int(w)
|
|
|
+ for mark in 0...1 {
|
|
|
+ let color = checkImageRep.colorAt(x: min(x, cWidth-1), y: min(mark == 0 ? x : (maxWidth - x), (cHeight-1))) as! NSColor
|
|
|
+
|
|
|
+ if (markInfo[color] != nil) {
|
|
|
+ let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
|
|
|
+
|
|
|
+ markInfo[color] = NSNumber.init(value: count + 1)
|
|
|
+ }else {
|
|
|
+ markInfo[color] = NSNumber.init(value: 1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var maxCount = Int(0);
|
|
|
+ var bgColor : NSColor? = nil
|
|
|
+ for color in markInfo.allKeys {
|
|
|
+ let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
|
|
|
+
|
|
|
+ if count > maxCount {
|
|
|
+ maxCount = count
|
|
|
+ bgColor = color as! NSColor
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if nil != bgColor {
|
|
|
+ NSLog(String("识别到背景色\(bgColor)"))
|
|
|
+ }
|
|
|
+
|
|
|
+ // Compare
|
|
|
+ let compareDifValue = DataModel.shared.comparativeDifference()
|
|
|
+ var equalCount = 0 as Double
|
|
|
+ var bgCount = 0 as Double
|
|
|
+ for w in 0...maxWidth {
|
|
|
+ let x = Int(w)
|
|
|
+
|
|
|
+ for h in 0...maxHeight {
|
|
|
+ let y = Int(h)
|
|
|
+
|
|
|
+ let cColor = checkImageRep.colorAt(x: x, y: y) as! NSColor
|
|
|
+ let rColor = resultImageRep.colorAt(x: x, y: y) as! NSColor
|
|
|
+
|
|
|
+ let cr = Int(cColor.redComponent*255)
|
|
|
+ let cg = Int(cColor.greenComponent*255)
|
|
|
+ let cb = Int(cColor.blueComponent*255)
|
|
|
+ let ca = Int(cColor.blueComponent*255)
|
|
|
+
|
|
|
+ let rr = Int(rColor.redComponent*255)
|
|
|
+ let rg = Int(rColor.greenComponent*255)
|
|
|
+ let rb = Int(rColor.blueComponent*255)
|
|
|
+ let ra = Int(rColor.blueComponent*255)
|
|
|
+
|
|
|
+// if (cColor.isEqual(to: rColor)) {
|
|
|
+ if (abs(cr - rr) <= compareDifValue &&
|
|
|
+ abs(cg - rg) <= compareDifValue &&
|
|
|
+ abs(cb - rb) <= compareDifValue &&
|
|
|
+ abs(ca - ra) <= compareDifValue) {
|
|
|
+ equalCount = equalCount + 1
|
|
|
+
|
|
|
+ if bgColor != nil &&
|
|
|
+ cColor.isEqual(to: bgColor) {
|
|
|
+ bgCount += 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ NSLog(String("过滤点数目\(bgCount)"))
|
|
|
+
|
|
|
+ return Double(max(equalCount-bgCount, 1)/(max(Double(cWidth) * Double(cHeight)-bgCount, 1)) * 100.0)
|
|
|
+ }
|
|
|
+
|
|
|
+ //Genera Image
|
|
|
+ class func processImage(_ resultPath:String, checkPath:String) -> NSImage? {
|
|
|
+ if !FileManager.default.fileExists(atPath: resultPath) || !FileManager.default.fileExists(atPath: checkPath) {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ let rImage = NSImage.init(contentsOfFile: resultPath) ?? nil
|
|
|
+ let cImage = NSImage.init(contentsOfFile: checkPath) ?? nil
|
|
|
+
|
|
|
+ if nil == rImage || nil == cImage {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ let resultImage = rImage as! NSImage
|
|
|
+ let checkImage = cImage as! NSImage
|
|
|
+
|
|
|
+ let resultImageRep = NSBitmapImageRep.init(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
|
|
|
+ let checkImageRep = NSBitmapImageRep.init(cgImage: checkImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
|
|
|
+
|
|
|
+ let rWidth = resultImageRep.pixelsWide
|
|
|
+ let rHeight = resultImageRep.pixelsHigh
|
|
|
+ let rBitPerPixel = resultImageRep.bitsPerPixel / 8
|
|
|
+ let rBytePerRow = resultImageRep.bytesPerRow
|
|
|
+
|
|
|
+ let cWidth = checkImageRep.pixelsWide
|
|
|
+ let cHeight = checkImageRep.pixelsHigh
|
|
|
+ let cBitPerPixel = checkImageRep.bitsPerPixel / 8
|
|
|
+ let cBytePerRow = checkImageRep.bytesPerRow
|
|
|
+ let data = NSMutableData.init(length: cWidth * cHeight * 4)
|
|
|
+ if nil == data {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ let maxWidth = min(rWidth, cWidth) - 1
|
|
|
+ let maxHeight = min(rHeight, cHeight) - 1
|
|
|
+
|
|
|
+ // check background color
|
|
|
+ // 挑选图片 对角斜线 上的相素进行识别
|
|
|
+ var markInfo = NSMutableDictionary.init()
|
|
|
+ for w in 0...maxWidth {
|
|
|
+ let x = Int(w)
|
|
|
+ for mark in 0...1 {
|
|
|
+ let color = checkImageRep.colorAt(x: min(x, cWidth-1), y: min(mark == 0 ? x : (maxWidth - x), (cHeight-1))) as! NSColor
|
|
|
+
|
|
|
+ if (markInfo[color] != nil) {
|
|
|
+ let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
|
|
|
+
|
|
|
+ markInfo[color] = NSNumber.init(value: count + 1)
|
|
|
+ }else {
|
|
|
+ markInfo[color] = NSNumber.init(value: 1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var maxCount = Int(0);
|
|
|
+ var bgColor : NSColor? = nil
|
|
|
+ for color in markInfo.allKeys {
|
|
|
+ let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
|
|
|
+
|
|
|
+ if count > maxCount {
|
|
|
+ maxCount = count
|
|
|
+ bgColor = color as! NSColor
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if nil != bgColor {
|
|
|
+ NSLog(String("识别到背景色\(bgColor)"))
|
|
|
+ }
|
|
|
+
|
|
|
+ // Compare
|
|
|
+ let compareDifValue = DataModel.shared.comparativeDifference()
|
|
|
+ for w in 0...maxWidth {
|
|
|
+ let x = Int(w)
|
|
|
+
|
|
|
+ for h in 0...maxHeight {
|
|
|
+ let y = Int(h)
|
|
|
+
|
|
|
+ let cColor = checkImageRep.colorAt(x: x, y: y) as! NSColor
|
|
|
+ let rColor = resultImageRep.colorAt(x: x, y: y) as! NSColor
|
|
|
+
|
|
|
+ let cr = Int(cColor.redComponent*255)
|
|
|
+ let cg = Int(cColor.greenComponent*255)
|
|
|
+ let cb = Int(cColor.blueComponent*255)
|
|
|
+ let ca = Int(cColor.blueComponent*255)
|
|
|
+
|
|
|
+ let rr = Int(rColor.redComponent*255)
|
|
|
+ let rg = Int(rColor.greenComponent*255)
|
|
|
+ let rb = Int(rColor.blueComponent*255)
|
|
|
+ let ra = Int(rColor.blueComponent*255)
|
|
|
+
|
|
|
+ // if (cColor.isEqual(to: rColor)) {
|
|
|
+ if (abs(cr - rr) <= compareDifValue &&
|
|
|
+ abs(cg - rg) <= compareDifValue &&
|
|
|
+ abs(cb - rb) <= compareDifValue &&
|
|
|
+ abs(ca - ra) <= compareDifValue) {
|
|
|
+ if bgColor != nil &&
|
|
|
+ cColor.isEqual(to: bgColor) {
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+// NSLog("(\(cr),\(cg),\(cb),\(cr))=(\(rr),\(rg),\(rb),\(rr))")
|
|
|
+ let addr = cWidth * 4 * y + x * 4
|
|
|
+
|
|
|
+ var r = uint8(255)
|
|
|
+ data!.replaceBytes(in: NSRange.init(location: addr+0, length: 1), withBytes: &r)
|
|
|
+ var g = uint8(255 * rColor.greenComponent/2)
|
|
|
+ data!.replaceBytes(in: NSRange.init(location: addr+1, length: 1), withBytes: &g)
|
|
|
+ var b = uint8(255 * rColor.blueComponent/2)
|
|
|
+ data!.replaceBytes(in: NSRange.init(location: addr+2, length: 1), withBytes: &b)
|
|
|
+ var a = uint8(255 * rColor.alphaComponent * 0.7)
|
|
|
+ data!.replaceBytes(in: NSRange.init(location: addr+3, length: 1), withBytes: &a)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let cfData = CFDataCreate(kCFAllocatorDefault, data?.bytes, data!.length)
|
|
|
+ let dataProvider = CGDataProvider.init(data: cfData!)
|
|
|
+
|
|
|
+ let colorSpace = CGColorSpaceCreateDeviceRGB()
|
|
|
+ let cgImage = CGImage.init(width: cWidth,
|
|
|
+ height: cHeight,
|
|
|
+ bitsPerComponent: 8,
|
|
|
+ bitsPerPixel: 8 * 4,
|
|
|
+ bytesPerRow: cWidth * 4,
|
|
|
+ space: colorSpace,
|
|
|
+ bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrderDefault.rawValue) ?? CGBitmapInfo.byteOrderDefault,
|
|
|
+ provider: dataProvider!,
|
|
|
+ decode: nil,
|
|
|
+ shouldInterpolate: true,
|
|
|
+ intent: CGColorRenderingIntent.defaultIntent)
|
|
|
+
|
|
|
+ if nil != cgImage {
|
|
|
+ return NSImage.init(cgImage: cgImage!, size: NSSize.init(width: cWidth, height: cHeight))
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+}
|