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:
parent
39a28791fd
commit
bb41dbc046
|
@ -32,11 +32,19 @@ typedef NS_ENUM(NSInteger, SDImageFormat) {
|
||||||
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
|
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Convert SDImageFormat to UTType
|
* Convert SDImageFormat to UTType
|
||||||
|
*
|
||||||
@param format Format as SDImageFormat
|
* @param format Format as SDImageFormat
|
||||||
@return The UTType as CFStringRef
|
* @return The UTType as CFStringRef
|
||||||
*/
|
*/
|
||||||
+ (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format;
|
+ (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
|
@end
|
||||||
|
|
|
@ -95,4 +95,27 @@
|
||||||
return UTType;
|
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
|
@end
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#ifdef SD_WEBP
|
#ifdef SD_WEBP
|
||||||
#import "SDWebImageWebPCoder.h"
|
#import "SDWebImageWebPCoder.h"
|
||||||
#endif
|
#endif
|
||||||
|
#import "UIImage+MultiFormat.h"
|
||||||
|
|
||||||
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
|
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
|
||||||
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
|
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
|
||||||
|
@ -121,7 +122,9 @@
|
||||||
UNLOCK(self.codersLock);
|
UNLOCK(self.codersLock);
|
||||||
for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) {
|
for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) {
|
||||||
if ([coder canDecodeFromData:*data]) {
|
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;
|
return nil;
|
||||||
|
|
|
@ -35,6 +35,7 @@ inline UIImage *SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullabl
|
||||||
UIImage *animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];
|
UIImage *animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];
|
||||||
if (animatedImage) {
|
if (animatedImage) {
|
||||||
animatedImage.sd_imageLoopCount = image.sd_imageLoopCount;
|
animatedImage.sd_imageLoopCount = image.sd_imageLoopCount;
|
||||||
|
animatedImage.sd_imageFormat = image.sd_imageFormat;
|
||||||
}
|
}
|
||||||
return animatedImage;
|
return animatedImage;
|
||||||
} else {
|
} 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];
|
UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
|
||||||
|
scaledImage.sd_imageFormat = image.sd_imageFormat;
|
||||||
image = scaledImage;
|
image = scaledImage;
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
|
|
||||||
animatedImage = [SDWebImageCoderHelper animatedImageWithFrames:frames];
|
animatedImage = [SDWebImageCoderHelper animatedImageWithFrames:frames];
|
||||||
animatedImage.sd_imageLoopCount = loopCount;
|
animatedImage.sd_imageLoopCount = loopCount;
|
||||||
|
animatedImage.sd_imageFormat = SDImageFormatGIF;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(source);
|
CFRelease(source);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#import "NSImage+WebCache.h"
|
#import "NSImage+WebCache.h"
|
||||||
#import <ImageIO/ImageIO.h>
|
#import <ImageIO/ImageIO.h>
|
||||||
#import "NSData+ImageContentType.h"
|
#import "NSData+ImageContentType.h"
|
||||||
|
#import "UIImage+MultiFormat.h"
|
||||||
|
|
||||||
#if SD_UIKIT || SD_WATCH
|
#if SD_UIKIT || SD_WATCH
|
||||||
static const size_t kBytesPerPixel = 4;
|
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];
|
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||||
|
image.sd_imageFormat = [NSData sd_imageFormatForImageData:data];
|
||||||
|
|
||||||
return image;
|
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];
|
image = [[UIImage alloc] initWithCGImage:partialImageRef size:NSZeroSize];
|
||||||
#endif
|
#endif
|
||||||
CGImageRelease(partialImageRef);
|
CGImageRelease(partialImageRef);
|
||||||
|
image.sd_imageFormat = [NSData sd_imageFormatForImageData:data];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,7 @@
|
||||||
}
|
}
|
||||||
WebPDemuxDelete(demuxer);
|
WebPDemuxDelete(demuxer);
|
||||||
CGContextRelease(canvas);
|
CGContextRelease(canvas);
|
||||||
|
staticImage.sd_imageFormat = SDImageFormatWebP;
|
||||||
return staticImage;
|
return staticImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +146,7 @@
|
||||||
|
|
||||||
UIImage *animatedImage = [SDWebImageCoderHelper animatedImageWithFrames:frames];
|
UIImage *animatedImage = [SDWebImageCoderHelper animatedImageWithFrames:frames];
|
||||||
animatedImage.sd_imageLoopCount = loopCount;
|
animatedImage.sd_imageLoopCount = loopCount;
|
||||||
|
animatedImage.sd_imageFormat = SDImageFormatWebP;
|
||||||
|
|
||||||
return animatedImage;
|
return animatedImage;
|
||||||
}
|
}
|
||||||
|
@ -215,6 +217,7 @@
|
||||||
#else
|
#else
|
||||||
image = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
|
image = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
|
||||||
#endif
|
#endif
|
||||||
|
image.sd_imageFormat = SDImageFormatWebP;
|
||||||
CGImageRelease(newImageRef);
|
CGImageRelease(newImageRef);
|
||||||
CGContextRelease(canvas);
|
CGContextRelease(canvas);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* UIKit:
|
* UIKit:
|
||||||
* For static image format, this value is always 0.
|
* For static image format, this value is always 0.
|
||||||
* For animated image format, 0 means infinite looping.
|
* 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:
|
* AppKit:
|
||||||
* NSImage currently only support animated via GIF imageRep unlike UIImage.
|
* NSImage currently only support animated via GIF imageRep unlike UIImage.
|
||||||
* The getter of this property will get the loop count from GIF imageRep
|
* The getter of this property will get the loop count from GIF imageRep
|
||||||
|
@ -23,6 +23,13 @@
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, assign) NSUInteger sd_imageLoopCount;
|
@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 UIImage *)sd_imageWithData:(nullable NSData *)data;
|
||||||
- (nullable NSData *)sd_imageData;
|
- (nullable NSData *)sd_imageData;
|
||||||
- (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat;
|
- (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat;
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import "UIImage+MultiFormat.h"
|
#import "UIImage+MultiFormat.h"
|
||||||
|
#import "NSImage+WebCache.h"
|
||||||
#import "objc/runtime.h"
|
|
||||||
#import "SDWebImageCodersManager.h"
|
#import "SDWebImageCodersManager.h"
|
||||||
|
#import "objc/runtime.h"
|
||||||
|
|
||||||
@implementation UIImage (MultiFormat)
|
@implementation UIImage (MultiFormat)
|
||||||
|
|
||||||
|
@ -53,6 +53,28 @@
|
||||||
}
|
}
|
||||||
#endif
|
#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 {
|
+ (nullable UIImage *)sd_imageWithData:(nullable NSData *)data {
|
||||||
return [[SDWebImageCodersManager sharedInstance] decodedImageWithData:data];
|
return [[SDWebImageCodersManager sharedInstance] decodedImageWithData:data];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue