UIImage+NIMKit.m 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. //
  2. // UIImage+NIMKit.m
  3. // NIMKit
  4. //
  5. // Created by chris.
  6. // Copyright (c) 2015年 NetEase. All rights reserved.
  7. //
  8. #import "UIImage+NIMKit.h"
  9. #import "NIMInputEmoticonDefine.h"
  10. #import "NIMKit.h"
  11. #import "NIMKitDevice.h"
  12. @implementation UIImage (NIMKit)
  13. + (UIImage *)nim_fetchEmoticon:(NSString *)imageNameOrPath{
  14. UIImage *image = [UIImage nim_emoticonInKit:imageNameOrPath];
  15. if (!image) {
  16. image = [UIImage imageWithContentsOfFile:imageNameOrPath];
  17. }
  18. return image;
  19. }
  20. + (UIImage *)nim_fetchChartlet:(NSString *)imageName chartletId:(NSString *)chartletId{
  21. if ([chartletId isEqualToString:NIMKit_EmojiCatalog]) {
  22. return [UIImage imageNamed:imageName];
  23. }
  24. NSString *subDirectory = [NSString stringWithFormat:@"%@/%@/%@",NIMKit_ChartletChartletCatalogPath,chartletId,NIMKit_ChartletChartletCatalogContentPath];
  25. //先拿2倍图
  26. NSString *doubleImage = [imageName stringByAppendingString:@"@2x"];
  27. NSString *tribleImage = [imageName stringByAppendingString:@"@3x"];
  28. NSString *bundlePath = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:subDirectory];
  29. NSString *path = nil;
  30. NSArray *array = [NSBundle pathsForResourcesOfType:nil inDirectory:bundlePath];
  31. NSString *fileExt = [[array.firstObject lastPathComponent] pathExtension];
  32. if ([UIScreen mainScreen].scale == 3.0) {
  33. path = [NSBundle pathForResource:tribleImage ofType:fileExt inDirectory:bundlePath];
  34. }
  35. path = path ? path : [NSBundle pathForResource:doubleImage ofType:fileExt inDirectory:bundlePath]; //取二倍图
  36. path = path ? path : [NSBundle pathForResource:imageName ofType:fileExt inDirectory:bundlePath]; //实在没了就去取一倍图
  37. return [UIImage imageWithContentsOfFile:path];
  38. }
  39. + (CGSize)nim_sizeWithImageOriginSize:(CGSize)originSize
  40. minSize:(CGSize)imageMinSize
  41. maxSize:(CGSize)imageMaxSiz{
  42. CGSize size;
  43. NSInteger imageWidth = originSize.width ,imageHeight = originSize.height;
  44. NSInteger imageMinWidth = imageMinSize.width, imageMinHeight = imageMinSize.height;
  45. NSInteger imageMaxWidth = imageMaxSiz.width, imageMaxHeight = imageMaxSiz.height;
  46. if (imageWidth > imageHeight) //宽图
  47. {
  48. size.height = imageMinHeight; //高度取最小高度
  49. size.width = imageWidth * imageMinHeight / imageHeight;
  50. if (size.width > imageMaxWidth)
  51. {
  52. size.width = imageMaxWidth;
  53. }
  54. }
  55. else if(imageWidth < imageHeight)//高图
  56. {
  57. size.width = imageMinWidth;
  58. size.height = imageHeight *imageMinWidth / imageWidth;
  59. if (size.height > imageMaxHeight)
  60. {
  61. size.height = imageMaxHeight;
  62. }
  63. }
  64. else//方图
  65. {
  66. if (imageWidth > imageMaxWidth)
  67. {
  68. size.width = imageMaxWidth;
  69. size.height = imageMaxHeight;
  70. }
  71. else if(imageWidth > imageMinWidth)
  72. {
  73. size.width = imageWidth;
  74. size.height = imageHeight;
  75. }
  76. else
  77. {
  78. size.width = imageMinWidth;
  79. size.height = imageMinHeight;
  80. }
  81. }
  82. return size;
  83. }
  84. + (UIImage *)nim_imageInKit:(NSString *)imageName{
  85. NSString *name = [[[NIMKit sharedKit] resourceBundleName] stringByAppendingPathComponent:imageName];
  86. UIImage *image = [UIImage imageNamed:imageName];
  87. //优先取上层bundle 里的图片,如果没有,则用自带资源的图片
  88. return image? image : [UIImage imageNamed:name];
  89. }
  90. + (UIImage *)nim_emoticonInKit:(NSString *)imageName
  91. {
  92. NSString *name = [[[NIMKit sharedKit] emoticonBundleName] stringByAppendingPathComponent:imageName];
  93. UIImage *image = [UIImage imageNamed:name];
  94. return image;
  95. }
  96. - (UIImage *)nim_imageForAvatarUpload
  97. {
  98. CGFloat pixels = [[NIMKitDevice currentDevice] suggestImagePixels];
  99. UIImage * image = [self nim_imageForUpload:pixels];
  100. return [image nim_fixOrientation];
  101. }
  102. #pragma mark - Private
  103. - (UIImage *)nim_imageForUpload: (CGFloat)suggestPixels
  104. {
  105. CGFloat maxPixels = 4000000;
  106. CGFloat maxRatio = 3;
  107. CGFloat width = self.size.width;
  108. CGFloat height= self.size.height;
  109. //对于超过建议像素,且长宽比超过max ratio的图做特殊处理
  110. if (width * height > suggestPixels &&
  111. (width / height > maxRatio || height / width > maxRatio))
  112. {
  113. return [self nim_scaleWithMaxPixels:maxPixels];
  114. }
  115. else
  116. {
  117. return [self nim_scaleWithMaxPixels:suggestPixels];
  118. }
  119. }
  120. - (UIImage *)nim_scaleWithMaxPixels: (CGFloat)maxPixels
  121. {
  122. CGFloat width = self.size.width;
  123. CGFloat height= self.size.height;
  124. if (width * height < maxPixels || maxPixels == 0)
  125. {
  126. return self;
  127. }
  128. CGFloat ratio = sqrt(width * height / maxPixels);
  129. if (fabs(ratio - 1) <= 0.01)
  130. {
  131. return self;
  132. }
  133. CGFloat newSizeWidth = width / ratio;
  134. CGFloat newSizeHeight= height/ ratio;
  135. return [self nim_scaleToSize:CGSizeMake(newSizeWidth, newSizeHeight)];
  136. }
  137. //内缩放,一条变等于最长边,另外一条小于等于最长边
  138. - (UIImage *)nim_scaleToSize:(CGSize)newSize
  139. {
  140. CGFloat width = self.size.width;
  141. CGFloat height= self.size.height;
  142. CGFloat newSizeWidth = newSize.width;
  143. CGFloat newSizeHeight= newSize.height;
  144. if (width <= newSizeWidth &&
  145. height <= newSizeHeight)
  146. {
  147. return self;
  148. }
  149. if (width == 0 || height == 0 || newSizeHeight == 0 || newSizeWidth == 0)
  150. {
  151. return nil;
  152. }
  153. CGSize size;
  154. if (width / height > newSizeWidth / newSizeHeight)
  155. {
  156. size = CGSizeMake(newSizeWidth, newSizeWidth * height / width);
  157. }
  158. else
  159. {
  160. size = CGSizeMake(newSizeHeight * width / height, newSizeHeight);
  161. }
  162. return [self nim_drawImageWithSize:size];
  163. }
  164. - (UIImage *)nim_drawImageWithSize: (CGSize)size
  165. {
  166. CGSize drawSize = CGSizeMake(floor(size.width), floor(size.height));
  167. // 传入的View.frame.size是0的话,直接返回nil,防止 UIGraphicsBeginImageContext() 传入0,导致崩溃
  168. if (CGSizeEqualToSize(size, CGSizeZero)) {
  169. return nil;
  170. }
  171. UIGraphicsBeginImageContext(drawSize);
  172. [self drawInRect:CGRectMake(0, 0, drawSize.width, drawSize.height)];
  173. UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
  174. UIGraphicsEndImageContext();
  175. return newImage;
  176. }
  177. - (UIImage *)nim_fixOrientation
  178. {
  179. // No-op if the orientation is already correct
  180. if (self.imageOrientation == UIImageOrientationUp)
  181. return self;
  182. // We need to calculate the proper transformation to make the image upright.
  183. // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
  184. CGAffineTransform transform = CGAffineTransformIdentity;
  185. switch (self.imageOrientation) {
  186. case UIImageOrientationDown:
  187. case UIImageOrientationDownMirrored:
  188. transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
  189. transform = CGAffineTransformRotate(transform, M_PI);
  190. break;
  191. case UIImageOrientationLeft:
  192. case UIImageOrientationLeftMirrored:
  193. transform = CGAffineTransformTranslate(transform, self.size.width, 0);
  194. transform = CGAffineTransformRotate(transform, M_PI_2);
  195. break;
  196. case UIImageOrientationRight:
  197. case UIImageOrientationRightMirrored:
  198. transform = CGAffineTransformTranslate(transform, 0, self.size.height);
  199. transform = CGAffineTransformRotate(transform, -M_PI_2);
  200. break;
  201. default:
  202. break;
  203. }
  204. switch (self.imageOrientation) {
  205. case UIImageOrientationUpMirrored:
  206. case UIImageOrientationDownMirrored:
  207. transform = CGAffineTransformTranslate(transform, self.size.width, 0);
  208. transform = CGAffineTransformScale(transform, -1, 1);
  209. break;
  210. case UIImageOrientationLeftMirrored:
  211. case UIImageOrientationRightMirrored:
  212. transform = CGAffineTransformTranslate(transform, self.size.height, 0);
  213. transform = CGAffineTransformScale(transform, -1, 1);
  214. break;
  215. default:
  216. break;
  217. }
  218. // Now we draw the underlying CGImage into a new context, applying the transform
  219. // calculated above.
  220. CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
  221. CGImageGetBitsPerComponent(self.CGImage), 0,
  222. CGImageGetColorSpace(self.CGImage),
  223. CGImageGetBitmapInfo(self.CGImage));
  224. CGContextConcatCTM(ctx, transform);
  225. switch (self.imageOrientation) {
  226. case UIImageOrientationLeft:
  227. case UIImageOrientationLeftMirrored:
  228. case UIImageOrientationRight:
  229. case UIImageOrientationRightMirrored:
  230. // Grr...
  231. CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
  232. break;
  233. default:
  234. CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
  235. break;
  236. }
  237. // And now we just create a new UIImage from the drawing context
  238. CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
  239. UIImage *img = [UIImage imageWithCGImage:cgimg];
  240. CGContextRelease(ctx);
  241. CGImageRelease(cgimg);
  242. return img;
  243. }
  244. @end