iOS8下新框架 photoKit 之模仿 ALAsset 取 fullScreenImage 图片,解决内存暴增问题
转载请注明出处:http://www.cnblogs.com/shisishao/p/5737228.html
我们知道 photoKit 框架,官方是说用起来更方便,更快捷。但是其中的坑,只有用的人才知道是有多么的多,真是谁用谁知道啊!
photoKit 框架提供的对象是 PHAsset, 而之前的 用ALAssetsLibrary 取的是ALAsset对象,我们知道只要取的ALAsset对象,取图片是很简单的直接对象中就包含有图片对象,取大图:(UIImage *temp_img = [UIImage imageWithCGImage:temp_asset.defaultRepresentation.fullScreenImage];),取缩略图:(UIImage *temp_img = [UIImage imageWithCGImage:asset.aspectRatioThumbnail];) ,但是如果用PHAsset对象取图,只能通过 requestImageForAsset 方法回调,如果穿的参数 PHImageRequestOptions 的synchronous属性为YES返回的是原图,而原图是很大的,如果同时取多张图片,内存会暴增,有可能导致闪退,所以这里这里就模仿 ALAsset 通过获取图片的大小来设置参数,从而获取合适的图片:
- (UIImage *)getImageWithBaseAsset:(id)asset {
__block UIImage *resultImage = nil;
if ([asset isKindOfClass:[PHAsset class]]) {
PHAsset *tempAsset = asset;
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 下面的回调会返回两次 该属性设置YES 只返回一次
options.synchronous = YES;
options.resizeMode = PHImageRequestOptionsResizeModeFast;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize size = CGSizeMake(tempAsset.pixelWidth, tempAsset.pixelHeight);
NSLog(@"###, %f, %f, %f, %f", [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height, size.width, size.height);
CGFloat scale_width = [UIScreen mainScreen].bounds.size.width*scale;
CGFloat scale_height = [UIScreen mainScreen].bounds.size.height*scale;
// 通过设置合适的图片参数,防止内存过高问题(关键点)
if (tempAsset.pixelWidth > scale_width && tempAsset.pixelHeight > scale_height) {
if (tempAsset.pixelWidth >= tempAsset.pixelHeight) {
size = CGSizeMake(scale_height, (NSInteger)(scale_height/tempAsset.pixelWidth*tempAsset.pixelHeight));
} else {
size = CGSizeMake((NSInteger)(scale_height/tempAsset.pixelHeight*tempAsset.pixelWidth), scale_height);
}
}
WS(weakSelf);
[[PHImageManager defaultManager] requestImageForAsset:tempAsset targetSize:size contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"### index");
UIImage *temp_img = result;
resultImage = [weakSelf fixOrientation:temp_img];
}];
}
return resultImage;
}
// 修正图片转向
- (UIImage *)fixOrientation:(UIImage *)aImage {
if (!self.shouldFixOrientation) return aImage;
// No-op if the orientation is already correct
if (aImage.imageOrientation == UIImageOrientationUp)
return aImage;
// We need to calculate the proper transformation to make the image upright.
// We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
CGAffineTransform transform = CGAffineTransformIdentity;
switch (aImage.imageOrientation) {
case UIImageOrientationDown:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
default:
break;
}
switch (aImage.imageOrientation) {
case UIImageOrientationUpMirrored:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
case UIImageOrientationLeftMirrored:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
default:
break;
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
CGImageGetBitsPerComponent(aImage.CGImage), 0,
CGImageGetColorSpace(aImage.CGImage),
CGImageGetBitmapInfo(aImage.CGImage));
CGContextConcatCTM(ctx, transform);
switch (aImage.imageOrientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
// Grr...
CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
break;
default:
CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
break;
}
// And now we just create a new UIImage from the drawing context
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
UIImage *img = [UIImage imageWithCGImage:cgimg];
CGContextRelease(ctx);
CGImageRelease(cgimg);
return img;
}
这样取出的图片分辨率跟 ALAsse.defaultRepresentation.fullScreenImage 取到的图片分辨率一样,而且不会导致内存暴增,还有一点是通过回调取到的图片,图片的方向信息有可能是拍照时的方向,所以 fixOrientation 方法是用来修正图片方向的。