UIImage+Extension.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. //
  2. // UIImage+Extension.m
  3. // MIT_Endorsement
  4. //
  5. // Created by 翟玉磊 on 2017/12/15.
  6. // Copyright © 2017年 翟玉磊. All rights reserved.
  7. //
  8. #import "UIImage+Extension.h"
  9. #import <AVFoundation/AVFoundation.h>
  10. #import <AssetsLibrary/AssetsLibrary.h>
  11. #import <Accelerate/Accelerate.h>
  12. static NSTimeInterval const ThumbnailImageTime = 10.0f;
  13. @implementation UIImage (Extension)
  14. /**
  15. * 根据图片名返回一张能够自由拉伸的图片 (从中间拉伸)
  16. */
  17. + (UIImage *)resizableImage:(NSString *)imgName
  18. {
  19. return [self resizableImage:imgName xPos:0.5 yPos:0.5];;
  20. }
  21. /**
  22. * 根据图片名返回一张能够自由拉伸的图片
  23. */
  24. + (UIImage *)resizableImage:(NSString *)imgName xPos:(CGFloat)xPos yPos:(CGFloat)yPos
  25. {
  26. UIImage *image = [UIImage imageNamed:imgName];
  27. return [image stretchableImageWithLeftCapWidth:image.size.width * xPos topCapHeight:image.size.height * yPos];
  28. }
  29. /**
  30. * 获取视频第一帧图片
  31. */
  32. + (UIImage *)getVideoFirstThumbnailImageWithVideoUrl:(NSURL *)videoUrl
  33. {
  34. AVURLAsset*asset = [[AVURLAsset alloc] initWithURL:videoUrl options:nil];
  35. NSParameterAssert(asset);
  36. AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:asset];
  37. assetImageGenerator.appliesPreferredTrackTransform = YES;
  38. assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
  39. CGImageRef thumbnailImageRef = nil;
  40. CFTimeInterval thumbnailImageTime = ThumbnailImageTime;
  41. NSError *thumbnailImageGenerationError = nil;
  42. thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 1.0f) actualTime:nil error:&thumbnailImageGenerationError];
  43. if(!thumbnailImageRef)
  44. {
  45. NSLog(@"======thumbnailImageGenerationError======= %@",thumbnailImageGenerationError);
  46. }
  47. return thumbnailImageRef ? [[UIImage alloc] initWithCGImage:thumbnailImageRef] : nil;
  48. }
  49. /// 根据url获取第一帧图片,获取任一帧图片
  50. - (UIImage *)thumbnailImageForVideo:(NSURL *)videoURL atTime:(NSTimeInterval)time {
  51. AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
  52. NSParameterAssert(asset);
  53. AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:asset];
  54. assetImageGenerator.appliesPreferredTrackTransform = YES;
  55. assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
  56. CGImageRef thumbnailImageRef = NULL;
  57. CFTimeInterval thumbnailImageTime = time;
  58. NSError *thumbnailImageGenerationError = nil;
  59. thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60)actualTime:NULL error:&thumbnailImageGenerationError];
  60. if(!thumbnailImageRef)
  61. NSLog(@"thumbnailImageGenerationError %@",thumbnailImageGenerationError);
  62. UIImage*thumbnailImage = thumbnailImageRef ? [[UIImage alloc]initWithCGImage: thumbnailImageRef] : nil;
  63. return thumbnailImage;
  64. }
  65. /**
  66. * 图片不被渲染
  67. *
  68. */
  69. + (UIImage *)imageAlwaysShowOriginalImageWithImageName:(NSString *)imageName
  70. {
  71. UIImage *image = [UIImage imageNamed:imageName];
  72. if ([image respondsToSelector:@selector(imageWithRenderingMode:)])
  73. { //iOS 7.0+
  74. return [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  75. }else{
  76. return image;
  77. }
  78. }
  79. /**
  80. * 根据图片和颜色返回一张加深颜色以后的图片
  81. * 图片着色
  82. */
  83. + (UIImage *)colorizeImageWithSourceImage:(UIImage *)sourceImage color:(UIColor *)color
  84. {
  85. UIGraphicsBeginImageContext(CGSizeMake(sourceImage.size.width*2, sourceImage.size.height*2));
  86. CGContextRef ctx = UIGraphicsGetCurrentContext();
  87. CGRect area = CGRectMake(0, 0, sourceImage.size.width * 2, sourceImage.size.height * 2);
  88. CGContextScaleCTM(ctx, 1, -1);
  89. CGContextTranslateCTM(ctx, 0, -area.size.height);
  90. CGContextSaveGState(ctx);
  91. CGContextClipToMask(ctx, area, sourceImage.CGImage);
  92. [color set];
  93. CGContextFillRect(ctx, area);
  94. CGContextRestoreGState(ctx);
  95. CGContextSetBlendMode(ctx, kCGBlendModeMultiply);
  96. CGContextDrawImage(ctx, area, sourceImage.CGImage);
  97. UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
  98. UIGraphicsEndImageContext();
  99. return destImage;
  100. }
  101. /**
  102. * 根据指定的图片颜色和图片大小获取指定的Image
  103. *
  104. * @param color 颜色
  105. * @param size 大小
  106. *
  107. */
  108. + (UIImage *)getImageWithColor:(UIColor *)color size:(CGSize)size
  109. {
  110. UIGraphicsBeginImageContextWithOptions(size, 0, [UIScreen mainScreen].scale);
  111. [color set];
  112. UIRectFill(CGRectMake(0, 0, size.width, size.height));
  113. UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
  114. UIGraphicsEndImageContext();
  115. return destImage;
  116. }
  117. /**
  118. * 通过传入一个图片对象获取一张缩略图
  119. */
  120. + (UIImage *)getThumbnailImageWithImageObj:(id)imageObj
  121. {
  122. __block UIImage *image = nil;
  123. if ([imageObj isKindOfClass:[UIImage class]]) {
  124. return imageObj;
  125. }else if ([imageObj isKindOfClass:[ALAsset class]]){
  126. @autoreleasepool {
  127. ALAsset *asset = (ALAsset *)imageObj;
  128. return [UIImage imageWithCGImage:[asset aspectRatioThumbnail]];
  129. }
  130. }
  131. return image;
  132. }
  133. /**
  134. * 通过传入一个图片对象获取一张原始图
  135. */
  136. + (UIImage *)getOriginalImageWithImageObj:(id)imageObj
  137. {
  138. __block UIImage *image = nil;
  139. if ([imageObj isKindOfClass:[UIImage class]]) {
  140. return imageObj;
  141. }else if ([imageObj isKindOfClass:[ALAsset class]]){
  142. @autoreleasepool {
  143. ALAsset *asset = (ALAsset *)imageObj;
  144. return [UIImage imageWithCGImage:asset.defaultRepresentation.fullScreenImage];
  145. }
  146. }
  147. return image;
  148. }
  149. + (UIImage *)gradientColorImageFromColors:(NSArray*)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize {
  150. NSMutableArray *ar = [NSMutableArray array];
  151. for(UIColor *c in colors) {
  152. [ar addObject:(id)c.CGColor];
  153. }
  154. UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1);
  155. CGContextRef context = UIGraphicsGetCurrentContext();
  156. CGContextSaveGState(context);
  157. CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]);
  158. CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)ar, NULL);
  159. CGPoint start;
  160. CGPoint end;
  161. switch (gradientType) {
  162. case GradientTypeTopToBottom:
  163. start = CGPointMake(0.0, 0.0);
  164. end = CGPointMake(0.0, imgSize.height);
  165. break;
  166. case GradientTypeLeftToRight:
  167. start = CGPointMake(0.0, 0.0);
  168. end = CGPointMake(imgSize.width, 0.0);
  169. break;
  170. case GradientTypeUpleftToLowright:
  171. start = CGPointMake(0.0, 0.0);
  172. end = CGPointMake(imgSize.width, imgSize.height);
  173. break;
  174. case GradientTypeUprightToLowleft:
  175. start = CGPointMake(imgSize.width, 0.0);
  176. end = CGPointMake(0.0, imgSize.height);
  177. break;
  178. default:
  179. break;
  180. }
  181. CGContextDrawLinearGradient(context, gradient, start, end,kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
  182. UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  183. CGGradientRelease(gradient);
  184. CGContextRestoreGState(context);
  185. CGColorSpaceRelease(colorSpace);
  186. UIGraphicsEndImageContext();
  187. return image;
  188. }
  189. /// 常用蓝色渐变图片
  190. + (UIImage *)commonRedGradientColorImageWithImgSize:(CGSize)imgSize {
  191. UIImage *image = [UIImage gradientColorImageFromColors:@[ColorFromHexString(@"#5D26FF"), ColorFromHexString(@"#9059FF")] gradientType:GradientTypeLeftToRight imgSize:imgSize];
  192. return image;
  193. }
  194. /// 获取模糊效果的图片
  195. /// @param image 要模糊的图片
  196. /// @param blur 要模糊的程度
  197. + (UIImage *)boxblurImage:(UIImage *)image withBlurNumber:(CGFloat)blur {
  198. if (blur < 0.f || blur > 1.f) {
  199. blur = 0.5f;
  200. }
  201. int boxSize = (int)(blur * 40);
  202. boxSize = boxSize - (boxSize % 2) + 1;
  203. CGImageRef img = image.CGImage;
  204. vImage_Buffer inBuffer, outBuffer;
  205. vImage_Error error;
  206. void *pixelBuffer;
  207. //从CGImage中获取数据
  208. CGDataProviderRef inProvider = CGImageGetDataProvider(img);
  209. CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
  210. //设置从CGImage获取对象的属性
  211. inBuffer.width = CGImageGetWidth(img);
  212. inBuffer.height = CGImageGetHeight(img);
  213. inBuffer.rowBytes = CGImageGetBytesPerRow(img);
  214. inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
  215. pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
  216. if(pixelBuffer == NULL)
  217. NSLog(@"No pixelbuffer");
  218. outBuffer.data = pixelBuffer;
  219. outBuffer.width = CGImageGetWidth(img);
  220. outBuffer.height = CGImageGetHeight(img);
  221. outBuffer.rowBytes = CGImageGetBytesPerRow(img);
  222. error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
  223. if(error){
  224. NSLog(@"error from convolution %ld", error);
  225. }
  226. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  227. CGContextRef ctx = CGBitmapContextCreate( outBuffer.data, outBuffer.width, outBuffer.height, 8, outBuffer.rowBytes, colorSpace, kCGImageAlphaNoneSkipLast);
  228. CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
  229. UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
  230. //clean up CGContextRelease(ctx)
  231. CGColorSpaceRelease(colorSpace);
  232. free(pixelBuffer);
  233. CFRelease(inBitmapData);
  234. CGColorSpaceRelease(colorSpace);
  235. CGImageRelease(imageRef);
  236. return returnImage;
  237. }
  238. /// GPUImage的开源库实现毛玻璃效果(比较吃内存,相对Core Image好一点)
  239. /// blurRadius一般10~30之间就可以满足需求
  240. + (UIImage *)GPUImageStyleWithImage:(UIImage *)image withBlurRadius:(CGFloat)blurRadius {
  241. GPUImageGaussianBlurFilter *filter = [[GPUImageGaussianBlurFilter alloc] init];
  242. filter.blurRadiusInPixels = blurRadius;//值越大,模糊度越大
  243. UIImage *blurImage = [filter imageByFilteringImage:image];
  244. return blurImage;
  245. }
  246. /// 修改图片颜色
  247. /// @param color 要修改的颜色
  248. - (UIImage*)imageChangeColor:(UIColor*)color {
  249. //获取画布
  250. UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
  251. //画笔沾取颜色
  252. [color setFill];
  253. CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height);
  254. UIRectFill(bounds);
  255. //绘制一次
  256. [self drawInRect:bounds blendMode:kCGBlendModeOverlay alpha:1.0f];
  257. //再绘制一次
  258. [self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f];
  259. //获取图片
  260. UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
  261. UIGraphicsEndImageContext();
  262. return img;
  263. }
  264. // 以图片中心为中心,以最小边为边长,裁剪正方形图片
  265. +(UIImage *)cropSquareImage:(UIImage *)image{
  266. CGImageRef sourceImageRef = [image CGImage];//将UIImage转换成CGImageRef
  267. CGFloat _imageWidth = image.size.width * image.scale;
  268. CGFloat _imageHeight = image.size.height * image.scale;
  269. CGFloat _width = _imageWidth > _imageHeight ? _imageHeight : _imageWidth;
  270. CGFloat _offsetX = (_imageWidth - _width) / 2;
  271. CGFloat _offsetY = (_imageHeight - _width) / 2;
  272. CGRect rect = CGRectMake(_offsetX, _offsetY, _width, _width);
  273. CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);//按照给定的矩形区域进行剪裁
  274. UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
  275. return newImage;
  276. }
  277. // 以图片中心为中心,以最小边为边长,裁剪圆形图片
  278. + (UIImage *)imageWithClipImage:(UIImage *)image {
  279. //1.开启跟原始图片一样大小的上下文
  280. UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
  281. //2.设置一个圆形裁剪区域
  282. //2.1绘制一个圆形
  283. UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
  284. //2.2.把圆形的路径设置成裁剪区域
  285. [path addClip];//超过裁剪区域以外的内容都给裁剪掉
  286. //3.把图片绘制到上下文当中(超过裁剪区域以外的内容都给裁剪掉)
  287. [image drawAtPoint:CGPointZero];
  288. //4.从上下文当中取出图片
  289. UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
  290. //5.关闭上下文
  291. UIGraphicsEndImageContext();
  292. return newImage;
  293. }
  294. // 获取gif图
  295. + (UIImage *)animatedGIFWithData:(NSData *)data {
  296. if (!data) {
  297. return nil;
  298. }
  299. CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
  300. size_t count = CGImageSourceGetCount(source);
  301. UIImage *animatedImage;
  302. if (count <= 1) {
  303. animatedImage = [[UIImage alloc] initWithData:data];
  304. }
  305. else {
  306. NSMutableArray *images = [NSMutableArray array];
  307. NSTimeInterval duration = 0.0f;
  308. for (size_t i = 0; i < count; i++) {
  309. CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
  310. if (!image) {
  311. continue;
  312. }
  313. duration += [self frameDurationAtIndex:i source:source];
  314. [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
  315. CGImageRelease(image);
  316. }
  317. if (!duration) {
  318. duration = (1.0f / 10.0f) * count;
  319. }
  320. animatedImage = [UIImage animatedImageWithImages:images duration:duration];
  321. }
  322. CFRelease(source);
  323. return animatedImage;
  324. }
  325. + (float)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
  326. float frameDuration = 0.1f;
  327. CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
  328. NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
  329. NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
  330. NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
  331. if (delayTimeUnclampedProp) {
  332. frameDuration = [delayTimeUnclampedProp floatValue];
  333. }
  334. else {
  335. NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
  336. if (delayTimeProp) {
  337. frameDuration = [delayTimeProp floatValue];
  338. }
  339. }
  340. // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
  341. // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
  342. // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
  343. // for more information.
  344. if (frameDuration < 0.011f) {
  345. frameDuration = 0.100f;
  346. }
  347. CFRelease(cfFrameProperties);
  348. return frameDuration;
  349. }
  350. + (UIImage *)animatedGIFNamed:(NSString *)name {
  351. if (![name hasSuffix:@".gif"]) {
  352. return [UIImage imageNamed:name];
  353. }
  354. CGFloat scale = [UIScreen mainScreen].scale;
  355. if (scale > 1.0f) {
  356. NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:nil];
  357. NSData *data = [NSData dataWithContentsOfFile:retinaPath];
  358. if (data) {
  359. return [UIImage animatedGIFWithData:data];
  360. }
  361. NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:nil];
  362. data = [NSData dataWithContentsOfFile:path];
  363. if (data) {
  364. return [UIImage animatedGIFWithData:data];
  365. }
  366. return [UIImage imageNamed:name];
  367. }
  368. else {
  369. NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:nil];
  370. NSData *data = [NSData dataWithContentsOfFile:path];
  371. if (data) {
  372. return [UIImage animatedGIFWithData:data];
  373. }
  374. return [UIImage imageNamed:name];
  375. }
  376. }
  377. /// 回去变灰图片
  378. + (UIImage*)getGrayImage:(UIImage*)oldImage {
  379. int bitmapInfo = kCGImageAlphaPremultipliedLast;
  380. int width = oldImage.size.width*[UIScreen mainScreen].scale;
  381. int height = oldImage.size.height*[UIScreen mainScreen].scale;
  382. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
  383. CGContextRef context = CGBitmapContextCreate (nil, width, height, 8, 0, colorSpace, bitmapInfo);
  384. CGColorSpaceRelease(colorSpace);
  385. if (context == NULL) {return nil;}
  386. CGContextDrawImage(context, CGRectMake(0, 0, width, height), oldImage.CGImage);
  387. UIImage *grayImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
  388. CGContextRelease(context);
  389. return grayImage;
  390. // CGImageRef inflatedImageRef = CGBitmapContextCreateImage(context);
  391. // UIImage *grayImage = [UIImage imageWithCGImage:inflatedImageRef];
  392. // CGImageRelease(inflatedImageRef);
  393. // int width = image.size.width;
  394. // int height = image.size.height;
  395. //
  396. // //第一步:开辟颜色空间
  397. // CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceGray();
  398. //
  399. // //第二步:创建颜色空间的上下文
  400. // CGContextRef contextRef = CGBitmapContextCreate(nil, width, height, 8, 0,colorSpaceRef, kCGImageAlphaNone);
  401. //
  402. // if (contextRef == nil)
  403. // {
  404. // return nil;
  405. // }
  406. // //第三步:渲染图片
  407. // CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), image.CGImage);
  408. //
  409. // //第四步:创建图片 将绘制的颜色空间转成CGImage
  410. // CGImageRef grayImageRef = CGBitmapContextCreateImage(contextRef);
  411. //
  412. // //第五步:将C/C++图片转成UIImage
  413. //
  414. // UIImage * newImage = [UIImage imageWithCGImage:grayImageRef];
  415. //
  416. // //释放内存
  417. // CGColorSpaceRelease(colorSpaceRef);
  418. // CGContextRelease(contextRef);
  419. // CGImageRelease(grayImageRef);
  420. //
  421. // return newImage;
  422. }
  423. @end