diff --git a/SDWebImage/Core/SDImageTransformer.h b/SDWebImage/Core/SDImageTransformer.h index 95d6b95c..31b4370e 100644 --- a/SDWebImage/Core/SDImageTransformer.h +++ b/SDWebImage/Core/SDImageTransformer.h @@ -36,6 +36,17 @@ FOUNDATION_EXPORT NSString * _Nullable SDThumbnailedKeyForKey(NSString * _Nullab */ @protocol SDImageTransformer +@optional + +/** + Defaults to YES. + We keep some metadata like Image Format (`sd_imageFormat`)/ Animated Loop Count (`sd_imageLoopCount`) via associated object on UIImage instance. + When transformer generate a new UIImage instance, in most cases you still want to keep these information. So this is what for during the image loading pipeline. + If the value is YES, we will keep and override the metadata **After you generate the UIImage** + If the value is NO, we will not touch the UIImage metadata and it's controlled by you during the generation. Read `UIImage+Medata.h` and pick the metadata you want for the new generated UIImage. + */ +@property (nonatomic, assign, readonly) BOOL preserveImageMetadata; + @required /** For each transformer, it must contains its cache key to used to store the image cache or query from the cache. This key will be appened after the original cache key generated by URL or from user. diff --git a/SDWebImage/Core/SDWebImageManager.m b/SDWebImage/Core/SDWebImageManager.m index 2ddceabb..e69eda27 100644 --- a/SDWebImage/Core/SDWebImageManager.m +++ b/SDWebImage/Core/SDWebImageManager.m @@ -510,6 +510,16 @@ static id _defaultImageLoader; // Case that transformer on thumbnail, which this time need full pixel image UIImage *transformedImage = [transformer transformedImageWithImage:cacheImage forKey:key]; if (transformedImage) { + // We need keep some metadata from the full size image when needed + // Because most of our transformer does not care about these information + BOOL preserveImageMetadata = YES; + if ([transformer respondsToSelector:@selector(preserveImageMetadata)]) { + preserveImageMetadata = transformer.preserveImageMetadata; + } + if (preserveImageMetadata) { + SDImageCopyAssociatedObject(cacheImage, transformedImage); + } + // Mark the transformed transformedImage.sd_isTransformed = YES; [self callStoreOriginCacheProcessForOperation:operation url:url options:options context:context originalImage:originalImage cacheImage:transformedImage originalData:originalData cacheData:nil cacheType:cacheType finished:finished completed:completedBlock]; } else { diff --git a/Tests/Tests/SDWebImageManagerTests.m b/Tests/Tests/SDWebImageManagerTests.m index ab808626..d0c009d8 100644 --- a/Tests/Tests/SDWebImageManagerTests.m +++ b/Tests/Tests/SDWebImageManagerTests.m @@ -132,10 +132,16 @@ - (void)test08ThatImageTransformerWork { XCTestExpectation *expectation = [self expectationWithDescription:@"Image transformer work"]; - NSURL *url = [NSURL URLWithString:@"https://placehold.co/80x60.png"]; + NSURL *url = [NSURL URLWithString:@"https://placehold.co/80x60.jpg"]; SDWebImageTestTransformer *transformer = [[SDWebImageTestTransformer alloc] init]; + transformer.preserveImageMetadata = YES; // preserve metadata + NSData *extData = [@"Foobar" dataUsingEncoding:NSUTF8StringEncoding]; - transformer.testImage = [[UIImage alloc] initWithContentsOfFile:[self testJPEGPath]]; + CGSize transformSize = CGSizeMake(40, 30); + UIImage *testImage = [[[UIImage alloc] initWithContentsOfFile:[self testJPEGPath]] sd_resizedImageWithSize:transformSize scaleMode:SDImageScaleModeFill]; + testImage.sd_imageFormat = SDImageFormatUndefined; + testImage.sd_extendedObject = extData; + transformer.testImage = testImage; SDImageCache *cache = [[SDImageCache alloc] initWithNamespace:@"Transformer"]; SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:cache loader:SDWebImageDownloader.sharedDownloader]; NSString *key = [manager cacheKeyForURL:url]; @@ -150,6 +156,12 @@ SDImageCoderOptions *encodeOptions = @{SDImageCoderEncodeMaxPixelSize : @(CGSizeMake(40, 30))}; [manager loadImageWithURL:url options:SDWebImageTransformAnimatedImage | SDWebImageTransformVectorImage | SDWebImageWaitStoreCache context:@{SDWebImageContextImageEncodeOptions : encodeOptions} progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) { expect(image).equal(transformer.testImage); + // Test metadata + expect(image.size).equal(transformSize); + expect(image.sd_isTransformed).equal(YES); + expect(image.sd_imageFormat).equal(SDImageFormatJPEG); // override from full image + expect(image.sd_extendedObject).beNil(); // override from full image + // Query the encoded data again NSData *encodedData = [cache diskImageDataForKey:transformedKey]; UIImage *encodedImage = [UIImage sd_imageWithData:encodedData]; @@ -256,6 +268,7 @@ SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:cache loader:SDWebImageDownloader.sharedDownloader]; SDWebImageTestTransformer *transformer = [[SDWebImageTestTransformer alloc] init]; transformer.testImage = [[UIImage alloc] initWithContentsOfFile:[self testJPEGPath]]; + transformer.preserveImageMetadata = NO; // the transformed image should not inherite any attribute from original one manager.transformer = transformer; // test: original image -> disk only, transformed image -> memory only diff --git a/Tests/Tests/SDWebImageTestTransformer.h b/Tests/Tests/SDWebImageTestTransformer.h index c741c751..0484a3ce 100644 --- a/Tests/Tests/SDWebImageTestTransformer.h +++ b/Tests/Tests/SDWebImageTestTransformer.h @@ -11,6 +11,8 @@ @interface SDWebImageTestTransformer : NSObject +@property (nonatomic, assign) BOOL preserveImageMetadata; + @property (nonatomic, strong, nullable) UIImage *testImage; @end diff --git a/Tests/Tests/SDWebImageTestTransformer.m b/Tests/Tests/SDWebImageTestTransformer.m index 0afafe76..2bce7a10 100644 --- a/Tests/Tests/SDWebImageTestTransformer.m +++ b/Tests/Tests/SDWebImageTestTransformer.m @@ -11,6 +11,14 @@ @implementation SDWebImageTestTransformer +- (instancetype)init { + self = [super init]; + if (self) { + _preserveImageMetadata = YES; + } + return self; +} + - (NSString *)transformerKey { return @"SDWebImageTestTransformer"; }