iOS简单自定义相机

最近在做一个趣味相机的小项目,分享一下自己在学习的过程中的收获。

首先,我们需要知道的是,自定义相机也是和系统相机一样,需要调用手机的硬件,所以相机的工作流程大致为:
1、获取设备
2、输入设备
3、输出数据
4、在预览层展示数据

所以我们需要先导入框架

  #import<AVFoundation/AVFoundation.h>

然后声明几个必要的对象

@property (nonatomic, strong) AVCaptureDevice *device; //获取设备

@property (nonatomic, strong) AVCaptureDeviceInput* videoInput; //输入设备

@property (nonatomic, strong) AVCaptureSession* session; //AVCaptureSession对象来执行输入设备和输出设备之间的数据传递

@property (nonatomic, strong) AVCaptureStillImageOutput* stillImageOutput; //输出数据

@property (nonatomic, strong) AVCaptureVideoPreviewLayer* previewLayer; //预览层显示图像


@property (nonatomic, strong) UIImageView *previewImageView;//显示拍下的照片
@property (nonatomic, strong) UIImage *previewImage;

初始化

- (void)viewDidLoad{
   [super viewDidLoad];
   //这里可以就在viewDidload中初始化了

    self.device = [self cameraWithPosition:AVCaptureDevicePositionFront];
    //更改这个设置的时候必须先锁定设备,修改完后再解锁,否则崩溃
    [device lockForConfiguration:nil];
    //设置闪光灯为自动
    [device unlockForConfiguration];

    self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:nil];//此处也可以做一个错误判断

    self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    //输出设置。AVVedioCodecJPEG 输出jpeg格式图片
    NSDictionary *outPutSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
    [self.stillImageOutput setOutputSettings:outPutSettings];

    self.session = [[AVCaptureSession alloc] init];

    self.session.sessionPreset = AVCaptureSessionPreset640x480;
    //     拿到的图像的大小可以自行设定
    //    AVCaptureSessionPreset320x240
    //    AVCaptureSessionPreset352x288
    //    AVCaptureSessionPreset640x480
    //    AVCaptureSessionPreset960x540
    //    AVCaptureSessionPreset1280x720
    //    AVCaptureSessionPreset1920x1080
    //    AVCaptureSessionPreset3840x2160
    //    默认为全屏


    //输入输出设备结合
    if ([self.session canAddInput:self.videoInput]) {
        [self.session addInput:self.videoInput];
    }
    if ([self.session canAddOutput:self.stillImageOutput]) {
        [self.session addOutput:self.stillImageOutput];
    }
    //初始化预览层
    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
    self.previewLayer.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    self.view.layer.masksToBounds = YES;
    [self.view.layer addSublayer:self.previewLayer];
}    

之后在viewWillAppear,viewDidDisappear方法里开启和关闭session

- (void)viewWillAppear:(BOOL)animated{

    [super viewWillAppear:YES];

    if (self.session) {

    [self.session startRunning];
    }
}


- (void)viewDidDisappear:(BOOL)animated{

   [super viewDidDisappear:YES];

   if (self.session) {

     [self.session stopRunning];
   }
}

至此初始化工作基本完成,已经可以在程序中显示出设备捕捉到的画面,接下来需要一个获取设备方向的方法,再配置图片输出的时候需要使用

- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for ( AVCaptureDevice *device in devices )
        if ( device.position == position ){
            return device;
        }
    return nil;
}

拍照按钮方法

- (void)action_TakeShot:(UIButton *)sender{
    NSLog(@"------------- 拍照");
    AVCaptureConnection *connection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
    if (!connection) {
        NSLog(@"拍照失败!");
        return;
    }
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        if (imageDataSampleBuffer == nil) {
            return ;
        }
        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        self.previewImage = [UIImage imageWithData:imageData];
        [self.session stopRunning];
        [self.view addSubview:self.previewImageView];
    }];
}

到此相机的基本功能就已实现,再此基础上再添加保存照片、闪光灯、前后置摄像头切换、触屏对焦等功能

