UIImage+MultiFormat.m 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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. image = [UIImage imageWithData:data];
  30. }
  31. #endif
  32. else {
  33. image = [[UIImage alloc] initWithData:data];
  34. #if SD_UIKIT || SD_WATCH
  35. UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
  36. if (orientation != UIImageOrientationUp) {
  37. image = [UIImage imageWithCGImage:image.CGImage
  38. scale:image.scale
  39. orientation:orientation];
  40. }
  41. #endif
  42. }
  43. return image;
  44. }
  45. #if SD_UIKIT || SD_WATCH
  46. +(UIImageOrientation)sd_imageOrientationFromImageData:(nonnull NSData *)imageData {
  47. UIImageOrientation result = UIImageOrientationUp;
  48. CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
  49. if (imageSource) {
  50. CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
  51. if (properties) {
  52. CFTypeRef val;
  53. int exifOrientation;
  54. val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);
  55. if (val) {
  56. CFNumberGetValue(val, kCFNumberIntType, &exifOrientation);
  57. result = [self sd_exifOrientationToiOSOrientation:exifOrientation];
  58. } // else - if it's not set it remains at up
  59. CFRelease((CFTypeRef) properties);
  60. } else {
  61. //NSLog(@"NO PROPERTIES, FAIL");
  62. }
  63. CFRelease(imageSource);
  64. }
  65. return result;
  66. }
  67. #pragma mark EXIF orientation tag converter
  68. // Convert an EXIF image orientation to an iOS one.
  69. // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html
  70. + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation {
  71. UIImageOrientation orientation = UIImageOrientationUp;
  72. switch (exifOrientation) {
  73. case 1:
  74. orientation = UIImageOrientationUp;
  75. break;
  76. case 3:
  77. orientation = UIImageOrientationDown;
  78. break;
  79. case 8:
  80. orientation = UIImageOrientationLeft;
  81. break;
  82. case 6:
  83. orientation = UIImageOrientationRight;
  84. break;
  85. case 2:
  86. orientation = UIImageOrientationUpMirrored;
  87. break;
  88. case 4:
  89. orientation = UIImageOrientationDownMirrored;
  90. break;
  91. case 5:
  92. orientation = UIImageOrientationLeftMirrored;
  93. break;
  94. case 7:
  95. orientation = UIImageOrientationRightMirrored;
  96. break;
  97. default:
  98. break;
  99. }
  100. return orientation;
  101. }
  102. #endif
  103. - (nullable NSData *)sd_imageData {
  104. return [self sd_imageDataAsFormat:SDImageFormatUndefined];
  105. }
  106. - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat {
  107. NSData *imageData = nil;
  108. if (self) {
  109. #if SD_UIKIT || SD_WATCH
  110. int alphaInfo = CGImageGetAlphaInfo(self.CGImage);
  111. BOOL hasAlpha = !(alphaInfo == kCGImageAlphaNone ||
  112. alphaInfo == kCGImageAlphaNoneSkipFirst ||
  113. alphaInfo == kCGImageAlphaNoneSkipLast);
  114. BOOL usePNG = hasAlpha;
  115. // the imageFormat param has priority here. But if the format is undefined, we relly on the alpha channel
  116. if (imageFormat != SDImageFormatUndefined) {
  117. usePNG = (imageFormat == SDImageFormatPNG);
  118. }
  119. if (usePNG) {
  120. imageData = UIImagePNGRepresentation(self);
  121. } else {
  122. imageData = UIImageJPEGRepresentation(self, (CGFloat)1.0);
  123. }
  124. #else
  125. NSBitmapImageFileType imageFileType = NSJPEGFileType;
  126. if (imageFormat == SDImageFormatGIF) {
  127. imageFileType = NSGIFFileType;
  128. } else if (imageFormat == SDImageFormatPNG) {
  129. imageFileType = NSPNGFileType;
  130. }
  131. imageData = [NSBitmapImageRep representationOfImageRepsInArray:self.representations
  132. usingType:imageFileType
  133. properties:@{}];
  134. #endif
  135. }
  136. return imageData;
  137. }
  138. @end