327 lines
9.7 KiB
Objective-C
327 lines
9.7 KiB
Objective-C
/*
|
|
* This file is part of the SDWebImage package.
|
|
* (c) Olivier Poitrey <rs@dailymotion.com>
|
|
*
|
|
* 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 <CoreImage/CoreImage.h>
|
|
#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<id<SDImageTransformer>> *transformers;
|
|
@property (nonatomic, copy, readwrite) NSString *transformerKey;
|
|
|
|
@end
|
|
|
|
@implementation SDImagePipelineTransformer
|
|
|
|
+ (instancetype)transformerWithTransformers:(NSArray<id<SDImageTransformer>> *)transformers {
|
|
SDImagePipelineTransformer *transformer = [SDImagePipelineTransformer new];
|
|
transformer.transformers = transformers;
|
|
transformer.transformerKey = [[self class] cacheKeyForTransformers:transformers];
|
|
|
|
return transformer;
|
|
}
|
|
|
|
+ (NSString *)cacheKeyForTransformers:(NSArray<id<SDImageTransformer>> *)transformers {
|
|
if (transformers.count == 0) {
|
|
return @"";
|
|
}
|
|
NSMutableArray<NSString *> *cacheKeys = [NSMutableArray arrayWithCapacity:transformers.count];
|
|
[transformers enumerateObjectsUsingBlock:^(id<SDImageTransformer> _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<SDImageTransformer> 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
|