2016-07-25 3 views
0

그래서 Apple 설명서에 CIImageEquatable을 준수한다고 나와 있습니다. 나는 다음과 같은 단위 테스트가 통과한다는 것을 의미 할 것이다. 그러나 그렇지 않습니다. 나는 왜 그런지에 관심이있다. 그들은 동일하지,CIImage를 동등해야합니까?

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을 두 번 생성하여 비교해 보았습니다. 그것은 또한 실패합니다.

답변

2

모든 NSObject 서브 클래스는 Equatable을 준수하고, == 기능은 객체에 isEqual: 메소드를 호출 . NSObject의 단순히 오브젝트 포인터를 비교 isEqual: 방법, 즉 o1 == o2o1o2가 동일한 객체 인스턴스를 참조하는 경우 을 보유하고있다.

예를 Interacting with Objective-C APIs를 참조하십시오 :

스위프트는 ==의 기본 구현을 제공하고 === 연산자와 는 NSObject의 클래스에서 파생 객체에 대한 Equatable 프로토콜을 채택한다. == 연산자의 기본 구현은 isEqual : 메서드를 호출하고 === 연산자의 기본 구현은 포인터 동일성을 확인합니다. Objective-C에서 가져온 유형에 대해서는 동일성 또는 ID 연산자를 재정의해서는 안됩니다.

NSObject 클래스 에 의해 제공되는 isEqual :의 기본 구현은 포인터 동일성에 의한 신원 확인과 같습니다.

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

두 개의 서로 다른 CIImage 인스턴스를 생성하고 이러한 "동일하지"로 비교

:

많은 NSObject 서브 클래스 (예 : NSString, NSArray, NSDate, ...)하지만 CIImageisEqual: 메소드를 오버라이드 (override) .

+0

재미 있습니다. 그래서 저는 그것들을 각각 UIImage로 변환 한 다음 NSData로 변환하고 비교해 보았습니다 - 여전히 번들과 동일한 이미지로도 실패했습니다. 그게 효과가 있니? – Luke

+0

@lukech : PNG 파일 -> UIImage -> CIImage -> UIImage -> PNG 데이터로 변환합니다. 나는 데이터가 동일 할 것이라고 기대하지 않는다. –

+0

그럴 것입니다. 아마 그것은 순진하다. 어쨌든, 내 질문에 대한 정답과 같이 보입니다. 감사합니다 :) – Luke

0

FlexMonkey의 ImageCompareDemo은 C++에서 Swift에 대한 페이스 북의 ios-snapshot-test-case에서 불완전한 포트입니다. 그것은 픽셀 당 픽셀 비교의 마지막 부분을 생략했습니다. 내 것은 스위프트 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) 
    } 
    return imageEqual 
} 
관련 문제