From 099371823e8213a0bcacbd35cc7d0308835e3e3c Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 3 Sep 2024 17:09:48 +0800 Subject: [PATCH 1/4] Add blend mode to UIImage+Transform tint color API Also works for CIFilter variant --- SDWebImage/Core/UIImage+Transform.h | 12 ++- SDWebImage/Core/UIImage+Transform.m | 160 ++++++++++++++++++++++++++-- 2 files changed, 162 insertions(+), 10 deletions(-) diff --git a/SDWebImage/Core/UIImage+Transform.h b/SDWebImage/Core/UIImage+Transform.h index 60b488ae..bbacc145 100644 --- a/SDWebImage/Core/UIImage+Transform.h +++ b/SDWebImage/Core/UIImage+Transform.h @@ -98,13 +98,23 @@ typedef NS_OPTIONS(NSUInteger, SDRectCorner) { #pragma mark - Image Blending /** - Return a tinted image with the given color. This actually use alpha blending of current image and the tint color. + Return a tinted image with the given color. This actually use `sourceAtop` blend mode. @param tintColor The tint color. @return The new image with the tint color. */ - (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor; +/** + Return a tinted image with the given color and blend mode. + @note The blend mode treat `self` as background image (destination), treat `tintColor` as input image (source). So mostly you need `source` variant blend mode (use `sourceAtop` not `destinationAtop`). + + @param tintColor The tint color. + @param blendMode The blend mode. + @return The new image with the tint color. + */ +- (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor blendMode:(CGBlendMode)blendMode; + /** Return the pixel color at specify position. The point is from the top-left to the bottom-right and 0-based. The returned the color is always be RGBA format. The image must be CG-based. @note The point's x/y will be converted into integer. diff --git a/SDWebImage/Core/UIImage+Transform.m b/SDWebImage/Core/UIImage+Transform.m index 65c7d638..c40e4cfb 100644 --- a/SDWebImage/Core/UIImage+Transform.m +++ b/SDWebImage/Core/UIImage+Transform.m @@ -536,28 +536,173 @@ static inline CGImageRef _Nullable SDCreateCGImageFromCIImage(CIImage * _Nonnull #pragma mark - Image Blending +static NSString * _Nullable SDGetCIFilterNameFromBlendMode(CGBlendMode blendMode) { + // CGBlendMode: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_images/dq_images.html#//apple_ref/doc/uid/TP30001066-CH212-CJBIJEFG + // CIFilter: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/uid/TP30000136-SW71 + NSString *filterName; + switch (blendMode) { + case kCGBlendModeMultiply: + filterName = @"CIMultiplyBlendMode"; + break; + case kCGBlendModeScreen: + filterName = @"CIScreenBlendMode"; + break; + case kCGBlendModeOverlay: + filterName = @"CIOverlayBlendMode"; + break; + case kCGBlendModeDarken: + filterName = @"CIDarkenBlendMode"; + break; + case kCGBlendModeLighten: + filterName = @"CILightenBlendMode"; + break; + case kCGBlendModeColorDodge: + filterName = @"CIColorDodgeBlendMode"; + break; + case kCGBlendModeColorBurn: + filterName = @"CIColorBurnBlendMode"; + break; + case kCGBlendModeSoftLight: + filterName = @"CISoftLightBlendMode"; + break; + case kCGBlendModeHardLight: + filterName = @"CIHardLightBlendMode"; + break; + case kCGBlendModeDifference: + filterName = @"CIDifferenceBlendMode"; + break; + case kCGBlendModeExclusion: + filterName = @"CIExclusionBlendMode"; + break; + case kCGBlendModeHue: + filterName = @"CIHueBlendMode"; + break; + case kCGBlendModeSaturation: + filterName = @"CISaturationBlendMode"; + break; + case kCGBlendModeColor: + // Color blend mode uses the luminance values of the background with the hue and saturation values of the source image. + filterName = @"CIColorBlendMode"; + break; + case kCGBlendModeLuminosity: + filterName = @"CILuminosityBlendMode"; + break; + + // macOS 10.5+ + case kCGBlendModeSourceAtop: + case kCGBlendModeDestinationAtop: + filterName = @"CISourceAtopCompositing"; + break; + case kCGBlendModeSourceIn: + case kCGBlendModeDestinationIn: + filterName = @"CISourceInCompositing"; + break; + case kCGBlendModeSourceOut: + case kCGBlendModeDestinationOut: + filterName = @"CISourceOutCompositing"; + break; + case kCGBlendModeNormal: // SourceOver + case kCGBlendModeDestinationOver: + filterName = @"CISourceOverCompositing"; + break; + + // need special handling + case kCGBlendModeClear: + // use clear color instead + break; + case kCGBlendModeCopy: + // use input color instead + break; + case kCGBlendModeXOR: + // unsupported + break; + case kCGBlendModePlusDarker: + // chain filters + break; + case kCGBlendModePlusLighter: + // chain filters + break; + } + return filterName; +} + - (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor { + return [self sd_tintedImageWithColor:tintColor blendMode:kCGBlendModeSourceAtop]; +} + +- (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor blendMode:(CGBlendMode)blendMode { BOOL hasTint = CGColorGetAlpha(tintColor.CGColor) > __FLT_EPSILON__; if (!hasTint) { return self; } + // blend mode, see https://en.wikipedia.org/wiki/Alpha_compositing #if SD_UIKIT || SD_MAC // CIImage shortcut - if (self.CIImage) { - CIImage *ciImage = self.CIImage; + CIImage *ciImage = self.CIImage; + if (ciImage) { CIImage *colorImage = [CIImage imageWithColor:[[CIColor alloc] initWithColor:tintColor]]; colorImage = [colorImage imageByCroppingToRect:ciImage.extent]; - CIFilter *filter = [CIFilter filterWithName:@"CISourceAtopCompositing"]; - [filter setValue:colorImage forKey:kCIInputImageKey]; - [filter setValue:ciImage forKey:kCIInputBackgroundImageKey]; - ciImage = filter.outputImage; + NSString *filterName = SDGetCIFilterNameFromBlendMode(blendMode); + // Some blend mode is not nativelly supported + if (filterName) { + CIFilter *filter = [CIFilter filterWithName:filterName]; + [filter setValue:colorImage forKey:kCIInputImageKey]; + [filter setValue:ciImage forKey:kCIInputBackgroundImageKey]; + ciImage = filter.outputImage; + } else { + if (blendMode == kCGBlendModeClear) { + // R = 0 + CIColor *clearColor; + if (@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)) { + clearColor = CIColor.clearColor; + } else { + clearColor = [[CIColor alloc] initWithColor:UIColor.clearColor]; + } + ciImage = [CIImage imageWithColor:clearColor]; + } else if (blendMode == kCGBlendModeCopy) { + // R = S + ciImage = colorImage; + } else if (blendMode == kCGBlendModePlusLighter) { + // R = MIN(1, S + D) + // S + D + CIFilter *filter = [CIFilter filterWithName:@"CIAdditionCompositing"]; + [filter setValue:colorImage forKey:kCIInputImageKey]; + [filter setValue:ciImage forKey:kCIInputBackgroundImageKey]; + ciImage = filter.outputImage; + // MIN + ciImage = [ciImage imageByApplyingFilter:@"CIColorClamp" withInputParameters:nil]; + } else if (blendMode == kCGBlendModePlusDarker) { + // R = MAX(0, (1 - D) + (1 - S)) + // (1 - D) + CIFilter *filter1 = [CIFilter filterWithName:@"CIColorInvert"]; + [filter1 setValue:ciImage forKey:kCIInputImageKey]; + ciImage = filter1.outputImage; + // (1 - S) + CIFilter *filter2 = [CIFilter filterWithName:@"CIColorInvert"]; + [filter2 setValue:colorImage forKey:kCIInputImageKey]; + colorImage = filter2.outputImage; + // + + CIFilter *filter = [CIFilter filterWithName:@"CIAdditionCompositing"]; + [filter setValue:colorImage forKey:kCIInputImageKey]; + [filter setValue:ciImage forKey:kCIInputBackgroundImageKey]; + ciImage = filter.outputImage; + // MAX + ciImage = [ciImage imageByApplyingFilter:@"CIColorClamp" withInputParameters:nil]; + } else { + SD_LOG("UIImage+Transform error: Unsupported blend mode: %zu", blendMode); + ciImage = nil; + } + } + + if (ciImage) { #if SD_UIKIT UIImage *image = [UIImage imageWithCIImage:ciImage scale:self.scale orientation:self.imageOrientation]; #else UIImage *image = [[UIImage alloc] initWithCIImage:ciImage scale:self.scale orientation:kCGImagePropertyOrientationUp]; #endif return image; + } } #endif @@ -565,9 +710,6 @@ static inline CGImageRef _Nullable SDCreateCGImageFromCIImage(CIImage * _Nonnull CGRect rect = { CGPointZero, size }; CGFloat scale = self.scale; - // blend mode, see https://en.wikipedia.org/wiki/Alpha_compositing - CGBlendMode blendMode = kCGBlendModeSourceAtop; - SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init]; format.scale = scale; SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:size format:format]; From 3c89a092cd1f14d989d819e13cf411d27dce151b Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 3 Sep 2024 17:22:34 +0800 Subject: [PATCH 2/4] Added the blend mode to transformer API as well Update unit tests --- SDWebImage/Core/SDImageTransformer.h | 3 +++ SDWebImage/Core/SDImageTransformer.m | 8 +++++++- Tests/Tests/SDImageTransformerTests.m | 6 +++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/SDWebImage/Core/SDImageTransformer.h b/SDWebImage/Core/SDImageTransformer.h index 31b4370e..0c0ff4f1 100644 --- a/SDWebImage/Core/SDImageTransformer.h +++ b/SDWebImage/Core/SDImageTransformer.h @@ -223,11 +223,14 @@ FOUNDATION_EXPORT NSString * _Nullable SDThumbnailedKeyForKey(NSString * _Nullab The tint color. */ @property (nonatomic, strong, readonly, nonnull) UIColor *tintColor; +/// The blend mode, defaults to `sourceAtop` if you use the old initializer +@property (nonatomic, assign, readonly) CGBlendMode blendMode; - (nonnull instancetype)init NS_UNAVAILABLE; + (nonnull instancetype)new NS_UNAVAILABLE; + (nonnull instancetype)transformerWithColor:(nonnull UIColor *)tintColor; ++ (nonnull instancetype)transformerWithColor:(nonnull UIColor *)tintColor blendMode:(CGBlendMode)blendMode; @end diff --git a/SDWebImage/Core/SDImageTransformer.m b/SDWebImage/Core/SDImageTransformer.m index 8e7a3e2a..056cbbdd 100644 --- a/SDWebImage/Core/SDImageTransformer.m +++ b/SDWebImage/Core/SDImageTransformer.m @@ -245,20 +245,26 @@ NSString * _Nullable SDThumbnailedKeyForKey(NSString * _Nullable key, CGSize thu @interface SDImageTintTransformer () @property (nonatomic, strong, nonnull) UIColor *tintColor; +@property (nonatomic, assign) CGBlendMode blendMode; @end @implementation SDImageTintTransformer + (instancetype)transformerWithColor:(UIColor *)tintColor { + return [self transformerWithColor:tintColor blendMode:kCGBlendModeSourceAtop]; +} + ++ (instancetype)transformerWithColor:(UIColor *)tintColor blendMode:(CGBlendMode)blendMode { SDImageTintTransformer *transformer = [SDImageTintTransformer new]; transformer.tintColor = tintColor; + transformer.blendMode = blendMode; return transformer; } - (NSString *)transformerKey { - return [NSString stringWithFormat:@"SDImageTintTransformer(%@)", self.tintColor.sd_hexString]; + return [NSString stringWithFormat:@"SDImageTintTransformer(%@,%d)", self.tintColor.sd_hexString, self.blendMode]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { diff --git a/Tests/Tests/SDImageTransformerTests.m b/Tests/Tests/SDImageTransformerTests.m index 7ad802f9..1559d4d2 100644 --- a/Tests/Tests/SDImageTransformerTests.m +++ b/Tests/Tests/SDImageTransformerTests.m @@ -242,6 +242,10 @@ static void SDAssertCGImageFirstComponentWhite(CGImageRef image, OSType pixelTyp // Check rounded corner operation not inversion the image UIColor *topCenterColor = [tintedImage sd_colorAtPoint:CGPointMake(150, 20)]; expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy(); + + UIImage *tintedSourceInImage = [testImage sd_tintedImageWithColor:tintColor blendMode:kCGBlendModeSourceOut]; + centerColor = [tintedSourceInImage sd_colorAtPoint:CGPointMake(150, 150)]; + expect([centerColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy(); } - (void)test07UIImageTransformBlurCG { @@ -353,7 +357,7 @@ static void SDAssertCGImageFirstComponentWhite(CGImageRef image, OSType pixelTyp @"SDImageRoundCornerTransformer(50.000000,18446744073709551615,1.000000,#ff000000)", @"SDImageFlippingTransformer(1,1)", @"SDImageCroppingTransformer({0.000000,0.000000,50.000000,50.000000})", - @"SDImageTintTransformer(#00000000)", + @"SDImageTintTransformer(#00000000,20)", @"SDImageBlurTransformer(5.000000)", @"SDImageFilterTransformer(CIColorInvert)" ]; From 7892f4ca2033568a20ba397babbb80671d4606d5 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 3 Sep 2024 18:56:03 +0800 Subject: [PATCH 3/4] Fix some CIFilter implementation --- SDWebImage/Core/UIImage+Transform.m | 10 +++++++--- Tests/Tests/SDImageTransformerTests.m | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/SDWebImage/Core/UIImage+Transform.m b/SDWebImage/Core/UIImage+Transform.m index c40e4cfb..a4d72f23 100644 --- a/SDWebImage/Core/UIImage+Transform.m +++ b/SDWebImage/Core/UIImage+Transform.m @@ -659,7 +659,9 @@ static NSString * _Nullable SDGetCIFilterNameFromBlendMode(CGBlendMode blendMode } else { clearColor = [[CIColor alloc] initWithColor:UIColor.clearColor]; } - ciImage = [CIImage imageWithColor:clearColor]; + colorImage = [CIImage imageWithColor:clearColor]; + colorImage = [colorImage imageByCroppingToRect:ciImage.extent]; + ciImage = colorImage; } else if (blendMode == kCGBlendModeCopy) { // R = S ciImage = colorImage; @@ -675,12 +677,14 @@ static NSString * _Nullable SDGetCIFilterNameFromBlendMode(CGBlendMode blendMode } else if (blendMode == kCGBlendModePlusDarker) { // R = MAX(0, (1 - D) + (1 - S)) // (1 - D) - CIFilter *filter1 = [CIFilter filterWithName:@"CIColorInvert"]; + CIFilter *filter1 = [CIFilter filterWithName:@"CIColorControls"]; [filter1 setValue:ciImage forKey:kCIInputImageKey]; + [filter1 setValue:@(-0.5) forKey:kCIInputBrightnessKey]; ciImage = filter1.outputImage; // (1 - S) - CIFilter *filter2 = [CIFilter filterWithName:@"CIColorInvert"]; + CIFilter *filter2 = [CIFilter filterWithName:@"CIColorControls"]; [filter2 setValue:colorImage forKey:kCIInputImageKey]; + [filter2 setValue:@(-0.5) forKey:kCIInputBrightnessKey]; colorImage = filter2.outputImage; // + CIFilter *filter = [CIFilter filterWithName:@"CIAdditionCompositing"]; diff --git a/Tests/Tests/SDImageTransformerTests.m b/Tests/Tests/SDImageTransformerTests.m index 1559d4d2..b099fb7e 100644 --- a/Tests/Tests/SDImageTransformerTests.m +++ b/Tests/Tests/SDImageTransformerTests.m @@ -243,7 +243,7 @@ static void SDAssertCGImageFirstComponentWhite(CGImageRef image, OSType pixelTyp UIColor *topCenterColor = [tintedImage sd_colorAtPoint:CGPointMake(150, 20)]; expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy(); - UIImage *tintedSourceInImage = [testImage sd_tintedImageWithColor:tintColor blendMode:kCGBlendModeSourceOut]; + UIImage *tintedSourceInImage = [testImage sd_tintedImageWithColor:tintColor blendMode:kCGBlendModeSourceIn]; centerColor = [tintedSourceInImage sd_colorAtPoint:CGPointMake(150, 150)]; expect([centerColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy(); } From 05e1840538324649fd82136b2c0f9703172cb884 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 8 Oct 2024 17:16:43 +0800 Subject: [PATCH 4/4] Behavior changes: change the default tint transformer to use `sourceIn` instead of `sourceAtop` This matches the Apple UIKit's naming and behavior --- SDWebImage/Core/SDImageTransformer.h | 2 +- SDWebImage/Core/SDImageTransformer.m | 2 +- SDWebImage/Core/UIImage+Transform.h | 5 +++-- SDWebImage/Core/UIImage+Transform.m | 4 ++-- Tests/Tests/SDImageTransformerTests.m | 30 ++++++++++++++++++++++++--- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/SDWebImage/Core/SDImageTransformer.h b/SDWebImage/Core/SDImageTransformer.h index 0c0ff4f1..e01550a6 100644 --- a/SDWebImage/Core/SDImageTransformer.h +++ b/SDWebImage/Core/SDImageTransformer.h @@ -223,7 +223,7 @@ FOUNDATION_EXPORT NSString * _Nullable SDThumbnailedKeyForKey(NSString * _Nullab The tint color. */ @property (nonatomic, strong, readonly, nonnull) UIColor *tintColor; -/// The blend mode, defaults to `sourceAtop` if you use the old initializer +/// The blend mode, defaults to `sourceIn` if you use the initializer without blend mode @property (nonatomic, assign, readonly) CGBlendMode blendMode; - (nonnull instancetype)init NS_UNAVAILABLE; diff --git a/SDWebImage/Core/SDImageTransformer.m b/SDWebImage/Core/SDImageTransformer.m index 056cbbdd..813be2e8 100644 --- a/SDWebImage/Core/SDImageTransformer.m +++ b/SDWebImage/Core/SDImageTransformer.m @@ -252,7 +252,7 @@ NSString * _Nullable SDThumbnailedKeyForKey(NSString * _Nullable key, CGSize thu @implementation SDImageTintTransformer + (instancetype)transformerWithColor:(UIColor *)tintColor { - return [self transformerWithColor:tintColor blendMode:kCGBlendModeSourceAtop]; + return [self transformerWithColor:tintColor blendMode:kCGBlendModeSourceIn]; } + (instancetype)transformerWithColor:(UIColor *)tintColor blendMode:(CGBlendMode)blendMode { diff --git a/SDWebImage/Core/UIImage+Transform.h b/SDWebImage/Core/UIImage+Transform.h index bbacc145..f4c50d3a 100644 --- a/SDWebImage/Core/UIImage+Transform.h +++ b/SDWebImage/Core/UIImage+Transform.h @@ -98,7 +98,8 @@ typedef NS_OPTIONS(NSUInteger, SDRectCorner) { #pragma mark - Image Blending /** - Return a tinted image with the given color. This actually use `sourceAtop` blend mode. + Return a tinted image with the given color. This actually use `sourceIn` blend mode. + @note Before 5.20, this API actually use `sourceAtop` and cause naming confusing. After 5.20, we match UIKit's behavior using `sourceIn`. @param tintColor The tint color. @return The new image with the tint color. @@ -107,7 +108,7 @@ typedef NS_OPTIONS(NSUInteger, SDRectCorner) { /** Return a tinted image with the given color and blend mode. - @note The blend mode treat `self` as background image (destination), treat `tintColor` as input image (source). So mostly you need `source` variant blend mode (use `sourceAtop` not `destinationAtop`). + @note The blend mode treat `self` as background image (destination), treat `tintColor` as input image (source). So mostly you need `source` variant blend mode (use `sourceIn` not `destinationIn`), which is different from UIKit's `+[UIImage imageWithTintColor:]`. @param tintColor The tint color. @param blendMode The blend mode. diff --git a/SDWebImage/Core/UIImage+Transform.m b/SDWebImage/Core/UIImage+Transform.m index a4d72f23..bed7279d 100644 --- a/SDWebImage/Core/UIImage+Transform.m +++ b/SDWebImage/Core/UIImage+Transform.m @@ -627,7 +627,7 @@ static NSString * _Nullable SDGetCIFilterNameFromBlendMode(CGBlendMode blendMode } - (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor { - return [self sd_tintedImageWithColor:tintColor blendMode:kCGBlendModeSourceAtop]; + return [self sd_tintedImageWithColor:tintColor blendMode:kCGBlendModeSourceIn]; } - (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor blendMode:(CGBlendMode)blendMode { @@ -694,7 +694,7 @@ static NSString * _Nullable SDGetCIFilterNameFromBlendMode(CGBlendMode blendMode // MAX ciImage = [ciImage imageByApplyingFilter:@"CIColorClamp" withInputParameters:nil]; } else { - SD_LOG("UIImage+Transform error: Unsupported blend mode: %zu", blendMode); + SD_LOG("UIImage+Transform error: Unsupported blend mode: %d", blendMode); ciImage = nil; } } diff --git a/Tests/Tests/SDImageTransformerTests.m b/Tests/Tests/SDImageTransformerTests.m index b099fb7e..550a854b 100644 --- a/Tests/Tests/SDImageTransformerTests.m +++ b/Tests/Tests/SDImageTransformerTests.m @@ -244,9 +244,33 @@ static void SDAssertCGImageFirstComponentWhite(CGImageRef image, OSType pixelTyp expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy(); UIImage *tintedSourceInImage = [testImage sd_tintedImageWithColor:tintColor blendMode:kCGBlendModeSourceIn]; - centerColor = [tintedSourceInImage sd_colorAtPoint:CGPointMake(150, 150)]; - expect([centerColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy(); + topCenterColor = [tintedSourceInImage sd_colorAtPoint:CGPointMake(150, 20)]; +#if SD_UIKIT + // Test UIKit's tint color behavior + if (@available(iOS 13.0, tvOS 13.0, watchOS 6.0, *)) { + UIImage *tintedSystemImage = [testImage imageWithTintColor:tintColor renderingMode:UIImageRenderingModeAlwaysTemplate]; + UIGraphicsImageRendererFormat *format = UIGraphicsImageRendererFormat.preferredFormat; + format.scale = tintedSourceInImage.scale; + UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:tintedSystemImage.size format:format]; + // Draw template image + tintedSystemImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) { + [tintedSystemImage drawInRect:CGRectMake(0, 0, tintedSystemImage.size.width, tintedSystemImage.size.height)]; + }]; + UIColor *testColor1 = [tintedSourceInImage sd_colorAtPoint:CGPointMake(150, 20)]; + UIColor *testColor2 = [tintedSystemImage sd_colorAtPoint:CGPointMake(150, 20)]; + CGFloat r1, g1, b1, a1; + CGFloat r2, g2, b2, a2; + [testColor1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1]; + [testColor2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2]; + expect(r1).beCloseToWithin(r2, 0.01); + expect(g1).beCloseToWithin(g2, 0.01); + expect(b1).beCloseToWithin(b2, 0.01); + expect(a1).beCloseToWithin(a2, 0.01); + } +#endif + expect([topCenterColor.sd_hexString isEqualToString:tintColor.sd_hexString]).beTruthy(); } +#pragma clang diagnostic pop - (void)test07UIImageTransformBlurCG { [self test07UIImageTransformBlurWithImage:self.testImageCG]; @@ -357,7 +381,7 @@ static void SDAssertCGImageFirstComponentWhite(CGImageRef image, OSType pixelTyp @"SDImageRoundCornerTransformer(50.000000,18446744073709551615,1.000000,#ff000000)", @"SDImageFlippingTransformer(1,1)", @"SDImageCroppingTransformer({0.000000,0.000000,50.000000,50.000000})", - @"SDImageTintTransformer(#00000000,20)", + @"SDImageTintTransformer(#00000000,18)", @"SDImageBlurTransformer(5.000000)", @"SDImageFilterTransformer(CIColorInvert)" ];