美文网首页
读取照片、图片库、拍摄图像

读取照片、图片库、拍摄图像

作者: 牛家村的枇杷 | 来源:发表于2016-04-14 16:09 被阅读0次

最近的项目版本-社区用到了读取照片、拍照裁切、美化照片等功能,正好趁有时间对这一部分的内容做一个总结。

  • UIImagePickerController类给我们提供了一个类似相机应用程序的界面,可以通过其实现读取相册、拍照和录制视频的功能。
  • Assets Library框架可以以编程的方式访问图片库和其中的照片。需要链接到AssetsLibrary.framework并导入<AssetsLibrary/AssetsLibrary.h>。
  • AV Foundation从更深层次来看,其提供了对照相机硬件的直接控制功能。需要链接到AVFoundation.framework(或许还有CoreMedia.framework)并导入<AVFoundation/AVFoundation.h>。

[TOC]

UIImagePickerController

UIImagePickerController是一个视图控制器(UINavigationController),它的视图提供了类似于Photo应用程序的导航界面,用户可以借此从图片库中选取一个照片,或者,在硬件条件允许的条件下,它可以提供一个类似于Cemera应用程序的界面,用来拍摄视频或静态图片.

实例化UIImagePickerController,须设置soureceType,如:

// 判断硬件是否支持拍照
- (BOOL)imagePickerControlerIsAvailabelToCamera {
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        return YES;
    } else {
        return NO;
    }
}

如果没有返回YES,就不要用这种资源类型给视图控制器赋值。
利用UIAlertController进行选择:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"图片" message:@"选择" preferredStyle:UIAlertControllerStyleActionSheet];
    UIAlertAction *photoAlbumAction = [UIAlertAction actionWithTitle:@"相册" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        [self creatUIImagePickerControllerWithAlertActionType:1 controller:Controller];
    }];
    UIAlertAction *cemeraAction = [UIAlertAction actionWithTitle:@"相机" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        [self creatUIImagePickerControllerWithAlertActionType:2 controller:Controller];
    }];
    UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        [self creatUIImagePickerControllerWithAlertActionType:0 controller:Controller];
    }];
    [alertController addAction:photoAlbumAction];
    [alertController addAction:cancleAction];
    if ([self imagePickerControlerIsAvailabelToCamera]) {
         [alertController addAction:cemeraAction];
    }
   [self presentViewController:alertController animated:YES completion:^{
       
   }];

创建UIImagePickerController

enum {
   UIImagePickerControllerSourceTypePhotoLibrary ,//来自图库
   UIImagePickerControllerSourceTypeCamera ,//来自相机
   UIImagePickerControllerSourceTypeSavedPhotosAlbum //来自相册
};
 NSUInteger sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    switch (type) {
        case 1:
        {
            // 用户可以在一组相册列表中选择,并进入其中一个相册选择图片
            sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        }
            break;
        case 2:
        {
           sourceType = UIImagePickerControllerSourceTypeCamera;
        }
            break;
        case 0:
        {
            return;
        }
            break;
            
        default:
            break;
    }
    UIImagePickerController *picker = [UIImagePickerController new];
    picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = sourceType;
    [self presentViewController:picker animated:YES completion:^{
    }];

第一次这样操作的时候,系统会弹出授权提示框,我们可以在Info.plist中对
“Privacy-Photo Library Usage Description”键(NSPhotoLibraryUsageDescription)进行设置修改其显示内容。
当用户拒绝时,UIImagePickerController依然可以显现,只不过是空的视图,显示用户拒绝访问图库,除了取消不能进行其它操作。

  NSString *mediaType = AVMediaTypeVideo;
  AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
    switch (authStatus) {
        case 0: { //第一次使用,则会弹出是否打开权限
            [AVCaptureDevice requestAccessForMediaType : AVMediaTypeVideo completionHandler:^(BOOL granted) {
                // granted 是否授权成功
            }];
        }
            break;
        case 1:{ //还未授权
        }
            break;
        case 2:{ //主动拒绝授权
        }
            break;
        case 3: {  //已授权
        }
            break;
            
        default:
            break;
    }

如果UIImagePickerControllerDelegate方法未被实现,视图控制器会自动退出,但我们应该主动实现两种委托方法并退出视图控制器。
设置代理<UINavigationControllerDelegate, UIImagePickerControllerDelegate>

#pragma mark - UIImagePickerControllerDelegate
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
   //获取编辑后的图片
    UIImage *image = info[@"UIImagePickerControllerEditedImage"];
}

