iOS 相机拍照、相册获取照片(仿微信) 一一 从相册获取图片、图片裁剪

版权声明:本文为博主原创文章,转载请注明。 https://blog.csdn.net/a44496913/article/details/72979704

上篇写了使用相机拍照并裁剪的过程,本来准备把相册处理也放进去的,但考虑到放一起篇幅太长,所以还是分开来写。

上篇相机拍照的地址:http://blog.csdn.net/a44496913/article/details/72934955


注:由于项目最低支持是iOS 8.0,所以我直接使用的 Photos 框架

下面进入正题

  • 导入框架

#import <Photos/Photos.h>

  • 获取所有的相册

- (void)getOriginalImages
{
    // 获得所有的自定义相簿
    PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    // 遍历所有的自定义相簿
    for (PHAssetCollection *assetCollection in assetCollections) {
        [self enumerateAssetsInAssetCollection:assetCollection original:YES];
    }
    
    // 获得相机胶卷
    PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
    // 遍历相机胶卷,获取大图
    [self enumerateAssetsInAssetCollection:cameraRoll original:YES];
}

  • 得到相册后进行遍历,获取每个相册中所有的 PHAsset,PHAsset中包含图片和图片的信息

/**
 *  遍历相簿中的所有图片
 *  @param assetCollection 相簿
 *  @param original        是否要原图
 */
- (void)enumerateAssetsInAssetCollection:(PHAssetCollection *)assetCollection original:(BOOL)original
{
    NSLog(@"相簿名:%@", assetCollection.localizedTitle);

    // 获得某个相簿中的所有PHAsset对象
    PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
    
    /*
     这里是把 asset 直接作为数据源添加到数组中,没有进一步的转化为图片,原因有两点:
     1.转化为图片很耗时,用户体验不好
     2.直接转化图片内存占用很大,一开始我直接转化为高清图,结果内存暴增闪退了
    */
    for (PHAsset *asset in assets) {
        [self.dataSource addObject:asset];
    }
    //添加显示列表
    [self.view addSubview:self.collectionView];
}

  • 在collectionVIew 代理方法中逐个获取预览图(预览图较小,对内存压力不大)

PHAsset *asset = self.dataSource[indexPath.row];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步获得图片, 只会返回1张图片
options.synchronous = YES;
//尺寸为零,获取的是预览图
CGSize size = CGSizeZero;
// 从asset中获得图片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        
    [cell updateCollectionViewCellInformationWithData:result];
}];

  • 如果需要获取原图,需要修改上面方法的 size

CGSize size = CGSizeMake(asset.pixelWidth, asset.pixelHeight);

  • 在得到原图之后就可以对其进行裁剪操作了,裁剪的处理过程和上篇的拍照裁剪类似,只是这里给图片添加了移动和缩放,所以裁剪会麻烦些,不过只要计算出裁剪比例和位置,剩下的就好处理了

/** 用于裁剪的原始图片 */
@property (strong, nonatomic) UIImage *image;
/** 图片显示 */
@property (strong, nonatomic) UIImageView *imageV;

/** 图片加载后的初始位置 */
@property (assign, nonatomic) CGRect norRect;

/** 裁剪框frame */
@property (assign, nonatomic) CGRect showRect;

/** 用于判断是否是放大操作 */
@property (assign, nonatomic) CGFloat lastImageW;

  • 图片移动,根据位置使其回弹

- (void)panGR:(UIPanGestureRecognizer *)sender{
    
    CGPoint point = [sender translationInView:self.view];
    
    _imageV.center = CGPointMake(_imageV.centerX + point.x, _imageV.centerY + point.y);
    [sender setTranslation:CGPointZero inView:self.view];
    
    //手势结束,调整 imageView 位置
    if (sender.state == UIGestureRecognizerStateEnded) {
        
        if (_imageV.origin.x > _showRect.origin.x ||
            _imageV.origin.y > _showRect.origin.y ||
            _imageV.origin.x + _imageV.size.width < _showRect.origin.x + _showRect.size.width ||
            _imageV.origin.y + _imageV.size.height < _showRect.origin.y + _showRect.size.height) {
            
            CGRect newRect = _imageV.frame;
            if (_imageV.origin.x > _showRect.origin.x) {
                newRect.origin.x = _showRect.origin.x;
            }
            
            if (_imageV.origin.y > _showRect.origin.y &&
                _imageV.frame.size.height > _showRect.size.height)
            {
                newRect.origin.y = _showRect.origin.y;
            }
            else if (_imageV.origin.y > _showRect.origin.y &&
                     _imageV.frame.size.height <= _showRect.size.height)
            {
                newRect.origin.y = (SCREEN_HEIGHT - _imageV.frame.size.height) / 2.0;
            }
            
            if ((_imageV.origin.x + _imageV.size.width < _showRect.origin.x + _showRect.size.width) )
            {
                newRect.origin.x += _showRect.origin.x + _showRect.size.width - (_imageV.origin.x + _imageV.size.width);
            }
            
            
            if ((_imageV.origin.y + _imageV.size.height < _showRect.origin.y + _showRect.size.height) &&
                (_imageV.frame.size.height > _showRect.size.height)) {
                newRect.origin.y += _showRect.origin.y + _showRect.size.height - (_imageV.origin.y + _imageV.size.height);
            }
            else if ((_imageV.origin.y + _imageV.size.height < _showRect.origin.y + _showRect.size.height) &&
                     (_imageV.frame.size.height <= _showRect.size.height))
            {
                newRect.origin.y = (SCREEN_HEIGHT - _imageV.frame.size.height) / 2.0;
            }
            
            [UIView animateWithDuration:0.3f animations:^{
                _imageV.frame = newRect;
            }];
        }
    }
}

  • 缩放手势

