123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- //
- // TZImageCropManager.m
- // TZImagePickerController
- //
- // Created by 谭真 on 2016/12/5.
- // Copyright © 2016年 谭真. All rights reserved.
- //
- #import "TZImageCropManager.h"
- #import "UIView+Layout.h"
- #import <ImageIO/ImageIO.h>
- #import "TZImageManager.h"
- #import "TZImagePickerController.h"
- @implementation TZImageCropManager
- /// 裁剪框背景的处理
- + (void)overlayClippingWithView:(UIView *)view cropRect:(CGRect)cropRect containerView:(UIView *)containerView needCircleCrop:(BOOL)needCircleCrop {
- UIBezierPath *path= [UIBezierPath bezierPathWithRect:[UIScreen mainScreen].bounds];
- CAShapeLayer *layer = [CAShapeLayer layer];
- if (needCircleCrop) { // 圆形裁剪框
- [path appendPath:[UIBezierPath bezierPathWithArcCenter:containerView.center radius:cropRect.size.width / 2 startAngle:0 endAngle: 2 * M_PI clockwise:NO]];
- } else { // 矩形裁剪框
- [path appendPath:[UIBezierPath bezierPathWithRect:cropRect]];
- }
- layer.path = path.CGPath;
- layer.fillRule = kCAFillRuleEvenOdd;
- layer.fillColor = [[UIColor blackColor] CGColor];
- layer.opacity = 0.5;
- [view.layer addSublayer:layer];
- }
- /// 获得裁剪后的图片
- + (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale containerView:(UIView *)containerView {
- CGAffineTransform transform = CGAffineTransformIdentity;
- // 平移的处理
- CGRect imageViewRect = [imageView convertRect:imageView.bounds toView:containerView];
- CGPoint point = CGPointMake(imageViewRect.origin.x + imageViewRect.size.width / 2, imageViewRect.origin.y + imageViewRect.size.height / 2);
- CGFloat xMargin = containerView.tz_width - CGRectGetMaxX(rect) - rect.origin.x;
- CGPoint zeroPoint = CGPointMake((CGRectGetWidth(containerView.frame) - xMargin) / 2, containerView.center.y);
- CGPoint translation = CGPointMake(point.x - zeroPoint.x, point.y - zeroPoint.y);
- transform = CGAffineTransformTranslate(transform, translation.x, translation.y);
- // 缩放的处理
- transform = CGAffineTransformScale(transform, zoomScale, zoomScale);
-
- CGImageRef imageRef = [self newTransformedImage:transform
- sourceImage:imageView.image.CGImage
- sourceSize:imageView.image.size
- outputWidth:rect.size.width * [UIScreen mainScreen].scale
- cropSize:rect.size
- imageViewSize:imageView.frame.size];
- UIImage *cropedImage = [UIImage imageWithCGImage:imageRef];
- cropedImage = [[TZImageManager manager] fixOrientation:cropedImage];
- CGImageRelease(imageRef);
- return cropedImage;
- }
- + (CGImageRef)newTransformedImage:(CGAffineTransform)transform sourceImage:(CGImageRef)sourceImage sourceSize:(CGSize)sourceSize outputWidth:(CGFloat)outputWidth cropSize:(CGSize)cropSize imageViewSize:(CGSize)imageViewSize {
- CGImageRef source = [self newScaledImage:sourceImage toSize:sourceSize];
-
- CGFloat aspect = cropSize.height/cropSize.width;
- CGSize outputSize = CGSizeMake(outputWidth, outputWidth*aspect);
-
- CGContextRef context = CGBitmapContextCreate(NULL, outputSize.width, outputSize.height, CGImageGetBitsPerComponent(source), 0, CGImageGetColorSpace(source), CGImageGetBitmapInfo(source));
- CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
- CGContextFillRect(context, CGRectMake(0, 0, outputSize.width, outputSize.height));
-
- CGAffineTransform uiCoords = CGAffineTransformMakeScale(outputSize.width / cropSize.width, outputSize.height / cropSize.height);
- uiCoords = CGAffineTransformTranslate(uiCoords, cropSize.width/2.0, cropSize.height / 2.0);
- uiCoords = CGAffineTransformScale(uiCoords, 1.0, -1.0);
- CGContextConcatCTM(context, uiCoords);
-
- CGContextConcatCTM(context, transform);
- CGContextScaleCTM(context, 1.0, -1.0);
-
- CGContextDrawImage(context, CGRectMake(-imageViewSize.width/2, -imageViewSize.height/2.0, imageViewSize.width, imageViewSize.height), source);
- CGImageRef resultRef = CGBitmapContextCreateImage(context);
- CGContextRelease(context);
- CGImageRelease(source);
- return resultRef;
- }
- + (CGImageRef)newScaledImage:(CGImageRef)source toSize:(CGSize)size {
- CGSize srcSize = size;
- CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
- CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, rgbColorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
- CGColorSpaceRelease(rgbColorSpace);
-
- CGContextSetInterpolationQuality(context, kCGInterpolationNone);
- CGContextTranslateCTM(context, size.width/2, size.height/2);
-
- CGContextDrawImage(context, CGRectMake(-srcSize.width/2, -srcSize.height/2, srcSize.width, srcSize.height), source);
-
- CGImageRef resultRef = CGBitmapContextCreateImage(context);
- CGContextRelease(context);
- return resultRef;
- }
- /// 获取圆形图片
- + (UIImage *)circularClipImage:(UIImage *)image {
- UIGraphicsBeginImageContextWithOptions(image.size, NO, [UIScreen mainScreen].scale);
-
- CGContextRef ctx = UIGraphicsGetCurrentContext();
- CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
- CGContextAddEllipseInRect(ctx, rect);
- CGContextClip(ctx);
-
- [image drawInRect:rect];
- UIImage *circleImage = UIGraphicsGetImageFromCurrentImageContext();
-
- UIGraphicsEndImageContext();
- return circleImage;
- }
- @end
- @implementation UIImage (TZGif)
- + (UIImage *)sd_tz_animatedGIFWithData:(NSData *)data {
- if (!data) {
- return nil;
- }
-
- CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
-
- size_t count = CGImageSourceGetCount(source);
-
- UIImage *animatedImage;
-
- if (count <= 1) {
- animatedImage = [[UIImage alloc] initWithData:data];
- }
- else {
- // images数组过大时内存会飙升,在这里限制下最大count
- NSInteger maxCount = [TZImagePickerConfig sharedInstance].gifPreviewMaxImagesCount ?: 50;
- NSInteger interval = MAX((count + maxCount / 2) / maxCount, 1);
-
- NSMutableArray *images = [NSMutableArray array];
-
- NSTimeInterval duration = 0.0f;
-
- for (size_t i = 0; i < count; i+=interval) {
- CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
- if (!image) {
- continue;
- }
-
- duration += [self sd_frameDurationAtIndex:i source:source] * MIN(interval, 3);
-
- [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
-
- CGImageRelease(image);
- }
-
- if (!duration) {
- duration = (1.0f / 10.0f) * count;
- }
-
- animatedImage = [UIImage animatedImageWithImages:images duration:duration];
- }
-
- CFRelease(source);
-
- return animatedImage;
- }
- + (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
- float frameDuration = 0.1f;
- CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
- NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
- NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
-
- NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
- if (delayTimeUnclampedProp) {
- frameDuration = [delayTimeUnclampedProp floatValue];
- }
- else {
-
- NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
- if (delayTimeProp) {
- frameDuration = [delayTimeProp floatValue];
- }
- }
-
- // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
- // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
- // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
- // for more information.
-
- if (frameDuration < 0.011f) {
- frameDuration = 0.100f;
- }
-
- CFRelease(cfFrameProperties);
- return frameDuration;
- }
- @end
|