闪光灯

- (void)flashButtonClick:(UIButton *)sender {

   NSLog(@"------------- 闪光灯");

   AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

   //修改前必须先锁定
   [device lockForConfiguration:nil];
   //必须判定是否有闪光灯,否则如果没有闪光灯会崩溃
   if ([device hasFlash]) {

      if (device.flashMode == AVCaptureFlashModeOff) {
        device.flashMode = AVCaptureFlashModeOn;

          [sender setTitle:@"flashOn"];
      } else if (device.flashMode == AVCaptureFlashModeOn) {
          device.flashMode = AVCaptureFlashModeAuto;
          [sender setTitle:@"flashAuto"];
      } else if (device.flashMode == AVCaptureFlashModeAuto) {
          device.flashMode = AVCaptureFlashModeOff;
          [sender setTitle:@"flashOff"];
      }

   } else {
      NSLog(@"设备不支持闪光灯");
   }
   [device unlockForConfiguration];
}

device; //获取设备
videoInput; //输入设备
session; //AVCaptureSession对象来执行输入设备和输出设备之间的数据传递
stillImageOutput; //输出数据
previewLayer; //预览层显示图像
previewImageView;//显示拍下的照片
previewImage;

切换前后置摄像头

- (void)changeCamera:(UIButton *)sender{
    NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
    if (cameraCount > 1) {
        NSError *error;
        //给摄像头的切换添加翻转动画
        CATransition *animation = [CATransition animation];
        animation.duration = .5f;
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        animation.type = @"oglFlip";

        AVCaptureDevice *newCamera = nil;
        AVCaptureDeviceInput *newInput = nil;
  //拿到另外一个摄像头位置
        AVCaptureDevicePosition position = [[_input device] position];
        if (position == AVCaptureDevicePositionFront){
            newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
            animation.subtype = kCATransitionFromLeft;//动画翻转方向
        }
        else {
            newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
            animation.subtype = kCATransitionFromRight;//动画翻转方向
        }
        //生成新的输入
        newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil];
        [self.previewLayer addAnimation:animation forKey:nil];
        if (newInput != nil) {
            [self.session beginConfiguration];
            [self.session removeInput:self.input];
            if ([self.session canAddInput:newInput]) {
                [self.session addInput:newInput];
                self.input = newInput;

            } else {
                [self.session addInput:self.input];
            }
            [self.session commitConfiguration];

        } else if (error) {
            NSLog(@"toggle carema failed, error = %@", error);
        }
    }
}

备注:
参考文档:
[https://github.com/nanshanyi/photographDemo ]
[https://github.com/RockyAo/RACustomCamera ]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS Objective-C 中自定义相片拍照功能,可以使用系统提供的 UIImagePickerController 类。UIImagePickerController 是一个系统自带的 UIImagePickerController 控制器,它提供了相机和相册的访问功能,可以方便地实现自定义相片拍照功能。 以下是简单的实现步骤: 1. 导入 UIImagePickerController 类: ``` #import <UIKit/UIKit.h> ``` 2. 创建 UIImagePickerController 实例: ``` UIImagePickerController *pickerController = [[UIImagePickerController alloc] init]; ``` 3. 配置 UIImagePickerController 实例: ``` pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; // 设置为相机模式 pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; // 设置为拍照模式 pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear; // 设置为后置摄像头 pickerController.allowsEditing = NO; // 禁止编辑 pickerController.delegate = self; // 设置代理 ``` 4. 打开相机: ``` [self presentViewController:pickerController animated:YES completion:nil]; ``` 5. 处理拍照结果: ``` - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info { UIImage *image = info[UIImagePickerControllerOriginalImage]; // 处理拍照结果 [picker dismissViewControllerAnimated:YES completion:nil]; } ``` 通过系统提供的 UIImagePickerController 控制器,我们可以轻松地实现自定义相片拍照功能。如果需要进一步定制相机界面和功能,可以考虑使用 AVFoundation 框架,自定义相机界面和拍照功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值