// 取消选择照片:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [self dismissViewControllerAnimated:YES completion:nil];
}

选取的信息都在info中,info 是一个字典,字典中的键与媒体类型有关。

NSString *const  UIImagePickerControllerMediaType ;指定用户选择的媒体类型(文章最后进行扩展)
NSString *const  UIImagePickerControllerOriginalImage ;原始图片
NSString *const  UIImagePickerControllerEditedImage ;修改后的图片
NSString *const  UIImagePickerControllerCropRect ;裁剪尺寸
NSString *const  UIImagePickerControllerMediaURL ;媒体的URL
NSString *const  UIImagePickerControllerReferenceURL ;原件的URL
NSString *const  UIImagePickerControllerMediaMetadata;当来数据来源是照相机的时候这个值才有效

使用照相机

对拍摄的图像和视频可以进行编辑,也可以对产生的委托消息进行处理,图像并不是存放于图片库中,所以传送给委托的数据字典里没有UIImagePickerControllerReferenceURL键。在图像拍摄过程中并不牵涉图库,所以无须考虑允许用户访问图片库的问题。

 BOOL ok = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
    if (!ok) {
        NSLog(@"相机硬件不支持");
        return;
    }
    /** 检查支持的媒体类型
     * @param kUTTypeImage 静态图片
     * @prama kUTTypeMovie 视频   (这两个字符串常量定义在MobileCoreServices框架中)
     */
    NSArray *ary = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
    if ([ary indexOfObject:(NSString *)kUTTypeImage] == NSNotFound) {
        return;
    }
    UIImagePickerController *picker = [UIImagePickerController new];
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    // 设置图像选取控制器的类型为静态图像
    picker.mediaTypes = @[(NSString *)kUTTypeImage];
    picker.delegate = self;
    [self presentViewController:picker animated:YES completion:nil];
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    NSLog(@"%@",image);
    [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [self dismissViewControllerAnimated:YES completion:nil];
}

自定义相机拍摄界面

对图像拍摄界面的外观和行为进行自定义的关键是能够理解UIImagePickerController的本质上是一个UINavigationController。在默认情况下,界面中底部显示的控件是导航控制器的工具栏。

将默认控件移除,用双击图像来完成拍摄

 BOOL ok = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
    if (!ok) {
        NSLog(@"相机硬件不支持");
        return;
    }
    /*** 检查支持的媒体类型
     ** UIImagePickerControllerMediaType 包含着KUTTypeImage 和KUTTypeMovie
     ** @param kUTTypeImage 静态图片
     * KUTTypeImage 包含:
         const CFStringRef  kUTTypeImage ;抽象的图片类型
         const CFStringRef  kUTTypeJPEG ;
         const CFStringRef  kUTTypeJPEG2000 ;
         const CFStringRef  kUTTypeTIFF ;
         const CFStringRef  kUTTypePICT ;
         const CFStringRef  kUTTypeGIF ;
         const CFStringRef  kUTTypePNG ;
         const CFStringRef  kUTTypeQuickTimeImage ;
         const CFStringRef  kUTTypeAppleICNS
         const CFStringRef kUTTypeBMP;
         const CFStringRef  kUTTypeICO;
     ** @prama kUTTypeMovie 视频   (这两个字符串常量定义在MobileCoreServices框架中)
     * KUTTypeMovie 包含:
         const CFStringRef  kUTTypeAudiovisualContent ;抽象的声音视频
         const CFStringRef  kUTTypeMovie ;抽象的媒体格式(声音和视频)
         const CFStringRef  kUTTypeVideo ;只有视频没有声音
         const CFStringRef  kUTTypeAudio ;只有声音没有视频
         const CFStringRef  kUTTypeQuickTimeMovie ;
         const CFStringRef  kUTTypeMPEG ;
         const CFStringRef  kUTTypeMPEG4 ;
         const CFStringRef  kUTTypeMP3 ;
         const CFStringRef  kUTTypeMPEG4Audio ;
         const CFStringRef  kUTTypeAppleProtectedMPEG4Audio;
     */

    NSArray *ary = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
    if ([ary indexOfObject:(NSString *)kUTTypeImage] == NSNotFound) {
        return;
    }
    UIImagePickerController *picker = [UIImagePickerController new];
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    // 设置图像选取控制器的类型为静态图像
    picker.mediaTypes = @[(NSString *)kUTTypeImage];
    // 全屏效果
    picker.cameraViewTransform = CGAffineTransformMakeScale(1.5, 1.5);
    picker.delegate = self;
    // 隐藏标准的拍摄视图控件
    picker.showsCameraControls = NO;
    CGRect f = self.view.window.bounds;
    UIView *view = [[UIView alloc]initWithFrame:f];
    UITapGestureRecognizer *tapG = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
    tapG.numberOfTapsRequired = 2;
    [view addGestureRecognizer:tapG];
    picker.cameraOverlayView = view;
    self.picker = picker;
    
    [self presentViewController:picker animated:YES completion:nil];
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    NSLog(@"%@",image);
    [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)tap:(id)recognizer {
    [self.picker takePicture];
}

