SDWebImage源码阅读(十三)UIImage+MultiFormat

  这个 UIImage 的一个叫 MultiFormat 的分类,看名字可能已经猜到,UIImage 的多版本,主要功能是用来做 NSData 和  UIImage 的相互转化的。

  .h

1 + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data;
2 - (nullable NSData *)sd_imageData;
3 - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat;

  定义了 3 个方法,基本只是看方法名和返回值,已经基本猜到各个方法要实现的功能。

  1.这是一个类方法,一个NSData 对象做参数,转化为一个  UIImage 对象返回。

  2.这是一个实例方法,把调取该方法的 UIImage 对象的 NSData 数据返回。

  3.获取 UIImage 的指定图片类型的 NSData 数据。

  .m

 1 + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data {
 2     if (!data) {
 3         return nil;
 4     }
 5     
 6     UIImage *image;
 7     SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:data];
 8     if (imageFormat == SDImageFormatGIF) {
 9         image = [UIImage sd_animatedGIFWithData:data];
10     }
11 #ifdef SD_WEBP
12     else if (imageFormat == SDImageFormatWebP)
13     {
14         image = [UIImage sd_imageWithWebPData:data];
15     }
16 #endif
17     else {
18         image = [[UIImage alloc] initWithData:data];
19 #if SD_UIKIT || SD_WATCH
20         UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
21         if (orientation != UIImageOrientationUp) {
22             image = [UIImage imageWithCGImage:image.CGImage
23                                         scale:image.scale
24                                   orientation:orientation];
25         }
26 #endif
27     }
28 
29 
30     return image;
31 }

  把 NSData 转化为 UIImage。

  如果 data 不存在,则直接返回 nil。

  根据 data 判断 UIImage 的后缀类型并赋值给 imageFormat。

  如果 imageFormat 是 SDImageFormatGIF,调用 sd_animatedGIFWithData: 把 data 转化为图片。

  如果 imageFormat 是 SDImageFormatWebP 则做相应的处理,这里并没有给出。

  其他的情况:

  直接调用 initWithData: 把 data 转化为 UIImage。

  如果是 iOS 平台开发或者 TV 平台开发或者 WATCH 平台开发,使用 data 调用 sd_imageOrientationFromImageData: 获取图片的方向并赋值给 orientation。

  如果 orientation 不等于 UIImageOrientationUP (默认方向),则调用:

1 + (UIImage *)imageWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(4_0);

  重新调整图片方向。

  最后返回 iamge。

 1 +(UIImageOrientation)sd_imageOrientationFromImageData:(nonnull NSData *)imageData {
 2     UIImageOrientation result = UIImageOrientationUp;
 3     CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
 4     if (imageSource) {
 5         CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
 6         if (properties) {
 7             CFTypeRef val;
 8             int exifOrientation;
 9             val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);
10             if (val) {
11                 CFNumberGetValue(val, kCFNumberIntType, &exifOrientation);
12                 result = [self sd_exifOrientationToiOSOrientation:exifOrientation];
13             } // else - if it's not set it remains at up
14             CFRelease((CFTypeRef) properties);
15         } else {
16             //NSLog(@"NO PROPERTIES, FAIL");
17         }
18         CFRelease(imageSource);
19     }
20     return result;
21 }

   根据 imageData 获取图片的方向。

 1 #pragma mark EXIF orientation tag converter
 2 // Convert an EXIF image orientation to an iOS one.
 3 // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html
 4 + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation {
 5     UIImageOrientation orientation = UIImageOrientationUp;
 6     switch (exifOrientation) {
 7         case 1:
 8             orientation = UIImageOrientationUp;
 9             break;
10 
11         case 3:
12             orientation = UIImageOrientationDown;
13             break;
14 
15         case 8:
16             orientation = UIImageOrientationLeft;
17             break;
18 
19         case 6:
20             orientation = UIImageOrientationRight;
21             break;
22 
23         case 2:
24             orientation = UIImageOrientationUpMirrored;
25             break;
26 
27         case 4:
28             orientation = UIImageOrientationDownMirrored;
29             break;
30 
31         case 5:
32             orientation = UIImageOrientationLeftMirrored;
33             break;
34 
35         case 7:
36             orientation = UIImageOrientationRightMirrored;
37             break;
38         default:
39             break;
40     }
41     return orientation;
42 }
43 #endif

  根据 exifOrientation 获得对应的 UIImageOrientation。

 1 - (nullable NSData *)sd_imageData {
 2     return [self sd_imageDataAsFormat:SDImageFormatUndefined];
 3 }
 4 
 5 - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat {
 6     NSData *imageData = nil;
 7     if (self) {
 8 #if SD_UIKIT || SD_WATCH
 9         int alphaInfo = CGImageGetAlphaInfo(self.CGImage);
10         BOOL hasAlpha = !(alphaInfo == kCGImageAlphaNone ||
11                           alphaInfo == kCGImageAlphaNoneSkipFirst ||
12                           alphaInfo == kCGImageAlphaNoneSkipLast);
13         
14         BOOL usePNG = hasAlpha;
15         
16         // the imageFormat param has priority here. But if the format is undefined, we relly on the alpha channel
17         if (imageFormat != SDImageFormatUndefined) {
18             usePNG = (imageFormat == SDImageFormatPNG);
19         }
20         
21         if (usePNG) {
22             imageData = UIImagePNGRepresentation(self);
23         } else {
24             imageData = UIImageJPEGRepresentation(self, (CGFloat)1.0);
25         }
26 #else
27         NSBitmapImageFileType imageFileType = NSJPEGFileType;
28         if (imageFormat == SDImageFormatGIF) {
29             imageFileType = NSGIFFileType;
30         } else if (imageFormat == SDImageFormatPNG) {
31             imageFileType = NSPNGFileType;
32         }
33         
34         imageData = [NSBitmapImageRep representationOfImageRepsInArray:self.representations
35                                                              usingType:imageFileType
36                                                             properties:@{}];
37 #endif
38     }
39     return imageData;
40 }

  获取 UIImage 对象的 NSData 数据。

  当不指定 imageFormat 的时候,使用 SDImageFormatUndefined。

  当 imageFormat 是 SDImageFormatUndefined 的时候根据 alphaInfo 判断,hasAlpha 是假的时候(没有 alpha 信息的时候)使用 

UIImageJPEGRepresentation 转化,把 UIImage 对象转化为 JPEG 类型的 NSData 数据,相反的有 alpha 的时候转化为 PNG 类型的 NSData 数据。

  如果 imageFormat  是 SDImageFormatPNG 的时候,则直接转化为 PNG 类型NSData 数据。

  下面有一篇:

1 UIKIT_EXTERN  NSData * __nullable UIImagePNGRepresentation(UIImage * __nonnull image);                               // return image as PNG. May return nil if image has no CGImageRef or invalid bitmap format
2 UIKIT_EXTERN  NSData * __nullable UIImageJPEGRepresentation(UIImage * __nonnull image, CGFloat compressionQuality);  // return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least)

  两者的比较。

 

参考链接:http://blog.csdn.net/mideveloper/article/details/11473627

http://www.jianshu.com/p/b9d415188c42

 

END 

posted @ 2017-06-10 12:28  鳄鱼不怕牙医不怕  阅读(535)  评论(0编辑  收藏  举报