美文网首页
iOS:自定义相机

iOS:自定义相机

作者: 春暖花已开 | 来源:发表于2020-09-28 15:12 被阅读0次
    图片.png
    代码部分
    #import "MZScanVC.h"
    
    #import <AVFoundation/AVFoundation.h>
    
    #define kScreenWidth UIScreen.mainScreen.bounds.size.width
    #define kScreenHeight UIScreen.mainScreen.bounds.size.height
    
    @interface MZScanView : UIView
    
    /// 重写layerClass, 并将该view设置为控制器的view
    + (Class)layerClass;
    
    @end
    
    @implementation MZScanView
    
    + (Class)layerClass {
        return [AVCaptureVideoPreviewLayer class];
    }
    
    @end
    
    
    @interface MZScanBackgroundView : UIView
    
    @property(nonatomic, assign) CGRect scanFrame;
    
    @end
    
    @implementation MZScanBackgroundView
    
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            self.backgroundColor = [UIColor clearColor];
        }
        return self;
    }
    
    - (void)drawRect:(CGRect)rect {
        [[[UIColor blackColor] colorWithAlphaComponent:0.2] setFill];
        //半透明区域
        UIRectFill(rect);
        //透明的区域
        CGRect holeiInterSection = CGRectIntersection(self.scanFrame, rect);
        [[UIColor clearColor] setFill];
        UIRectFill(holeiInterSection);
    }
    
    @end
    
    @interface MZScanVC ()<AVCaptureVideoDataOutputSampleBufferDelegate>
    
    @property (nonatomic, strong) AVCaptureStillImageOutput *stillImageOutput;
    @property (nonatomic, strong) AVCaptureSession *captureSession;
    @property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;
    @property (nonatomic, strong) AVCaptureDeviceInput *videoInput;
    
    @property (nonatomic, strong) MZScanBackgroundView *backgroundView;
    
    @end
    
    @implementation MZScanVC
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.view.backgroundColor = [UIColor clearColor];
        [self setupSession];
        [self backgroundView];
    }
    
    - (void)setupSession {
        
        self.captureSession = [[AVCaptureSession alloc] init];
        NSError *error;
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        //更改这个设置的时候必须先锁定设备,修改完后再解锁,否则崩溃
        [device lockForConfiguration:nil];
        
        [device unlockForConfiguration];
        
        self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error];
        if (error) NSLog(@"%@",error);
        
        self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
        //输出设置AVVideoCodecJPEG  输出jpeg格式图片
        NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
        [self.stillImageOutput setOutputSettings:outputSettings];
        
        if ([self.captureSession canAddInput:self.videoInput]) {
            [self.captureSession addInput:self.videoInput];
        }
        if ([self.captureSession canAddOutput:self.stillImageOutput]) {
            [self.captureSession addOutput:self.stillImageOutput];
        }
        
        //初始化预览图层
        self.videoPreviewLayer = (AVCaptureVideoPreviewLayer *)self.view.layer;
        self.videoPreviewLayer.session = self.captureSession;
        [self.videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        [self.videoPreviewLayer setFrame:self.view.layer.bounds];
        
        [self resetModes];
    }
    
    - (void)resetModes {
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        AVCaptureExposureMode exposureMode = AVCaptureExposureModeContinuousAutoExposure;
        AVCaptureFocusMode focusMode = AVCaptureFocusModeContinuousAutoFocus;
        BOOL canResetFocus = [device isFocusPointOfInterestSupported] && [device isFocusModeSupported:focusMode];
        BOOL canResetExposure = [device isExposurePointOfInterestSupported] && [device isExposureModeSupported:exposureMode];
        CGPoint centerPoint = CGPointMake(0.5f, 0.5f);
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            if (canResetFocus) {
                device.focusMode = focusMode;
                device.focusPointOfInterest = centerPoint;
            }
            if (canResetExposure) {
                device.exposureMode = exposureMode;
                device.exposurePointOfInterest = centerPoint;
            }
            [device unlockForConfiguration];
        }
    }
    
    - (void)startCapturing {
        if (!self.captureSession.isRunning) {
            [_captureSession startRunning];
        }
    }
    
    - (void)stopCapturing {
        if (self.captureSession.isRunning) {
            [_captureSession stopRunning];
        }
    }
    
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        
        [self.navigationController setNavigationBarHidden:YES animated:animated];
        [self startCapturing];
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        
        [self.navigationController setNavigationBarHidden:NO animated:animated];
        [self stopCapturing];
    }
    
    /// 点击取消
    - (IBAction)onClickCancel {
        [self stopCapturing];
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    
    /// 点击拍照
    - (IBAction)onClickTakePhoto {
        AVCaptureConnection *stillImageCon = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
        __weak typeof(self) weakself = self;
        [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:stillImageCon completionHandler:^(CMSampleBufferRef  _Nullable imageDataSampleBuffer, NSError * _Nullable error) {
            NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
            UIImage *image = [[UIImage alloc] initWithData:jpegData];
            //返回拍照
            !weakself.getBlock ?: weakself.getBlock(image);
            [weakself onClickCancel];
        }];
    }
    
    - (MZScanBackgroundView *)backgroundView {
        if (!_backgroundView) {
            _backgroundView = [MZScanBackgroundView new];
            [self.view addSubview:_backgroundView];
            _backgroundView.frame = [UIScreen mainScreen].bounds;
            CGFloat x = 10;
            CGFloat y = 120 + (kScreenHeight >= 812 ? 44 : 20);
            _backgroundView.scanFrame = CGRectMake(x, y, kScreenWidth - 20, (kScreenWidth - 20)/1.58);
            [self.view insertSubview:_backgroundView atIndex:1];
        }
        return _backgroundView;
    }
    
    @end
    
    xib部分
    <?xml version="1.0" encoding="UTF-8"?>
    <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
        <device id="retina6_1" orientation="portrait" appearance="light"/>
        <dependencies>
            <deployment identifier="iOS"/>
            <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/>
            <capability name="Safe area layout guides" minToolsVersion="9.0"/>
            <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
        </dependencies>
        <objects>
            <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MZScanVC">
                <connections>
                    <outlet property="view" destination="iN0-l3-epB" id="KHG-9D-L5m"/>
                </connections>
            </placeholder>
            <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
            <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="MZScanView">
                <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                <subviews>
                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vTX-dQ-8Gl">
                        <rect key="frame" x="10" y="164" width="394" height="249.5"/>
                        <subviews>
                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="扫描框-人像面" translatesAutoresizingMaskIntoConstraints="NO" id="Ks3-m2-6Bn">
                                <rect key="frame" x="0.0" y="0.0" width="394" height="249.5"/>
                            </imageView>
                        </subviews>
                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                        <constraints>
                            <constraint firstAttribute="bottom" secondItem="Ks3-m2-6Bn" secondAttribute="bottom" id="klT-V5-ikd"/>
                            <constraint firstAttribute="trailing" secondItem="Ks3-m2-6Bn" secondAttribute="trailing" id="pJd-wp-G1c"/>
                            <constraint firstItem="Ks3-m2-6Bn" firstAttribute="leading" secondItem="vTX-dQ-8Gl" secondAttribute="leading" id="roA-r3-DRd"/>
                            <constraint firstItem="Ks3-m2-6Bn" firstAttribute="top" secondItem="vTX-dQ-8Gl" secondAttribute="top" id="w2u-dR-MmR"/>
                            <constraint firstAttribute="width" secondItem="vTX-dQ-8Gl" secondAttribute="height" multiplier="1.58" id="xof-bC-YQ5"/>
                        </constraints>
                    </view>
                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vzR-sj-lX0">
                        <rect key="frame" x="0.0" y="696" width="414" height="200"/>
                        <subviews>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6up-o4-afi" userLabel="拍照">
                                <rect key="frame" x="174" y="45" width="66" height="66"/>
                                <state key="normal" image="icon-相机"/>
                                <connections>
                                    <action selector="onClickTakePhoto" destination="-1" eventType="touchUpInside" id="kCg-Yx-A2g"/>
                                </connections>
                            </button>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aQ9-jg-nlu">
                                <rect key="frame" x="357" y="61" width="37" height="34"/>
                                <state key="normal" title="取消"/>
                                <connections>
                                    <action selector="onClickCancel" destination="-1" eventType="touchUpInside" id="c6d-28-eSn"/>
                                </connections>
                            </button>
                        </subviews>
                        <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                        <constraints>
                            <constraint firstItem="6up-o4-afi" firstAttribute="top" secondItem="vzR-sj-lX0" secondAttribute="top" constant="45" id="AE0-fd-JXs"/>
                            <constraint firstItem="6up-o4-afi" firstAttribute="centerX" secondItem="vzR-sj-lX0" secondAttribute="centerX" id="GdT-Wa-Fq2"/>
                            <constraint firstItem="aQ9-jg-nlu" firstAttribute="centerY" secondItem="6up-o4-afi" secondAttribute="centerY" id="Hsh-RR-RHh"/>
                            <constraint firstAttribute="height" constant="200" id="K7T-ug-cqY"/>
                            <constraint firstAttribute="trailing" secondItem="aQ9-jg-nlu" secondAttribute="trailing" constant="20" id="hHZ-tv-cA7"/>
                        </constraints>
                    </view>
                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请将身份证人像面放入扫描框内" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wzH-hl-jRN">
                        <rect key="frame" x="100" y="428.5" width="214.5" height="18"/>
                        <fontDescription key="fontDescription" type="system" pointSize="15"/>
                        <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                        <nil key="highlightedColor"/>
                    </label>
                </subviews>
                <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
                <constraints>
                    <constraint firstItem="vTX-dQ-8Gl" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="120" id="B0s-1Y-6RG"/>
                    <constraint firstAttribute="bottom" secondItem="vzR-sj-lX0" secondAttribute="bottom" id="DxT-LM-dSC"/>
                    <constraint firstItem="vTX-dQ-8Gl" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="10" id="KNV-Ps-uLQ"/>
                    <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="vTX-dQ-8Gl" secondAttribute="trailing" constant="10" id="V9Y-tw-qdn"/>
                    <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="vzR-sj-lX0" secondAttribute="trailing" id="WaY-3C-trz"/>
                    <constraint firstItem="vzR-sj-lX0" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="c7n-0A-l75"/>
                    <constraint firstItem="wzH-hl-jRN" firstAttribute="top" secondItem="vTX-dQ-8Gl" secondAttribute="bottom" constant="15" id="hVB-v0-vZM"/>
                    <constraint firstItem="wzH-hl-jRN" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="v7b-5O-A6w"/>
                </constraints>
                <point key="canvasLocation" x="-249" y="76"/>
            </view>
        </objects>
        <resources>
            <image name="icon-相机" width="66" height="66"/>
            <image name="扫描框-人像面" width="315" height="198"/>
        </resources>
    </document>
    

    相关文章

      网友评论

          本文标题:iOS:自定义相机

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