UIImage+MultiFormat.m 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * This file is part of the SDWebImage package.
  3. * (c) Olivier Poitrey <rs@dailymotion.com>
  4. *
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. */
  8. #import "UIImage+MultiFormat.h"
  9. #import "UIImage+GIF.h"
  10. #import "NSData+ImageContentType.h"
  11. #import <ImageIO/ImageIO.h>
  12. #ifdef SD_WEBP
  13. #import "UIImage+WebP.h"
  14. #endif
  15. @implementation UIImage (MultiFormat)
  16. + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data {
  17. if (!data) {
  18. return nil;
  19. }
  20. UIImage *image;
  21. SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:data];
  22. if (imageFormat == SDImageFormatGIF) {
  23. image = [UIImage sd_animatedGIFWithData:data];
  24. }
  25. #ifdef SD_WEBP
  26. else if (imageFormat == SDImageFormatWebP)
  27. {
  28. image = [UIImage sd_imageWithWebPData:data];
  29. }
  30. #endif
  31. else {
  32. image = [[UIImage alloc] initWithData:data];
  33. #if SD_UIKIT || SD_WATCH
  34. UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
  35. if (orientation != UIImageOrientationUp) {
  36. image = [UIImage imageWithCGImage:image.CGImage
  37. scale:image.scale
  38. orientation:orientation];
  39. }
  40. #endif
  41. }
  42. return image;
  43. }
  44. #if SD_UIKIT || SD_WATCH
  45. +(UIImageOrientation)sd_imageOrientationFromImageData:(nonnull NSData *)imageData {
  46. UIImageOrientation result = UIImageOrientationUp;
  47. CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
  48. if (imageSource) {
  49. CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
  50. if (properties) {
  51. CFTypeRef val;
  52. int exifOrientation;
  53. val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);
  54. if (val) {
  55. CFNumberGetValue(val, kCFNumberIntType, &exifOrientation);
  56. result = [self sd_exifOrientationToiOSOrientation:exifOrientation];
  57. } // else - if it's not set it remains at up
  58. CFRelease((CFTypeRef) properties);
  59. } else {
  60. //NSLog(@"NO PROPERTIES, FAIL");
  61. }
  62. CFRelease(imageSource);
  63. }
  64. return result;
  65. }
  66. #pragma mark EXIF orientation tag converter
  67. // Convert an EXIF image orientation to an iOS one.
  68. // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html
  69. + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation {
  70. UIImageOrientation orientation = UIImageOrientationUp;
  71. switch (exifOrientation) {
  72. case 1:
  73. orientation = UIImageOrientationUp;
  74. break;
  75. case 3:
  76. orientation = UIImageOrientationDown;
  77. break;
  78. case 8:
  79. orientation = UIImageOrientationLeft;
  80. break;
  81. case 6:
  82. orientation = UIImageOrientationRight;
  83. break;
  84. case 2:
  85. orientation = UIImageOrientationUpMirrored;
  86. break;
  87. case 4:
  88. orientation = UIImageOrientationDownMirrored;
  89. break;
  90. case 5:
  91. orientation = UIImageOrientationLeftMirrored;
  92. break;
  93. case 7:
  94. orientation = UIImageOrientationRightMirrored;
  95. break;
  96. default:
  97. break;
  98. }
  99. return orientation;
  100. }
  101. #endif
  102. - (nullable NSData *)sd_imageData {
  103. return [self sd_imageDataAsFormat:SDImageFormatUndefined];
  104. }
  105. - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat {
  106. NSData *imageData = nil;
  107. if (self) {
  108. #if SD_UIKIT || SD_WATCH
  109. int alphaInfo = CGImageGetAlphaInfo(self.CGImage);
  110. BOOL hasAlpha = !(alphaInfo == kCGImageAlphaNone ||
  111. alphaInfo == kCGImageAlphaNoneSkipFirst ||
  112. alphaInfo == kCGImageAlphaNoneSkipLast);
  113. BOOL usePNG = hasAlpha;
  114. // the imageFormat param has priority here. But if the format is undefined, we relly on the alpha channel
  115. if (imageFormat != SDImageFormatUndefined) {
  116. usePNG = (imageFormat == SDImageFormatPNG);
  117. }
  118. if (usePNG) {
  119. imageData = UIImagePNGRepresentation(self);
  120. } else {
  121. imageData = UIImageJPEGRepresentation(self, (CGFloat)1.0);
  122. }
  123. #else
  124. NSBitmapImageFileType imageFileType = NSJPEGFileType;
  125. if (imageFormat == SDImageFormatGIF) {
  126. imageFileType = NSGIFFileType;
  127. } else if (imageFormat == SDImageFormatPNG) {
  128. imageFileType = NSPNGFileType;
  129. }
  130. imageData = [NSBitmapImageRep representationOfImageRepsInArray:self.representations
  131. usingType:imageFileType
  132. properties:@{}];
  133. #endif
  134. }
  135. return imageData;
  136. }
  137. @end