/* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDImageTransformer.h" #import "UIColor+HexString.h" #if SD_UIKIT || SD_MAC #import #endif // Separator for different transformerKey, for example, `image.png` |> flip(YES,NO) |> rotate(pi/4,YES) => 'image-SDImageFlippingTransformer(1,0)-SDImageRotationTransformer(0.78539816339,1).png' static NSString * const SDImageTransformerKeySeparator = @"-"; NSString * _Nullable SDTransformedKeyForKey(NSString * _Nullable key, NSString * _Nonnull transformerKey) { if (!key || !transformerKey) { return nil; } // Find the file extension NSURL *keyURL = [NSURL URLWithString:key]; NSString *ext = keyURL ? keyURL.pathExtension : key.pathExtension; if (ext.length > 0) { // For non-file URL if (keyURL && !keyURL.isFileURL) { // keep anything except path (like URL query) NSURLComponents *component = [NSURLComponents componentsWithURL:keyURL resolvingAgainstBaseURL:NO]; component.path = [[[component.path.stringByDeletingPathExtension stringByAppendingString:SDImageTransformerKeySeparator] stringByAppendingString:transformerKey] stringByAppendingPathExtension:ext]; return component.URL.absoluteString; } else { // file URL return [[[key.stringByDeletingPathExtension stringByAppendingString:SDImageTransformerKeySeparator] stringByAppendingString:transformerKey] stringByAppendingPathExtension:ext]; } } else { return [[key stringByAppendingString:SDImageTransformerKeySeparator] stringByAppendingString:transformerKey]; } } @interface SDImagePipelineTransformer () @property (nonatomic, copy, readwrite, nonnull) NSArray> *transformers; @property (nonatomic, copy, readwrite) NSString *transformerKey; @end @implementation SDImagePipelineTransformer + (instancetype)transformerWithTransformers:(NSArray> *)transformers { SDImagePipelineTransformer *transformer = [SDImagePipelineTransformer new]; transformer.transformers = transformers; transformer.transformerKey = [[self class] cacheKeyForTransformers:transformers]; return transformer; } + (NSString *)cacheKeyForTransformers:(NSArray> *)transformers { if (transformers.count == 0) { return @""; } NSMutableArray *cacheKeys = [NSMutableArray arrayWithCapacity:transformers.count]; [transformers enumerateObjectsUsingBlock:^(id _Nonnull transformer, NSUInteger idx, BOOL * _Nonnull stop) { NSString *cacheKey = transformer.transformerKey; [cacheKeys addObject:cacheKey]; }]; return [cacheKeys componentsJoinedByString:SDImageTransformerKeySeparator]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } UIImage *transformedImage = image; for (id transformer in self.transformers) { transformedImage = [transformer transformedImageWithImage:transformedImage forKey:key]; } return transformedImage; } @end @interface SDImageRoundCornerTransformer () @property (nonatomic, assign) CGFloat cornerRadius; @property (nonatomic, assign) SDRectCorner corners; @property (nonatomic, assign) CGFloat borderWidth; @property (nonatomic, strong, nullable) UIColor *borderColor; @end @implementation SDImageRoundCornerTransformer + (instancetype)transformerWithRadius:(CGFloat)cornerRadius corners:(SDRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor { SDImageRoundCornerTransformer *transformer = [SDImageRoundCornerTransformer new]; transformer.cornerRadius = cornerRadius; transformer.corners = corners; transformer.borderWidth = borderWidth; transformer.borderColor = borderColor; return transformer; } - (NSString *)transformerKey { return [NSString stringWithFormat:@"SDImageRoundCornerTransformer(%f,%lu,%f,%@)", self.cornerRadius, (unsigned long)self.corners, self.borderWidth, self.borderColor.sd_hexString]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } return [image sd_roundedCornerImageWithRadius:self.cornerRadius corners:self.corners borderWidth:self.borderWidth borderColor:self.borderColor]; } @end @interface SDImageResizingTransformer () @property (nonatomic, assign) CGSize size; @property (nonatomic, assign) SDImageScaleMode scaleMode; @end @implementation SDImageResizingTransformer + (instancetype)transformerWithSize:(CGSize)size scaleMode:(SDImageScaleMode)scaleMode { SDImageResizingTransformer *transformer = [SDImageResizingTransformer new]; transformer.size = size; transformer.scaleMode = scaleMode; return transformer; } - (NSString *)transformerKey { CGSize size = self.size; return [NSString stringWithFormat:@"SDImageResizingTransformer({%f,%f},%lu)", size.width, size.height, (unsigned long)self.scaleMode]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } return [image sd_resizedImageWithSize:self.size scaleMode:self.scaleMode]; } @end @interface SDImageCroppingTransformer () @property (nonatomic, assign) CGRect rect; @end @implementation SDImageCroppingTransformer + (instancetype)transformerWithRect:(CGRect)rect { SDImageCroppingTransformer *transformer = [SDImageCroppingTransformer new]; transformer.rect = rect; return transformer; } - (NSString *)transformerKey { CGRect rect = self.rect; return [NSString stringWithFormat:@"SDImageCroppingTransformer({%f,%f,%f,%f})", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } return [image sd_croppedImageWithRect:self.rect]; } @end @interface SDImageFlippingTransformer () @property (nonatomic, assign) BOOL horizontal; @property (nonatomic, assign) BOOL vertical; @end @implementation SDImageFlippingTransformer + (instancetype)transformerWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical { SDImageFlippingTransformer *transformer = [SDImageFlippingTransformer new]; transformer.horizontal = horizontal; transformer.vertical = vertical; return transformer; } - (NSString *)transformerKey { return [NSString stringWithFormat:@"SDImageFlippingTransformer(%d,%d)", self.horizontal, self.vertical]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } return [image sd_flippedImageWithHorizontal:self.horizontal vertical:self.vertical]; } @end @interface SDImageRotationTransformer () @property (nonatomic, assign) CGFloat angle; @property (nonatomic, assign) BOOL fitSize; @end @implementation SDImageRotationTransformer + (instancetype)transformerWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize { SDImageRotationTransformer *transformer = [SDImageRotationTransformer new]; transformer.angle = angle; transformer.fitSize = fitSize; return transformer; } - (NSString *)transformerKey { return [NSString stringWithFormat:@"SDImageRotationTransformer(%f,%d)", self.angle, self.fitSize]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } return [image sd_rotatedImageWithAngle:self.angle fitSize:self.fitSize]; } @end #pragma mark - Image Blending @interface SDImageTintTransformer () @property (nonatomic, strong, nonnull) UIColor *tintColor; @end @implementation SDImageTintTransformer + (instancetype)transformerWithColor:(UIColor *)tintColor { SDImageTintTransformer *transformer = [SDImageTintTransformer new]; transformer.tintColor = tintColor; return transformer; } - (NSString *)transformerKey { return [NSString stringWithFormat:@"SDImageTintTransformer(%@)", self.tintColor.sd_hexString]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } return [image sd_tintedImageWithColor:self.tintColor]; } @end #pragma mark - Image Effect @interface SDImageBlurTransformer () @property (nonatomic, assign) CGFloat blurRadius; @end @implementation SDImageBlurTransformer + (instancetype)transformerWithRadius:(CGFloat)blurRadius { SDImageBlurTransformer *transformer = [SDImageBlurTransformer new]; transformer.blurRadius = blurRadius; return transformer; } - (NSString *)transformerKey { return [NSString stringWithFormat:@"SDImageBlurTransformer(%f)", self.blurRadius]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } return [image sd_blurredImageWithRadius:self.blurRadius]; } @end #if SD_UIKIT || SD_MAC @interface SDImageFilterTransformer () @property (nonatomic, strong, nonnull) CIFilter *filter; @end @implementation SDImageFilterTransformer + (instancetype)transformerWithFilter:(CIFilter *)filter { SDImageFilterTransformer *transformer = [SDImageFilterTransformer new]; transformer.filter = filter; return transformer; } - (NSString *)transformerKey { return [NSString stringWithFormat:@"SDImageFilterTransformer(%@)", self.filter.name]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { if (!image) { return nil; } return [image sd_filteredImageWithFilter:self.filter]; } @end #endif