diff --git a/src/iOSSnapshotTestCaseCore/Categories/UIImage+Compare.m b/src/iOSSnapshotTestCaseCore/Categories/UIImage+Compare.m index cdd97da..f75d0c1 100644 --- a/src/iOSSnapshotTestCaseCore/Categories/UIImage+Compare.m +++ b/src/iOSSnapshotTestCaseCore/Categories/UIImage+Compare.m @@ -51,12 +51,13 @@ @implementation UIImage (Compare) - (BOOL)fb_compareWithImage:(UIImage *)image perPixelTolerance:(CGFloat)perPixelTolerance overallTolerance:(CGFloat)overallTolerance { CGSize referenceImageSize = CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage)); - CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage)); - NSAssert(CGSizeEqualToSize(referenceImageSize, imageSize), @"Images must be same size."); + NSAssert(CGSizeEqualToSize(CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage)), referenceImageSize), + @"Images must be same size."); - // The images have the equal size, so we could use the smallest amount of bytes because of byte padding - size_t minBytesPerRow = MIN(CGImageGetBytesPerRow(self.CGImage), CGImageGetBytesPerRow(image.CGImage)); - size_t referenceImageSizeBytes = referenceImageSize.height * minBytesPerRow; + // Use larger of the two in case one has been optimized (fewer bits per component and/or bytes per row) + size_t bytesPerRow = MAX(CGImageGetBytesPerRow(image.CGImage), CGImageGetBytesPerRow(self.CGImage)); + size_t bitsPerComponent = MAX(CGImageGetBitsPerComponent(image.CGImage), CGImageGetBitsPerComponent(self.CGImage)); + size_t referenceImageSizeBytes = referenceImageSize.height * bytesPerRow; void *referenceImagePixels = calloc(1, referenceImageSizeBytes); void *imagePixels = calloc(1, referenceImageSizeBytes); @@ -69,16 +70,16 @@ - (BOOL)fb_compareWithImage:(UIImage *)image perPixelTolerance:(CGFloat)perPixel CGContextRef referenceImageContext = CGBitmapContextCreate(referenceImagePixels, referenceImageSize.width, referenceImageSize.height, - CGImageGetBitsPerComponent(self.CGImage), - minBytesPerRow, - CGImageGetColorSpace(self.CGImage), + bitsPerComponent, + bytesPerRow, + CGColorSpaceCreateDeviceRGB(), (CGBitmapInfo)kCGImageAlphaPremultipliedLast); CGContextRef imageContext = CGBitmapContextCreate(imagePixels, - imageSize.width, - imageSize.height, - CGImageGetBitsPerComponent(image.CGImage), - minBytesPerRow, - CGImageGetColorSpace(image.CGImage), + referenceImageSize.width, + referenceImageSize.height, + bitsPerComponent, + bytesPerRow, + CGColorSpaceCreateDeviceRGB(), (CGBitmapInfo)kCGImageAlphaPremultipliedLast); if (!referenceImageContext || !imageContext) { @@ -90,7 +91,7 @@ - (BOOL)fb_compareWithImage:(UIImage *)image perPixelTolerance:(CGFloat)perPixel } CGContextDrawImage(referenceImageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), self.CGImage); - CGContextDrawImage(imageContext, CGRectMake(0, 0, imageSize.width, imageSize.height), image.CGImage); + CGContextDrawImage(imageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), image.CGImage); CGContextRelease(referenceImageContext); CGContextRelease(imageContext); diff --git a/src/iOSSnapshotTestCaseTests/FBSnapshotControllerTests.m b/src/iOSSnapshotTestCaseTests/FBSnapshotControllerTests.m index 9331038..4031be9 100644 --- a/src/iOSSnapshotTestCaseTests/FBSnapshotControllerTests.m +++ b/src/iOSSnapshotTestCaseTests/FBSnapshotControllerTests.m @@ -196,6 +196,37 @@ - (void)testCompareReferenceImageWithLowPixelToleranceShouldMatch XCTAssertNil(error); } +- (void)testCompareReferenceImageToGrayscaleCrushedImageShouldBeEqual +{ + UIImage *referenceImage = [self _bundledImageNamed:@"rect" type:@"png"]; + XCTAssertNotNil(referenceImage); + + // rect_crushed was made by pngcrush version 1.8.13 with default options as shown below. Reduced file size by 67% + // FBSnapshotTestCaseTests$ pngcrush rect.png rect_crushed.png + UIImage *testImage = [self _bundledImageNamed:@"rect_crushed" type:@"png"]; + XCTAssertNotNil(testImage); + + id testClass = nil; + FBSnapshotTestController *controller = [[FBSnapshotTestController alloc] initWithTestClass:testClass]; + NSError *error = nil; + XCTAssertTrue([controller compareReferenceImage:referenceImage toImage:testImage overallTolerance:0 error:&error]); + XCTAssertNil(error); +} + +- (void)testCompareGrayscaleCrushedImageToReferenceImageShouldBeEqual +{ + UIImage *referenceImage = [self _bundledImageNamed:@"rect_crushed" type:@"png"]; + XCTAssertNotNil(referenceImage); + UIImage *testImage = [self _bundledImageNamed:@"rect" type:@"png"]; + XCTAssertNotNil(testImage); + + id testClass = nil; + FBSnapshotTestController *controller = [[FBSnapshotTestController alloc] initWithTestClass:testClass]; + NSError *error = nil; + XCTAssertTrue([controller compareReferenceImage:referenceImage toImage:testImage overallTolerance:0 error:&error]); + XCTAssertNil(error); +} + #pragma mark - Private helper methods - (UIImage *)_bundledImageNamed:(NSString *)name type:(NSString *)type diff --git a/src/iOSSnapshotTestCaseTests/Resources/rect_crushed.png b/src/iOSSnapshotTestCaseTests/Resources/rect_crushed.png new file mode 100644 index 0000000..dbcf230 Binary files /dev/null and b/src/iOSSnapshotTestCaseTests/Resources/rect_crushed.png differ