- (void)pinGR:(UIPinchGestureRecognizer *)sender{
    
    _imageV.transform = CGAffineTransformScale(_imageV.transform, sender.scale, sender.scale);
    
    //缩放结束,调整 imageView 位置
    if (sender.state == UIGestureRecognizerStateEnded) {
        
        CGRect newRect = _imageV.frame;
        if (_imageV.frame.size.width <= _showRect.size.width) {
            
            CGFloat ret = _image.size.height / _image.size.width;
            newRect.size.width = _showRect.size.width;
            newRect.size.height = _showRect.size.width * ret;
            newRect.origin.x = _showRect.origin.x;
            newRect.origin.y = (SCREEN_HEIGHT - newRect.size.height) / 2.0;
            
        }else{
            
            if (newRect.size.width < _lastImageW){
                
                if (_imageV.centerX <= _showRect.origin.x + _showRect.size.width / 2.0) {
                    newRect.origin.x = _showRect.origin.x + _showRect.size.width - newRect.size.width;
                }else{
                    newRect.origin.x = _showRect.origin.x;
                }
                
                if (_imageV.centerY <= _showRect.origin.y + _showRect.size.height / 2.0) {
                    newRect.origin.y = _showRect.origin.y + _showRect.size.height - newRect.size.height;
                }else{
                    newRect.origin.y = _showRect.origin.y;
                }
            }
            
        }
        
        [UIView animateWithDuration:0.3f animations:^{
            _imageV.frame = newRect;
        }];
        
        _lastImageW = newRect.size.width;
    }
    
    sender.scale = 1.0;
}

  • 计算裁剪区域并裁剪
- (void)rightButtonClicked{
    
    CGRect clipRect = CGRectZero;
    
    CGFloat h = 0;
    CGFloat w = 0;
    CGFloat originX = 0;
    CGFloat originY = 0;
    CGFloat clipW = 0;
    CGFloat clipH = 0;
    
    if (_imageV.size.width <= _showRect.size.width) {   //图片没有放大
        
        if (_imageV.size.height <= _showRect.size.height)  //图片高度小于等于裁剪框高度,按图片高度截取正方形
        {
            h = _imageV.size.height;
            w = h;
            
            originX = (_imageV.size.width - w) / 2.0 / _imageV.size.width * _image.size.width;
            originY = 0;
        }
        else{  //图片高度大于裁剪框高度,按裁剪框截取
            
            h = _showRect.size.width;
            w = _showRect.size.width;
            
            originX = 0;
            originY = (_showRect.origin.y - _imageV.frame.origin.y) / _imageV.size.height * _image.size.height;
        }
        
    }else{   //图片被放大
      
        if (_imageV.size.height <= _showRect.size.height) {  //图片高度小于等于裁剪框高度,按图片高度截取正方形
         
            h = _imageV.size.height;
            w = h;
            
            originX = (_showRect.origin.x - _imageV.frame.origin.x + (_showRect.size.width - w) / 2.0) / _imageV.size.width * _image.size.width;
            originY = 0;
            
        }
        else{  //图片高度大于裁剪框高度,按裁剪框截取
            
            h = _showRect.size.width;
            w = _showRect.size.width;
            
            originX = (_showRect.origin.x - _imageV.frame.origin.x) / _imageV.frame.size.width * _image.size.width;
            originY = (_showRect.origin.y - _imageV.frame.origin.y) / _imageV.frame.size.height * _image.size.height;
        }
    }
    
    clipW = w / _imageV.size.width * _image.size.width;
    clipH = h / _imageV.size.height * _image.size.height;
    
    clipRect = CGRectMake(originX, originY, clipW, clipH);
    
    //裁剪后得到的图片
    UIImage *image = [self imageFromImage:self.image inRect:clipRect];
    //裁剪完成回调
    if (self.pictureSelectedBlock) {
        self.pictureSelectedBlock();
    }
    
    [_imageV removeFromSuperview];
    [self dismissViewControllerAnimated:YES completion:^{
        
        [[NSNotificationCenter defaultCenter] postNotificationName:@"PicutreFromAlbum" object:nil userInfo:@{@"image":image}];
        
    }];
}

//裁剪方法
- (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect{
    
    //将UIImage转换成CGImageRef
    CGImageRef sourceImageRef = [image CGImage];
    
    //按照给定的矩形区域进行剪裁
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);
    
    //将CGImageRef转换成UIImage
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    
    //返回剪裁后的图片
    return newImage;
}


Demo地址:https://github.com/HuberyYang/CameraDemo.git


猜你喜欢

转载自blog.csdn.net/a44496913/article/details/72979704