| | |
| | | */ |
| | | |
| | | #import "UIImage+MultiFormat.h" |
| | | #import "UIImage+GIF.h" |
| | | #import "NSData+ImageContentType.h" |
| | | #import <ImageIO/ImageIO.h> |
| | | |
| | | #ifdef SD_WEBP |
| | | #import "UIImage+WebP.h" |
| | | #endif |
| | | #import "objc/runtime.h" |
| | | #import "SDWebImageCodersManager.h" |
| | | |
| | | @implementation UIImage (MultiFormat) |
| | | |
| | | #if SD_MAC |
| | | - (NSUInteger)sd_imageLoopCount { |
| | | NSUInteger imageLoopCount = 0; |
| | | for (NSImageRep *rep in self.representations) { |
| | | if ([rep isKindOfClass:[NSBitmapImageRep class]]) { |
| | | NSBitmapImageRep *bitmapRep = (NSBitmapImageRep *)rep; |
| | | imageLoopCount = [[bitmapRep valueForProperty:NSImageLoopCount] unsignedIntegerValue]; |
| | | break; |
| | | } |
| | | } |
| | | return imageLoopCount; |
| | | } |
| | | |
| | | - (void)setSd_imageLoopCount:(NSUInteger)sd_imageLoopCount { |
| | | for (NSImageRep *rep in self.representations) { |
| | | if ([rep isKindOfClass:[NSBitmapImageRep class]]) { |
| | | NSBitmapImageRep *bitmapRep = (NSBitmapImageRep *)rep; |
| | | [bitmapRep setProperty:NSImageLoopCount withValue:@(sd_imageLoopCount)]; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | #else |
| | | |
| | | - (NSUInteger)sd_imageLoopCount { |
| | | NSUInteger imageLoopCount = 0; |
| | | NSNumber *value = objc_getAssociatedObject(self, @selector(sd_imageLoopCount)); |
| | | if ([value isKindOfClass:[NSNumber class]]) { |
| | | imageLoopCount = value.unsignedIntegerValue; |
| | | } |
| | | return imageLoopCount; |
| | | } |
| | | |
| | | - (void)setSd_imageLoopCount:(NSUInteger)sd_imageLoopCount { |
| | | NSNumber *value = @(sd_imageLoopCount); |
| | | objc_setAssociatedObject(self, @selector(sd_imageLoopCount), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
| | | } |
| | | #endif |
| | | |
| | | + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data { |
| | | if (!data) { |
| | | return nil; |
| | | } |
| | | |
| | | UIImage *image; |
| | | SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:data]; |
| | | if (imageFormat == SDImageFormatGIF) { |
| | | image = [UIImage sd_animatedGIFWithData:data]; |
| | | } |
| | | #ifdef SD_WEBP |
| | | else if (imageFormat == SDImageFormatWebP) |
| | | { |
| | | image = [UIImage sd_imageWithWebPData:data]; |
| | | } |
| | | #endif |
| | | else { |
| | | image = [[UIImage alloc] initWithData:data]; |
| | | #if SD_UIKIT || SD_WATCH |
| | | UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data]; |
| | | if (orientation != UIImageOrientationUp) { |
| | | image = [UIImage imageWithCGImage:image.CGImage |
| | | scale:image.scale |
| | | orientation:orientation]; |
| | | } |
| | | #endif |
| | | } |
| | | |
| | | |
| | | return image; |
| | | return [[SDWebImageCodersManager sharedInstance] decodedImageWithData:data]; |
| | | } |
| | | |
| | | #if SD_UIKIT || SD_WATCH |
| | | +(UIImageOrientation)sd_imageOrientationFromImageData:(nonnull NSData *)imageData { |
| | | UIImageOrientation result = UIImageOrientationUp; |
| | | CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); |
| | | if (imageSource) { |
| | | CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); |
| | | if (properties) { |
| | | CFTypeRef val; |
| | | int exifOrientation; |
| | | val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation); |
| | | if (val) { |
| | | CFNumberGetValue(val, kCFNumberIntType, &exifOrientation); |
| | | result = [self sd_exifOrientationToiOSOrientation:exifOrientation]; |
| | | } // else - if it's not set it remains at up |
| | | CFRelease((CFTypeRef) properties); |
| | | } else { |
| | | //NSLog(@"NO PROPERTIES, FAIL"); |
| | | } |
| | | CFRelease(imageSource); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | #pragma mark EXIF orientation tag converter |
| | | // Convert an EXIF image orientation to an iOS one. |
| | | // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html |
| | | + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation { |
| | | UIImageOrientation orientation = UIImageOrientationUp; |
| | | switch (exifOrientation) { |
| | | case 1: |
| | | orientation = UIImageOrientationUp; |
| | | break; |
| | | |
| | | case 3: |
| | | orientation = UIImageOrientationDown; |
| | | break; |
| | | |
| | | case 8: |
| | | orientation = UIImageOrientationLeft; |
| | | break; |
| | | |
| | | case 6: |
| | | orientation = UIImageOrientationRight; |
| | | break; |
| | | |
| | | case 2: |
| | | orientation = UIImageOrientationUpMirrored; |
| | | break; |
| | | |
| | | case 4: |
| | | orientation = UIImageOrientationDownMirrored; |
| | | break; |
| | | |
| | | case 5: |
| | | orientation = UIImageOrientationLeftMirrored; |
| | | break; |
| | | |
| | | case 7: |
| | | orientation = UIImageOrientationRightMirrored; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | return orientation; |
| | | } |
| | | #endif |
| | | |
| | | - (nullable NSData *)sd_imageData { |
| | | return [self sd_imageDataAsFormat:SDImageFormatUndefined]; |
| | |
| | | - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat { |
| | | NSData *imageData = nil; |
| | | if (self) { |
| | | #if SD_UIKIT || SD_WATCH |
| | | int alphaInfo = CGImageGetAlphaInfo(self.CGImage); |
| | | BOOL hasAlpha = !(alphaInfo == kCGImageAlphaNone || |
| | | alphaInfo == kCGImageAlphaNoneSkipFirst || |
| | | alphaInfo == kCGImageAlphaNoneSkipLast); |
| | | |
| | | BOOL usePNG = hasAlpha; |
| | | |
| | | // the imageFormat param has priority here. But if the format is undefined, we relly on the alpha channel |
| | | if (imageFormat != SDImageFormatUndefined) { |
| | | usePNG = (imageFormat == SDImageFormatPNG); |
| | | } |
| | | |
| | | if (usePNG) { |
| | | imageData = UIImagePNGRepresentation(self); |
| | | } else { |
| | | imageData = UIImageJPEGRepresentation(self, (CGFloat)1.0); |
| | | } |
| | | #else |
| | | NSBitmapImageFileType imageFileType = NSJPEGFileType; |
| | | if (imageFormat == SDImageFormatGIF) { |
| | | imageFileType = NSGIFFileType; |
| | | } else if (imageFormat == SDImageFormatPNG) { |
| | | imageFileType = NSPNGFileType; |
| | | } |
| | | |
| | | imageData = [NSBitmapImageRep representationOfImageRepsInArray:self.representations |
| | | usingType:imageFileType |
| | | properties:@{}]; |
| | | #endif |
| | | imageData = [[SDWebImageCodersManager sharedInstance] encodedDataWithImage:self format:imageFormat]; |
| | | } |
| | | return imageData; |
| | | } |