Merge pull request #2390 from dreampiggy/feature_image_format

Keep the information about image's original compressed format, for API which only contains image but not image data to process extra logic
This commit is contained in:
Bogdan Poplauschi 2018-07-18 11:15:04 +03:00 committed by GitHub
commit 68c58992d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 80 additions and 8 deletions

View File

@ -32,11 +32,19 @@ typedef NS_ENUM(NSInteger, SDImageFormat) {
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
/**
Convert SDImageFormat to UTType
@param format Format as SDImageFormat
@return The UTType as CFStringRef
* Convert SDImageFormat to UTType
*
* @param format Format as SDImageFormat
* @return The UTType as CFStringRef
*/
+ (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format;
/**
* Convert UTTyppe to SDImageFormat
*
* @param uttype The UTType as CFStringRef
* @return The Format as SDImageFormat
*/
+ (SDImageFormat)sd_imageFormatFromUTType:(nonnull CFStringRef)uttype;
@end

View File

@ -95,4 +95,27 @@
return UTType;
}
+ (SDImageFormat)sd_imageFormatFromUTType:(CFStringRef)uttype {
if (!uttype) {
return SDImageFormatUndefined;
}
SDImageFormat imageFormat;
if (CFStringCompare(uttype, kUTTypeJPEG, 0) == kCFCompareEqualTo) {
imageFormat = SDImageFormatJPEG;
} else if (CFStringCompare(uttype, kUTTypePNG, 0) == kCFCompareEqualTo) {
imageFormat = SDImageFormatPNG;
} else if (CFStringCompare(uttype, kUTTypeGIF, 0) == kCFCompareEqualTo) {
imageFormat = SDImageFormatGIF;
} else if (CFStringCompare(uttype, kUTTypeTIFF, 0) == kCFCompareEqualTo) {
imageFormat = SDImageFormatTIFF;
} else if (CFStringCompare(uttype, kSDUTTypeWebP, 0) == kCFCompareEqualTo) {
imageFormat = SDImageFormatWebP;
} else if (CFStringCompare(uttype, kSDUTTypeHEIC, 0) == kCFCompareEqualTo) {
imageFormat = SDImageFormatHEIC;
} else {
imageFormat = SDImageFormatUndefined;
}
return imageFormat;
}
@end

View File

@ -12,6 +12,7 @@
#ifdef SD_WEBP
#import "SDWebImageWebPCoder.h"
#endif
#import "UIImage+MultiFormat.h"
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
@ -121,7 +122,9 @@
UNLOCK(self.codersLock);
for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) {
if ([coder canDecodeFromData:*data]) {
return [coder decompressedImageWithImage:image data:data options:optionsDict];
UIImage *decompressedImage = [coder decompressedImageWithImage:image data:data options:optionsDict];
decompressedImage.sd_imageFormat = image.sd_imageFormat;
return decompressedImage;
}
}
return nil;

View File

@ -35,6 +35,7 @@ inline UIImage *SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullabl
UIImage *animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];
if (animatedImage) {
animatedImage.sd_imageLoopCount = image.sd_imageLoopCount;
animatedImage.sd_imageFormat = image.sd_imageFormat;
}
return animatedImage;
} else {
@ -57,6 +58,7 @@ inline UIImage *SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullabl
}
UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
scaledImage.sd_imageFormat = image.sd_imageFormat;
image = scaledImage;
}
return image;

View File

@ -81,6 +81,7 @@
animatedImage = [SDWebImageCoderHelper animatedImageWithFrames:frames];
animatedImage.sd_imageLoopCount = loopCount;
animatedImage.sd_imageFormat = SDImageFormatGIF;
}
CFRelease(source);

View File

@ -11,6 +11,7 @@
#import "NSImage+WebCache.h"
#import <ImageIO/ImageIO.h>
#import "NSData+ImageContentType.h"
#import "UIImage+MultiFormat.h"
#if SD_UIKIT || SD_WATCH
static const size_t kBytesPerPixel = 4;
@ -97,6 +98,7 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
}
UIImage *image = [[UIImage alloc] initWithData:data];
image.sd_imageFormat = [NSData sd_imageFormatForImageData:data];
return image;
}
@ -146,6 +148,7 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
image = [[UIImage alloc] initWithCGImage:partialImageRef size:NSZeroSize];
#endif
CGImageRelease(partialImageRef);
image.sd_imageFormat = [NSData sd_imageFormatForImageData:data];
}
}

View File

@ -106,6 +106,7 @@
}
WebPDemuxDelete(demuxer);
CGContextRelease(canvas);
staticImage.sd_imageFormat = SDImageFormatWebP;
return staticImage;
}
@ -145,6 +146,7 @@
UIImage *animatedImage = [SDWebImageCoderHelper animatedImageWithFrames:frames];
animatedImage.sd_imageLoopCount = loopCount;
animatedImage.sd_imageFormat = SDImageFormatWebP;
return animatedImage;
}
@ -215,6 +217,7 @@
#else
image = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
#endif
image.sd_imageFormat = SDImageFormatWebP;
CGImageRelease(newImageRef);
CGContextRelease(canvas);
}

View File

@ -15,7 +15,7 @@
* UIKit:
* For static image format, this value is always 0.
* For animated image format, 0 means infinite looping.
* Note that because of the limitations of categories this property can get out of sync if you create another instance with CGImage or other methods.
* @note Note that because of the limitations of categories this property can get out of sync if you create another instance with CGImage or other methods.
* AppKit:
* NSImage currently only support animated via GIF imageRep unlike UIImage.
* The getter of this property will get the loop count from GIF imageRep
@ -23,6 +23,13 @@
*/
@property (nonatomic, assign) NSUInteger sd_imageLoopCount;
/**
* The image format represent the original compressed image data format.
* If you don't manually specify a format, this information is retrieve from CGImage using `CGImageGetUTType`, which may return nil for non-CG based image. At this time it will return `SDImageFormatUndefined` as default value.
* @note Note that because of the limitations of categories this property can get out of sync if you create another instance with CGImage or other methods.
*/
@property (nonatomic, assign) SDImageFormat sd_imageFormat;
+ (nullable UIImage *)sd_imageWithData:(nullable NSData *)data;
- (nullable NSData *)sd_imageData;
- (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat;

View File

@ -7,9 +7,9 @@
*/
#import "UIImage+MultiFormat.h"
#import "objc/runtime.h"
#import "NSImage+WebCache.h"
#import "SDWebImageCodersManager.h"
#import "objc/runtime.h"
@implementation UIImage (MultiFormat)
@ -53,6 +53,28 @@
}
#endif
- (SDImageFormat)sd_imageFormat {
SDImageFormat imageFormat = SDImageFormatUndefined;
NSNumber *value = objc_getAssociatedObject(self, @selector(sd_imageFormat));
if ([value isKindOfClass:[NSNumber class]]) {
imageFormat = value.integerValue;
return imageFormat;
}
// Check CGImage's UTType, may return nil for non-Image/IO based image
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
if (&CGImageGetUTType != NULL) {
CFStringRef uttype = CGImageGetUTType(self.CGImage);
imageFormat = [NSData sd_imageFormatFromUTType:uttype];
}
#pragma clang diagnostic pop
return imageFormat;
}
- (void)setSd_imageFormat:(SDImageFormat)sd_imageFormat {
objc_setAssociatedObject(self, @selector(sd_imageFormat), @(sd_imageFormat), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (nullable UIImage *)sd_imageWithData:(nullable NSData *)data {
return [[SDWebImageCodersManager sharedInstance] decodedImageWithData:data];
}