Ios CIImage应该是相等的吗?

Ios CIImage应该是相等的吗?,ios,swift,core-image,ciimage,equatable,Ios,Swift,Core Image,Ciimage,Equatable,因此,苹果的文档表明,CIImage符合equalable。我认为这意味着下面的单元测试将通过。然而,事实并非如此。我对为什么感兴趣 func test_CIImageEqualityShouldWork() { let bundle = NSBundle(forClass: PrototypeTests.self) guard let path = bundle.pathForResource("testImage", ofType: "png") else { return

因此,苹果的文档表明,
CIImage
符合
equalable
。我认为这意味着下面的单元测试将通过。然而,事实并非如此。我对为什么感兴趣

func test_CIImageEqualityShouldWork() {
    let bundle = NSBundle(forClass: PrototypeTests.self)
    guard let path = bundle.pathForResource("testImage", ofType: "png") else { return }
    guard let image = UIImage(contentsOfFile: path) else { return }

    let thingy1 = CIImage(image: image)
    let thingy2 = CIImage(image: image)
    XCTAssert(thingy1 == thingy2)
}
映像存在,
guard
语句都通过,但断言失败,它们不相等


出于兴趣,我已经尝试创建了两次
UIImage
,并对它们进行了比较。这也失败了。

所有
NSObject
子类都符合
equalable
,并且
=
函数 对对象调用
isEqual:
方法。
isEqual:
方法 of
NSObject
只是比较对象指针,即
o1==o2
如果
o1
o2
引用同一对象实例,则保持该状态

例如,见 :

Swift提供==和===运算符和的默认实现 对从 NSObject类。==运算符的默认实现调用 方法,以及=== 运算符检查指针是否相等。你不应该忽略这个等式 或从Objective-C导入的类型的标识运算符

isEqual的基本实现:由NSObject类提供 相当于指针相等的身份检查

许多
NSObject
子类重写
isEqual:
方法(例如
NSString
NSArray
NSDate
,…)但不是
CIImage

let thingy1 = CIImage(image: image)
let thingy2 = CIImage(image: image)

创建两个不同的
CIImage
实例,并将它们比较为“不相等”。

所有
NSObject
子类都符合
equalable
,并且
=
函数 对对象调用
isEqual:
方法。
isEqual:
方法 of
NSObject
只是比较对象指针,即
o1==o2
如果
o1
o2
引用同一对象实例,则保持该状态

例如,见 :

Swift提供==和===运算符和的默认实现 对从 NSObject类。==运算符的默认实现调用 方法,以及=== 运算符检查指针是否相等。你不应该忽略这个等式 或从Objective-C导入的类型的标识运算符

isEqual的基本实现:由NSObject类提供 相当于指针相等的身份检查

许多
NSObject
子类重写
isEqual:
方法(例如
NSString
NSArray
NSDate
,…)但不是
CIImage

let thingy1 = CIImage(image: image)
let thingy2 = CIImage(image: image)

创建两个不同的<代码> CIImage < /Cl>实例,这些比较为“不相等”。< /P> < P> FractMeX是脸谱网从C++到SWIFT的不完整端口。它省略了每像素比较的最后一部分。我的是Swift 4,以下是整个功能:

static func compareWithImage(reference:CGImage, target:CGImage, tolerance:CGFloat) -> Bool {
    guard reference.width == target.width && reference.height == target.height else { return false }
    let referenceImageSize = CGSize(width:CGFloat(reference.width), height:CGFloat(reference.height))
    let targetImageSize = CGSize(width:CGFloat(target.width), height:CGFloat(target.height))
    let minBytesPerRow = min(reference.bytesPerRow, target.bytesPerRow)
    let referenceImageSizeBytes = Int(referenceImageSize.height) * minBytesPerRow
    let referenceImagePixels = calloc(1, referenceImageSizeBytes)
    let targetImagePixels = calloc(1, referenceImageSizeBytes)
    let referenceImageCtx = CGContext(data: referenceImagePixels,
                                      width: Int(referenceImageSize.width),
                                      height: Int(referenceImageSize.height),
                                      bitsPerComponent: reference.bitsPerComponent,
                                      bytesPerRow: minBytesPerRow,
                                      space: reference.colorSpace!,
                                      bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
    let targetImageCtx = CGContext(data: targetImagePixels,
                                   width: Int(targetImageSize.width),
                                   height: Int(targetImageSize.height),
                                   bitsPerComponent: target.bitsPerComponent,
                                   bytesPerRow: minBytesPerRow,
                                   space: target.colorSpace!,
                                   bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
    guard let referenceImageContext = referenceImageCtx, let targetImageContext = targetImageCtx else {
        return false
    }
    referenceImageContext.draw(reference, in:CGRect(x:0, y:0, width:referenceImageSize.width, height:referenceImageSize.height))
    targetImageContext.draw(target, in:CGRect(x:0, y:0, width:targetImageSize.width, height:targetImageSize.height))
    var imageEqual = true
    if(tolerance == 0) {
        imageEqual =  (memcmp(referenceImagePixels, targetImagePixels, referenceImageSizeBytes) == 0)
    } else {
        let pixelCount = Int(referenceImageSize.width * referenceImageSize.height)

        let p1 = convertUMRPtoUInt32Array(pointer:referenceImagePixels!, length:referenceImageSizeBytes)
        let p2 = convertUMRPtoUInt32Array(pointer:targetImagePixels!, length:referenceImageSizeBytes)
        var percent:CGFloat = 0
        var numDiffPixels = 0
        for n in 0..<pixelCount {
            if(p1[n] != p2[n]) {
                numDiffPixels += 1
                percent = CGFloat(numDiffPixels) / CGFloat(pixelCount)
                if (percent > tolerance) {
                    imageEqual = false;
                    break;
                }
            }
        }
        //print(percent)
    }
    referenceImagePixels?.deallocate(bytes:referenceImageSizeBytes, alignedTo:1)
    targetImagePixels?.deallocate(bytes: referenceImageSizeBytes, alignedTo: 1)
    return imageEqual
}
static func compareWithImage(参考:CGImage,目标:CGImage,容差:CGFloat)->Bool{
guard reference.width==target.width&&reference.height==target.height else{return false}
让referenceImageSize=CGSize(宽度:CGFloat(reference.width),高度:CGFloat(reference.height))
设targetImageSize=CGSize(宽度:CGFloat(target.width),高度:CGFloat(target.height))
让minBytesPerRow=min(reference.bytesPerRow,target.bytesPerRow)
让referenceImageSizeBytes=Int(referenceImageSize.height)*minBytesPerRow
让referenceImagePixels=calloc(1,referenceImageSizeBytes)
让targetImagePixels=calloc(1,referenceImageSizeBytes)
让referenceImageCtx=CGContext(数据:referenceImagePixels,
宽度:Int(referenceImageSize.width),
高度:Int(referenceImageSize.height),
bitsPerComponent:reference.bitsPerComponent,
bytesPerRow:minBytesPerRow,
空格:引用。颜色空格!,
bitmapInfo:CGImageAlphaInfo.PremultipledLast.rawValue)
设targetImageCtx=CGContext(数据:targetImagePixels,
宽度:Int(targetImageSize.width),
高度:Int(targetImageSize.height),
bitsPerComponent:target.bitsPerComponent,
bytesPerRow:minBytesPerRow,
空间:目标。颜色空间!,
bitmapInfo:CGImageAlphaInfo.PremultipledLast.rawValue)
保护let referenceImageContext=referenceImageCtx,让targetImageContext=targetImageCtx else{
返回错误
}
绘制(引用,in:CGRect(x:0,y:0,宽度:referenceImageSize.width,高度:referenceImageSize.height))
绘制(目标,in:CGRect(x:0,y:0,宽度:targetImageSize.width,高度:targetImageSize.height))
var imageEqual=true
如果(公差==0){
imageEqual=(memcmp(referenceImagePixels、targetImagePixels、referenceImageSizeBytes)==0)
}否则{
让pixelCount=Int(referenceImageSize.width*referenceImageSize.height)
设p1=convertUMRPtoUInt32Array(指针:referenceImagePixels!,长度:referenceImageSizeBytes)
设p2=convertUMRPtoUInt32Array(指针:targetImagePixels!,长度:referenceImageSizeBytes)
变量百分比:CGFloat=0
var numDiffPixels=0
对于0.公差中的n){
imageEqual=false;
打破
}
}
}
//打印(百分比)
}
referenceImagePixels?解除分配(字节:referenceImageSizeBytes,对齐到:1)
塔格