您的位置:首页 > 移动开发 > 微信开发

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

2017-06-10 11:42 696 查看

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

上篇相机拍照的地址: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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