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 方法是用来修正图片方向的。

 

posted @ 2016-08-04 16:28  小码哥伍六七  阅读(1082)  评论(0编辑  收藏  举报