在上面的demo中,出现了一块工具条大小空白区域,便界面看起来很丑,我们可以自己创建视图放置在这个空白区域。

    CGFloat h = 53;
    UIView *view2 = [[UIView alloc]initWithFrame:CGRectMake(0, f.size.height - h, f.size.width, h)];
    view2.backgroundColor = [UIColor orangeColor];
    [view addSubview:view2];
    UILabel *lable = [UILabel new];
    lable.text = @"双击拍摄照片";
    lable.backgroundColor = [UIColor clearColor];
    [lable sizeToFit];
    lable.center = CGPointMake(CGRectGetMidX(view2.bounds), CGRectGetMidY(view2.bounds));
    [view2 addSubview:lable];

我们创建了UIImagePickerController的委托,不仅接受了UIImagePickerControllerDelegate协议,还有UINavigationControllerDelegate协议。所以另外一种修改界面可以利用从导航控制器的界面来获得一些控件,放在根视图控制器的工具栏。

-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [navigationController setToolbarHidden:NO];
    CGRect f = navigationController.toolbar.frame;
    CGFloat h = 56;
    CGFloat diff = h - f.size.height;
    f.size.height = h;
    f.origin.y -= diff;
    navigationController.toolbar.frame = f;
    UIBarButtonItem *barBtnItem = [[UIBarButtonItem alloc]initWithTitle:@"取消" style:UIBarButtonItemStyleDone target:self action:@selector(doCancel:)];
    UILabel *lable = [UILabel new];
    lable.text = @"双击拍照";
    lable.backgroundColor = [UIColor clearColor];
    [lable sizeToFit];
    UIBarButtonItem *barBtnItem2 = [[UIBarButtonItem alloc]initWithCustomView:lable];
    [navigationController.topViewController setToolbarItems:@[barBtnItem,barBtnItem2]];
}

- (void)doCancel:(id)b {
    NSLog(@"doCancel");
    [self.picker dismissViewControllerAnimated:YES completion:nil];
}

可以通过在导航控制器上放置另一个视图控制器,自己生成接收图像的界面:

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    NSLog(@"%@",image);
   // [self dismissViewControllerAnimated:YES completion:nil];
    if (!image) {
        return;
    }
    ViewController2 *VC2 = [[ViewController2 alloc]initWithImage:image];
    [picker pushViewController:VC2 animated:YES];
}

Assets Library

Assets Library框架突出的一个用途是实现自己的界面,从而突破UIImagePickerController的限制,让用户可以实现多选。在图片库中的一个照片或者一段视频就是一个ALAsset对象。

