• iOS摄像头和相册-UIImagePickerController-浅析(转)


    iOS摄像头和相册-UIImagePickerController-浅析(转)

    在一些应用中,我们需要用到iOS设备的摄像头进行拍照,视频。并且从相册中选取我们需要的图片或者视频。
    关于iOS摄像头和相册的应用,可以使用UIImagePickerController类来完成控制。
    关于UIImagePickerController的相关知识,
    如下:
     
    iOS的一些设备上都安装了摄像头。现在绝大多数都有了。
    在编程中,我们是用相应的东西来进行照相,录像等功能。
     
    一、UIImagePickerController类

    UIImagePickerController 这个类可以为大家提供照相的功能,以及图片,视频浏览的功能。 

     
    二、检查硬件是否安装有摄像头或者允许操作相册
     
    这些公共的方法,我们也许会用到,我就贴了!So easy!!!
     #pragma mark - 摄像头和相册相关的公共类

    // 判断设备是否有摄像头

    - (BOOL) isCameraAvailable{

        return [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];

    }

    // 前面的摄像头是否可用

    - (BOOL) isFrontCameraAvailable{

        return [UIImagePickerControllerisCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront];

    }

     

    // 后面的摄像头是否可用

    - (BOOL) isRearCameraAvailable{

        return [UIImagePickerControllerisCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear];

    } 

    // 判断是否支持某种多媒体类型:拍照,视频

    - (BOOL) cameraSupportsMedia:(NSString *)paramMediaType sourceType:(UIImagePickerControllerSourceType)paramSourceType{

        __block BOOL result = NO;

        if ([paramMediaType length] == 0){

            NSLog(@"Media type is empty.");

            return NO;

        }

        NSArray *availableMediaTypes =[UIImagePickerControlleravailableMediaTypesForSourceType:paramSourceType];

        [availableMediaTypes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL*stop) {

                                                            NSString *mediaType = (NSString *)obj;

                                                            if ([mediaTypeisEqualToString:paramMediaType]){

                                                                result = YES;

                                                                *stop= YES;

                                                            }    }];

        return result;

    }

    // 检查摄像头是否支持录像

    - (BOOL) doesCameraSupportShootingVideos{

        return [self cameraSupportsMedia:( NSString *)kUTTypeMoviesourceType:UIImagePickerControllerSourceTypeCamera];

    }

     // 检查摄像头是否支持拍照

    - (BOOL) doesCameraSupportTakingPhotos{

        return [self cameraSupportsMedia:( NSString *)kUTTypeImagesourceType:UIImagePickerControllerSourceTypeCamera];

    }

     #pragma mark - 相册文件选取相关

    // 相册是否可用

    - (BOOL) isPhotoLibraryAvailable{

        return [UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypePhotoLibrary];

    }

     

    // 是否可以在相册中选择视频

    - (BOOL) canUserPickVideosFromPhotoLibrary{

        return [self cameraSupportsMedia:( NSString *)kUTTypeMoviesourceType:UIImagePickerControllerSourceTypePhotoLibrary];

    }

     // 是否可以在相册中选择视频

    - (BOOL) canUserPickPhotosFromPhotoLibrary{

        return [self cameraSupportsMedia:( NSString *)kUTTypeImagesourceType:UIImagePickerControllerSourceTypePhotoLibrary];

    }

    三、用摄像头进行拍照和录像功能
     
    1.我们将UIImagePickerController功能写在一个按钮的点击事件中:
     #pragma mark - 拍照按钮事件

     - (void)ClickControlAction:(id)sender{

        // 判断有摄像头,并且支持拍照功能

        if ([self isCameraAvailable] && [self doesCameraSupportTakingPhotos]){

            // 初始化图片选择控制器

            UIImagePickerController *controller = [[UIImagePickerController alloc] init];

            [controller setSourceType:UIImagePickerControllerSourceTypeCamera];// 设置类型

     

            

            // 设置所支持的类型,设置只能拍照,或则只能录像,或者两者都可以

            NSString *requiredMediaType = ( NSString *)kUTTypeImage;

            NSString *requiredMediaType1 = ( NSString *)kUTTypeMovie;

            NSArray *arrMediaTypes=[NSArray arrayWithObjects:requiredMediaType, requiredMediaType1,nil];

            [controller setMediaTypes:arrMediaTypes]; 

            // 设置录制视频的质量

            [controller setVideoQuality:UIImagePickerControllerQualityTypeHigh];

            //设置最长摄像时间

            [controller setVideoMaximumDuration:10.f];

            [controller setAllowsEditing:YES];// 设置是否可以管理已经存在的图片或者视频

            [controller setDelegate:self];// 设置代理

            [self.navigationController presentModalViewController:controller animated:YES];

            [controller release];

        } else {

            NSLog(@"Camera is not available.");

        }

    }

    解释:
     
    2. setSourceType方法
     
    通过设置setSourceType方法可以确定调用出来的UIImagePickerController所显示出来的界面
     

    typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {

        UIImagePickerControllerSourceTypePhotoLibrary,

        UIImagePickerControllerSourceTypeCamera,

        UIImagePickerControllerSourceTypeSavedPhotosAlbum

    };

    分别表示:图片列表,摄像头,相机相册
    3.setMediaTypes方法
     // 设置所支持的类型,设置只能拍照,或则只能录像,或者两者都可以

            NSString *requiredMediaType = ( NSString *)kUTTypeImage;

            NSString *requiredMediaType1 = ( NSString *)kUTTypeMovie;

            NSArray *arrMediaTypes=[NSArray arrayWithObjects:requiredMediaType, requiredMediaType1,nil];

            [controller setMediaTypes:arrMediaTypes];

    4.关于UIImagePickerControllerDelegate协议
     
    我们要对我们拍摄的照片和视频进行存储,那么就要实现UIImagePickerControllerDelegate协议的方法。
    #pragma mark - UIImagePickerControllerDelegate 代理方法

    // 保存图片后到相册后,调用的相关方法,查看是否保存成功

    - (void) imageWasSavedSuccessfully:(UIImage *)paramImage didFinishSavingWithError:(NSError *)paramError contextInfo:(void *)paramContextInfo{

        if (paramError == nil){

            NSLog(@"Image was saved successfully.");

        } else {

            NSLog(@"An error happened while saving the image.");

            NSLog(@"Error = %@", paramError);

        }

    }

     

    // 当得到照片或者视频后,调用该方法

    -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary*)info{

        NSLog(@"Picker returned successfully.");

        NSLog(@"%@", info);

        NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];

        // 判断获取类型:图片

        if ([mediaType isEqualToString:( NSString *)kUTTypeImage]){

            UIImage *theImage = nil;

            // 判断,图片是否允许修改

            if ([picker allowsEditing]){

                //获取用户编辑之后的图像

                theImage = [info objectForKey:UIImagePickerControllerEditedImage];

            } else {

                // 照片的元数据参数

                theImage = [info objectForKey:UIImagePickerControllerOriginalImage];

                  }

            // 保存图片到相册中

            SEL selectorToCall = @selector(imageWasSavedSuccessfully:didFinishSavingWithError:contextInfo:);

            UIImageWriteToSavedPhotosAlbum(theImage, self,selectorToCall, NULL);    

        }else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]){

            // 判断获取类型:视频

            //获取视频文件的url

            NSURL* mediaURL = [info objectForKey:UIImagePickerControllerMediaURL];

            //创建ALAssetsLibrary对象并将视频保存到媒体库

            // Assets Library 框架包是提供了在应用程序中操作图片和视频的相关功能。相当于一个桥梁,链接了应用程序和多媒体文件。

            ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];

            // 将视频保存到相册中

            [assetsLibrary writeVideoAtPathToSavedPhotosAlbum:mediaURL

                                              completionBlock:^(NSURL *assetURL, NSError *error) {

                                                  if (!error) {

                                                      NSLog(@"captured video saved with no error.");

                                                  }else{

                                                      NSLog(@"error occured while saving the video:%@", error);

                                                  }

                                              }];

            [assetsLibrary release];

     }

            [picker dismissModalViewControllerAnimated:YES];

    }

    // 当用户取消时,调用该方法

    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{

        

        [picker dismissModalViewControllerAnimated:YES];

    }

    四、从相册获取图片和视频数据
     
    1.我们将功能封装在一个按钮的点击事件中

    #pragma mark - 相册操作

     - (void)ClickShowPhotoAction:(id)sender{

        if ([self isPhotoLibraryAvailable]){

            UIImagePickerController *controller = [[UIImagePickerController alloc] init];

             [controller setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];// 设置类型

            NSMutableArray *mediaTypes = [[NSMutableArray alloc] init];

            if ([self canUserPickPhotosFromPhotoLibrary]){

                [mediaTypes addObject:( NSString *)kUTTypeImage];

            }

            if ([self canUserPickVideosFromPhotoLibrary]){

                [mediaTypes addObject:( NSString *)kUTTypeMovie];

            }

            [controller setMediaTypes:mediaTypes];

            [controller setDelegate:self];// 设置代理

            [self.navigationController presentModalViewController:controller animated:YES];

            [controller release];

            [mediaTypes release];   

    } } 

    2.关于UIImagePickerControllerDelegate协议,我们可以重用。
     
    在这里,就不用赘述了!
     
    最后,需要说的是,UIImagePickerControllerDelegate协议中

    -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info方法,中的info值,会根据我们操作的类型不同,而产生了不同的数据信息:

     当操作的为图片时::{

        UIImagePickerControllerCropRect = "NSRect: {{0, 405}, {2448, 2449}}";

        UIImagePickerControllerEditedImage = "";

        UIImagePickerControllerMediaMetadata =     {

            DPIHeight = 72;

            DPIWidth = 72;

            Orientation = 6;

            "{Exif}" =         {

                ApertureValue = "2.526068811667588";

                BrightnessValue = "-0.0709875088566263";

                ColorSpace = 1;

                DateTimeDigitized = "2013:04:05 16:43:00";

                DateTimeOriginal = "2013:04:05 16:43:00";

                ExposureMode = 0;

                ExposureProgram = 2;

                ExposureTime = "0.05882352941176471";

                FNumber = "2.4";

                Flash = 24;

                FocalLenIn35mmFilm = 35;

                FocalLength = "4.28";

                ISOSpeedRatings =             (

                    400

                );

                MeteringMode = 5;

                PixelXDimension = 3264;

                PixelYDimension = 2448;

                SceneType = 1;

                SensingMethod = 2;

                Sharpness = 0;

                ShutterSpeedValue = "4.099543917546131";

                SubjectArea =             (

                    1631,

                    1223,

                    881,

                    881

                );

                WhiteBalance = 0;

            };

            "{TIFF}" =         {

                DateTime = "2013:04:05 16:43:00";

                Make = Apple;

                Model = "iPhone 4S";

                Software = "5.1.1";

                XResolution = 72;

                YResolution = 72;

            };

        };

        UIImagePickerControllerMediaType = "public.image";

        UIImagePickerControllerOriginalImage = "";

    }

     
    当我们操作的为视频时:
     

    {

        UIImagePickerControllerMediaType = "public.movie";

        UIImagePickerControllerMediaURL = "file://localhost/private/var/mobile/Applications/22A14825-DD7E-48E1-A1D5-2D85B82095B5/tmp/capture-T0x1363a0.tmp.etXfD4/capturedvideo.MOV";

    }

     +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    1.UIImagePickerController的静态方法:

        imagepicker = [[UIImagePickerController alloc]init];
        //UIImagePickerController静态方法判断设备是否支持照相机/图片库/相册功能
        /*
         typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
         UIImagePickerControllerSourceTypePhotoLibrary,
         UIImagePickerControllerSourceTypeCamera,
         UIImagePickerControllerSourceTypeSavedPhotosAlbum
         };
         */
        BOOL isCameraSupport = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
        NSLog(@"support camera:%d",isCameraSupport);
        
        //UIImagePickerController静态方法判断设备是否支持前置摄像头/后置摄像头
        /*
         typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
         UIImagePickerControllerCameraDeviceRear,
         UIImagePickerControllerCameraDeviceFront
         };
         */
        BOOL isRearSupport = [UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear];
        NSLog(@"rear support:%d",isRearSupport);
        
        //UIImagePickerController静态方法判断设备是否支持前置摄像头闪光灯/后置摄像头闪光灯
        /*
         typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
         UIImagePickerControllerCameraDeviceRear,
         UIImagePickerControllerCameraDeviceFront
         };
         */
        BOOL isFlushSupport = [UIImagePickerController isFlashAvailableForCameraDevice:UIImagePickerControllerCameraDeviceRear];
        NSLog(@"rear flash support:%d",isFlushSupport);
        
        //UIImagePickerController静态方法返回前置摄像头/后置摄像头支持的拍摄类型
        /*
         typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
         UIImagePickerControllerCameraDeviceRear,
         UIImagePickerControllerCameraDeviceFront
         };
         */
        //返回类型有照片和视频
        /*
         enum {
         UIImagePickerControllerCameraCaptureModePhoto,
         UIImagePickerControllerCameraCaptureModeVideo
         };
         typedef NSUInteger UIImagePickerControllerCameraCaptureMode;
         */
        NSArray* captureModes = [UIImagePickerController availableCaptureModesForCameraDevice:UIImagePickerControllerCameraDeviceRear];
        for (NSNumber* mode in captureModes) {
            NSLog(@"capture modes:%d",[mode integerValue]);
        }
        
        //UIImagePickerController静态方法返回照相机/相册/照片库所支持的媒体类型
        /*
         typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
         UIImagePickerControllerSourceTypePhotoLibrary,
         UIImagePickerControllerSourceTypeCamera,
         UIImagePickerControllerSourceTypeSavedPhotosAlbum
         };
         */
        //返回类型有kUTTypeMovie,kUTTypeImage,其他类型均在<MobileCoreServices/MobileCoreServices.h>下
        NSArray* mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
        for (NSString* type in mediaTypes) {
            NSLog(@"media types:%@",type);
        }

    2.UIImagePickerController属性详解:

        //指定使用照相机模式,可以指定使用相册/照片库
        imagepicker.sourceType = UIImagePickerControllerSourceTypeCamera;
        //设置当拍照完或在相册选完照片后,是否跳到编辑模式进行图片剪裁。只有当showsCameraControls属性为true时才有效果
        imagepicker.allowsEditing = YES;
        //设置拍照时的下方的工具栏是否显示,如果需要自定义拍摄界面,则可把该工具栏隐藏
        imagepicker.showsCameraControls  = YES;
        //设置使用后置摄像头,可以使用前置摄像头
        imagepicker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
        //设置闪光灯模式
        /*
         typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) {
         UIImagePickerControllerCameraFlashModeOff  = -1,
         UIImagePickerControllerCameraFlashModeAuto = 0,
         UIImagePickerControllerCameraFlashModeOn   = 1
         };
         */
        imagepicker.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
        //设置相机支持的类型,拍照和录像
        imagepicker.mediaTypes = @[(NSString*)kUTTypeImage,(NSString*)kUTTypeMovie];
        //设置拍摄时屏幕的view的transform属性,可以实现旋转,缩放功能
       // imagepicker.cameraViewTransform = CGAffineTransformMakeRotation(M_PI*45/180);
       // imagepicker.cameraViewTransform = CGAffineTransformMakeScale(1.5, 1.5);
        //所有含有cameraXXX的属性都必须要sourceType是UIImagePickerControllerSourceTypeCamera时设置才有效果,否则会有异常
        //设置UIImagePickerController的代理
        imagepicker.delegate = self;

    -(void)showCamera{
        //用模态方式呈现imagepicker
        [self presentModalViewController:imagepicker animated:YES];
    }

    使用 imagepicker.cameraViewTransform = CGAffineTransformMakeRotation(M_PI*45/180);旋转45度的效果:

    使用imagepicker.cameraViewTransform = CGAffineTransformMakeScale(1.5, 1.5);全屏的效果,同时imagepicker.showsCameraControls  =NO;隐藏工具栏:

    使用imagepicker.allowsEditing = YES;出现的图片编辑效果,只有当imagepicker.showsCameraControls  = YES;才有效果:

    使用 imagepicker.mediaTypes = @[(NSString*)kUTTypeImage,(NSString*)kUTTypeMovie];支持拍照和视频的前后对比效果:

    3.UIImagePickerController回调详解:

    //成功获得相片还是视频后的回调
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
        //通过UIImagePickerControllerMediaType判断返回的是照片还是视频
        NSString* type = [info objectForKey:UIImagePickerControllerMediaType];
        //如果返回的type等于kUTTypeImage,代表返回的是照片,并且需要判断当前相机使用的sourcetype是拍照还是相册
        if ([type isEqualToString:(NSString*)kUTTypeImage]&&picker.sourceType==UIImagePickerControllerSourceTypeCamera) {
            //获取照片的原图
            UIImage* original = [info objectForKey:UIImagePickerControllerOriginalImage];
            //获取图片裁剪的图
            UIImage* edit = [info objectForKey:UIImagePickerControllerEditedImage];
            //获取图片裁剪后,剩下的图
            UIImage* crop = [info objectForKey:UIImagePickerControllerCropRect];
            //获取图片的url
            NSURL* url = [info objectForKey:UIImagePickerControllerMediaURL];
            //获取图片的metadata数据信息
            NSDictionary* metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
            //如果是拍照的照片,则需要手动保存到本地,系统不会自动保存拍照成功后的照片
            UIImageWriteToSavedPhotosAlbum(edit, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
        }else{
        
        }
        //模态方式退出uiimagepickercontroller
        [imagepicker dismissModalViewControllerAnimated:YES];
    }
    //取消照相机的回调
    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
        //模态方式退出uiimagepickercontroller
        [imagepicker dismissModalViewControllerAnimated:YES];
    }
    //保存照片成功后的回调
    - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error
      contextInfo:(void *)contextInfo{
        
        NSLog(@"saved..");
    }

    4.自定义相机拍照画面:

       //设置拍照时的下方的工具栏是否显示,如果需要自定义拍摄界面,则可把该工具栏隐藏
        imagepicker.showsCameraControls  = NO;

        UIToolbar* tool = [[UIToolbar alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height-55, self.view.frame.size.width, 75)];
        tool.barStyle = UIBarStyleBlackTranslucent;
        UIBarButtonItem* cancel = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelCamera)];
        UIBarButtonItem* add = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(savePhoto)];
        [tool setItems:[NSArray arrayWithObjects:cancel,add, nil]];
       //把自定义的view设置到imagepickercontroller的overlay属性中

       imagepicker.cameraOverlayView = tool;

    -(void)cancelCamera{
        [imagepicker dismissModalViewControllerAnimated:YES];
    }
    -(void)savePhoto{
        //拍照,会自动回调- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info,对于自定义照相机界面,拍照后回调可以不退出实现连续拍照效果
        [imagepicker takePicture];
    }

     

    5.UIImagePickerController是继承UINavigationController,所以可以push和pop一些viewcontroller进行导航效果。例如,自定义照相机画面的时候可以在拍摄完后push一个viewcontroller用于对照片进行编辑。

     
     
    花开花谢春不管,水暖水寒鱼自知.
  • 相关阅读:
    HTML转PDF
    观察者模式分析
    异常解决方案记录
    复杂结构数据提交
    在Spring Controller中将数据缓存到session
    Eclipse
    redis数据类型-散列类型
    redis数据类型-字符串类型
    redis键操作
    redis性能优化
  • 原文地址:https://www.cnblogs.com/wangxiaorui/p/5158727.html
Copyright © 2020-2023  润新知