Skip to content

Commit

Permalink
Keep the information about image's original compressed format, for AP…
Browse files Browse the repository at this point in the history
…I which only contains image but not image data to process extra logic
  • Loading branch information
dreampiggy committed Jul 18, 2018
1 parent 39a2879 commit bb41dbc
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 8 deletions.
16 changes: 12 additions & 4 deletions SDWebImage/NSData+ImageContentType.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 23 additions & 0 deletions SDWebImage/NSData+ImageContentType.m
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,27 @@ + (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format {
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
5 changes: 4 additions & 1 deletion SDWebImage/SDWebImageCodersManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -121,7 +122,9 @@ - (UIImage *)decompressedImageWithImage:(UIImage *)image
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;
Expand Down
2 changes: 2 additions & 0 deletions SDWebImage/SDWebImageCompat.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
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 {
Expand All @@ -57,6 +58,7 @@
}

UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
scaledImage.sd_imageFormat = image.sd_imageFormat;
image = scaledImage;
}
return image;
Expand Down
1 change: 1 addition & 0 deletions SDWebImage/SDWebImageGIFCoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data {

animatedImage = [SDWebImageCoderHelper animatedImageWithFrames:frames];
animatedImage.sd_imageLoopCount = loopCount;
animatedImage.sd_imageFormat = SDImageFormatGIF;
}

CFRelease(source);
Expand Down
3 changes: 3 additions & 0 deletions SDWebImage/SDWebImageImageIOCoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -97,6 +98,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data {
}

UIImage *image = [[UIImage alloc] initWithData:data];
image.sd_imageFormat = [NSData sd_imageFormatForImageData:data];

return image;
}
Expand Down Expand Up @@ -146,6 +148,7 @@ - (UIImage *)incrementallyDecodedImageWithData:(NSData *)data finished:(BOOL)fin
image = [[UIImage alloc] initWithCGImage:partialImageRef size:NSZeroSize];
#endif
CGImageRelease(partialImageRef);
image.sd_imageFormat = [NSData sd_imageFormatForImageData:data];
}
}

Expand Down
3 changes: 3 additions & 0 deletions SDWebImage/SDWebImageWebPCoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data {
}
WebPDemuxDelete(demuxer);
CGContextRelease(canvas);
staticImage.sd_imageFormat = SDImageFormatWebP;
return staticImage;
}

Expand Down Expand Up @@ -145,6 +146,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data {

UIImage *animatedImage = [SDWebImageCoderHelper animatedImageWithFrames:frames];
animatedImage.sd_imageLoopCount = loopCount;
animatedImage.sd_imageFormat = SDImageFormatWebP;

return animatedImage;
}
Expand Down Expand Up @@ -215,6 +217,7 @@ - (UIImage *)incrementallyDecodedImageWithData:(NSData *)data finished:(BOOL)fin
#else
image = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
#endif
image.sd_imageFormat = SDImageFormatWebP;
CGImageRelease(newImageRef);
CGContextRelease(canvas);
}
Expand Down
9 changes: 8 additions & 1 deletion SDWebImage/UIImage+MultiFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,21 @@
* 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
* The setter of this property will set the loop count from GIF imageRep
*/
@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;
Expand Down
26 changes: 24 additions & 2 deletions SDWebImage/UIImage+MultiFormat.m
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -53,6 +53,28 @@ - (void)setSd_imageLoopCount:(NSUInteger)sd_imageLoopCount {
}
#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];
}
Expand Down

0 comments on commit bb41dbc

Please sign in to comment.