TZImageCropManager.m 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. //
  2. // TZImageCropManager.m
  3. // TZImagePickerController
  4. //
  5. // Created by 谭真 on 2016/12/5.
  6. // Copyright © 2016年 谭真. All rights reserved.
  7. //
  8. #import "TZImageCropManager.h"
  9. #import "UIView+Layout.h"
  10. #import <ImageIO/ImageIO.h>
  11. #import "TZImageManager.h"
  12. @implementation TZImageCropManager
  13. /// 裁剪框背景的处理
  14. + (void)overlayClippingWithView:(UIView *)view cropRect:(CGRect)cropRect containerView:(UIView *)containerView needCircleCrop:(BOOL)needCircleCrop {
  15. UIBezierPath *path= [UIBezierPath bezierPathWithRect:[UIScreen mainScreen].bounds];
  16. CAShapeLayer *layer = [CAShapeLayer layer];
  17. if (needCircleCrop) { // 圆形裁剪框
  18. [path appendPath:[UIBezierPath bezierPathWithArcCenter:containerView.center radius:cropRect.size.width / 2 startAngle:0 endAngle: 2 * M_PI clockwise:NO]];
  19. } else { // 矩形裁剪框
  20. [path appendPath:[UIBezierPath bezierPathWithRect:cropRect]];
  21. }
  22. layer.path = path.CGPath;
  23. layer.fillRule = kCAFillRuleEvenOdd;
  24. layer.fillColor = [[UIColor blackColor] CGColor];
  25. layer.opacity = 0.5;
  26. [view.layer addSublayer:layer];
  27. }
  28. /// 获得裁剪后的图片
  29. + (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale containerView:(UIView *)containerView {
  30. CGAffineTransform transform = CGAffineTransformIdentity;
  31. // 平移的处理
  32. CGRect imageViewRect = [imageView convertRect:imageView.bounds toView:containerView];
  33. CGPoint point = CGPointMake(imageViewRect.origin.x + imageViewRect.size.width / 2, imageViewRect.origin.y + imageViewRect.size.height / 2);
  34. CGFloat xMargin = containerView.tz_width - CGRectGetMaxX(rect) - rect.origin.x;
  35. CGPoint zeroPoint = CGPointMake((CGRectGetWidth(containerView.frame) - xMargin) / 2, containerView.center.y);
  36. CGPoint translation = CGPointMake(point.x - zeroPoint.x, point.y - zeroPoint.y);
  37. transform = CGAffineTransformTranslate(transform, translation.x, translation.y);
  38. // 缩放的处理
  39. transform = CGAffineTransformScale(transform, zoomScale, zoomScale);
  40. CGImageRef imageRef = [self newTransformedImage:transform
  41. sourceImage:imageView.image.CGImage
  42. sourceSize:imageView.image.size
  43. outputWidth:rect.size.width * [UIScreen mainScreen].scale
  44. cropSize:rect.size
  45. imageViewSize:imageView.frame.size];
  46. UIImage *cropedImage = [UIImage imageWithCGImage:imageRef];
  47. cropedImage = [[TZImageManager manager] fixOrientation:cropedImage];
  48. CGImageRelease(imageRef);
  49. return cropedImage;
  50. }
  51. + (CGImageRef)newTransformedImage:(CGAffineTransform)transform sourceImage:(CGImageRef)sourceImage sourceSize:(CGSize)sourceSize outputWidth:(CGFloat)outputWidth cropSize:(CGSize)cropSize imageViewSize:(CGSize)imageViewSize {
  52. CGImageRef source = [self newScaledImage:sourceImage toSize:sourceSize];
  53. CGFloat aspect = cropSize.height/cropSize.width;
  54. CGSize outputSize = CGSizeMake(outputWidth, outputWidth*aspect);
  55. CGContextRef context = CGBitmapContextCreate(NULL, outputSize.width, outputSize.height, CGImageGetBitsPerComponent(source), 0, CGImageGetColorSpace(source), CGImageGetBitmapInfo(source));
  56. CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
  57. CGContextFillRect(context, CGRectMake(0, 0, outputSize.width, outputSize.height));
  58. CGAffineTransform uiCoords = CGAffineTransformMakeScale(outputSize.width / cropSize.width, outputSize.height / cropSize.height);
  59. uiCoords = CGAffineTransformTranslate(uiCoords, cropSize.width/2.0, cropSize.height / 2.0);
  60. uiCoords = CGAffineTransformScale(uiCoords, 1.0, -1.0);
  61. CGContextConcatCTM(context, uiCoords);
  62. CGContextConcatCTM(context, transform);
  63. CGContextScaleCTM(context, 1.0, -1.0);
  64. CGContextDrawImage(context, CGRectMake(-imageViewSize.width/2, -imageViewSize.height/2.0, imageViewSize.width, imageViewSize.height), source);
  65. CGImageRef resultRef = CGBitmapContextCreateImage(context);
  66. CGContextRelease(context);
  67. CGImageRelease(source);
  68. return resultRef;
  69. }
  70. + (CGImageRef)newScaledImage:(CGImageRef)source toSize:(CGSize)size {
  71. CGSize srcSize = size;
  72. CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
  73. CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, rgbColorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
  74. CGColorSpaceRelease(rgbColorSpace);
  75. CGContextSetInterpolationQuality(context, kCGInterpolationNone);
  76. CGContextTranslateCTM(context, size.width/2, size.height/2);
  77. CGContextDrawImage(context, CGRectMake(-srcSize.width/2, -srcSize.height/2, srcSize.width, srcSize.height), source);
  78. CGImageRef resultRef = CGBitmapContextCreateImage(context);
  79. CGContextRelease(context);
  80. return resultRef;
  81. }
  82. /// 获取圆形图片
  83. + (UIImage *)circularClipImage:(UIImage *)image {
  84. UIGraphicsBeginImageContextWithOptions(image.size, NO, [UIScreen mainScreen].scale);
  85. CGContextRef ctx = UIGraphicsGetCurrentContext();
  86. CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
  87. CGContextAddEllipseInRect(ctx, rect);
  88. CGContextClip(ctx);
  89. [image drawInRect:rect];
  90. UIImage *circleImage = UIGraphicsGetImageFromCurrentImageContext();
  91. UIGraphicsEndImageContext();
  92. return circleImage;
  93. }
  94. @end
  95. @implementation UIImage (TZGif)
  96. + (UIImage *)sd_tz_animatedGIFWithData:(NSData *)data {
  97. if (!data) {
  98. return nil;
  99. }
  100. CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
  101. size_t count = CGImageSourceGetCount(source);
  102. UIImage *animatedImage;
  103. if (count <= 1) {
  104. animatedImage = [[UIImage alloc] initWithData:data];
  105. }
  106. else {
  107. NSMutableArray *images = [NSMutableArray array];
  108. NSTimeInterval duration = 0.0f;
  109. for (size_t i = 0; i < count; i++) {
  110. CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
  111. if (!image) {
  112. continue;
  113. }
  114. duration += [self sd_frameDurationAtIndex:i source:source];
  115. [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
  116. CGImageRelease(image);
  117. }
  118. if (!duration) {
  119. duration = (1.0f / 10.0f) * count;
  120. }
  121. animatedImage = [UIImage animatedImageWithImages:images duration:duration];
  122. }
  123. CFRelease(source);
  124. return animatedImage;
  125. }
  126. + (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
  127. float frameDuration = 0.1f;
  128. CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
  129. NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
  130. NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
  131. NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
  132. if (delayTimeUnclampedProp) {
  133. frameDuration = [delayTimeUnclampedProp floatValue];
  134. }
  135. else {
  136. NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
  137. if (delayTimeProp) {
  138. frameDuration = [delayTimeProp floatValue];
  139. }
  140. }
  141. // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
  142. // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
  143. // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
  144. // for more information.
  145. if (frameDuration < 0.011f) {
  146. frameDuration = 0.100f;
  147. }
  148. CFRelease(cfFrameProperties);
  149. return frameDuration;
  150. }
  151. @end