//获取相册中的全部照片
-(void)getAllPictures {
    
    self.photosModelArray = [[NSMutableArray alloc]init];
    self.albumandPhotosDict = [[NSMutableDictionary alloc]init];
    
    NSMutableArray *assetURLDictionaries = [[NSMutableArray alloc] init];

    ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc]init];
    
    [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
        //group 相册分组
        if (group) {
            NSMutableArray *tempArray = [[NSMutableArray alloc]init];
           // if ([[group valueForProperty:ALAssetsGroupPropertyType] intValue] == 16) {
                //16 表示系统默认相册
                /*
                 //查看相册的名字
                 NSLog(@"ALAssetsGroupPropertyName:%@",[group valueForProperty:ALAssetsGroupPropertyName]);
                 //查看相册的类型
                 NSLog(@"ALAssetsGroupPropertyType:%@",[group valueForProperty:ALAssetsGroupPropertyType]);
                 */
                
                  __block int groupNum = 0;
                //从相册中获取照片
                [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
                    
                    if (asset) {
                        if([[asset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) {
                            [assetURLDictionaries addObject:[asset valueForProperty:ALAssetPropertyURLs]];
                            //NSURL *url= (NSURL*) [[asset defaultRepresentation]url];
                            //NSLog(@"%@,%@",[asset valueForProperty:ALAssetPropertyDate],url);

                            groupNum ++;
                            PhotoModel *photoModel = [[PhotoModel alloc]init];
                            photoModel.isSelected = NO;
                            photoModel.asset = asset;
                            photoModel.i = groupNum;
                            photoModel.image = [UIImage imageWithCGImage:[asset aspectRatioThumbnail]];
                            if ([[group valueForProperty:ALAssetsGroupPropertyType] intValue] == 16){
                                 [self.photosModelArray addObject:photoModel];
                            }
                           
                            [tempArray addObject:photoModel];
                        }
                        //获取资源图片的详细资源信息
                        //ALAssetRepresentation *representation = [result defaultRepresentation];
                        /*
                         //获取资源图片的长宽
                         CGSize dimension = [representation dimensions];
                         //获取资源图片的高清图
                         [representation fullResolutionImage];
                         //获取资源图片的全屏图
                         [representation fullScreenImage];
                         //获取资源图片的名字
                         [representation filename];
                         //缩放倍数
                         [representation scale];
                         //图片资源容量大小
                         [representation size];
                         //图片资源原数据
                         [representation metadata];
                         //旋转方向
                         [representation orientation];
                         //资源图片url地址,该地址和ALAsset通过ALAssetPropertyAssetURL获取的url地址是一样的
                         NSURL* url = [representation url];
                         //资源图片uti,唯一标示符
                         [representation UTI];
                         */
                       

                    }
                    
                    
                }];
                [self.collectionView reloadData];
            NSString *assetsGroupPropertyNameString = [group valueForProperty:ALAssetsGroupPropertyName];
            NSLog(@"ALAssetsGroupPropertyName:%@",[group valueForProperty:ALAssetsGroupPropertyName]);
            [self photosDictWithKey:assetsGroupPropertyNameString ValueArray:tempArray];
        }
       
        
    } failureBlock:^(NSError *error) {
        NSLog(@"获取照片失败");
    }];
    
}
//字典存放相册和全部照片
- (void)photosDictWithKey:(NSString *)key ValueArray:(NSMutableArray *)array
{
    [self.albumandPhotosDict setObject:array forKey:key];
}

使用AV Foundation拍摄图像

使用AV Foundation框架实现对摄像头的控制和拍摄,可以有更多对细节的控制,比如独立地直接控制调焦和曝光度,对于视频可以决定所拍摄影片的图像质量、尺寸和帧速。

相关文章

  • 读取照片、图片库、拍摄图像

    最近的项目版本-社区用到了读取照片、拍照裁切、美化照片等功能,正好趁有时间对这一部分的内容做一个总结。 UIIma...

  • Python各种图像库的图像的基本读写方式!

    目前主流的图像库有几下几种: 结论:以上图片库中当属OpenCV最为强大,成熟。 1.1 OpenCV 图像的读取...

  • 2019-03-20

    day3: PHAsset:图片库中图像、视频或实时照片的表示。 1、Fetching Assets获取asset...

  • OpenCV-Python学习(一):图像入门

    目标: 1.读取图像 2.显示图像 3.保存图像 4.使用Matplotlib显示图像 一、读取图像 读取图像函数...

  • python图像读取与自动化处理

    PIL 图像读取 输出结果: matplotlib 图像读取 输出结果: skimage 图像读取 输出结果: o...

  • Opencv图像操作

    从文件读取/写入图像,访问像素,原始操作,可视化图像 输入/输出 从文件中加载图像: 把自定义读入的彩色照片变成灰...

  • 图片压缩上传

    同样是读取摄像头拍摄的同样景色的照片,通过调用UIImageJPEGRepresentation(UIImage*...

  • nii图像读取

    SimpleITK读取和保存nii图像 注意SimpleITK读取的图像,顺序为(z,y,x) nibabel读取...

  • openCV

    Opencv2图像裁剪(子图像提取) opencv之读取图像 #######opencv读取图像的灰度值并显示出来...

  • Exif.js 读取图像的元数据,判断上传图片方向是否正确

    Exif.js 提供了 JavaScript 读取图像的原始数据的功能扩展,例如:拍照方向、相机设备型号、拍摄时间...

网友评论

      本文标题:读取照片、图片库、拍摄图像

      本文链接:https://www.haomeiwen.com/subject/tapglttx.html