123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- //
- // SPSBFilmingIdentityCardViewController.m
- // 我的社保
- //
- // Created by shanp on 2021/5/18.
- //
- #import "SPSBFilmingIdentityCardViewController.h"
- #import <AVFoundation/AVFoundation.h>
- #import <ImageIO/ImageIO.h>
- #import "SPSBUIGeneralHeader.h"
- #import <Photos/Photos.h>
- #import "UIView+SPSBLoadingTipsView.h"
- #import <UIImage+JXHProcessingImage.h>
- #import "SPSBConfirmAlertViewController.h"
- #import "SPSBSelectSinglePhotoViewController.h"
- @interface SPSBFilmingIdentityCardViewController ()<UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
- AVCaptureSession *_session;
- AVCaptureStillImageOutput *_dataOutput;
- AVCaptureDeviceInput * _dataInput;
- AVCaptureVideoPreviewLayer *_previewlayer;
- UIImageView *_imageView;
- CGFloat _topShadeViewHeight;
- CGFloat _leftShadViewWidth;
- CGFloat _bottomShadeViewHeight;
- bool _canOpenCamera;
- bool _alert;
- UIView *_tipsLabel;
- }
- @end
- @implementation SPSBFilmingIdentityCardViewController
- - (instancetype)init {
- self = [super init];
- if (!self) return nil;
- self.modalPresentationStyle = UIModalPresentationFullScreen;
- return self;
- }
- - (void)viewDidLoad {
- [super viewDidLoad];
- [self setUp];
- }
- - (void)viewDidAppear:(BOOL)animated {
- [super viewDidAppear:animated];
- if (_tipsLabel) {
- [UIView animateWithDuration:0.3 delay:2 options:0 animations:^{
- self->_tipsLabel.alpha = 0;
- } completion:^(BOOL finished) {
- [self->_tipsLabel removeFromSuperview];
- self->_tipsLabel = nil;
- }];
- }
-
- if (!_canOpenCamera) {
- if (_alert) {
- [self backAction];
- return;
- }
- _alert = true;
- SPSBConfirmAlertViewController *vc = [SPSBConfirmAlertViewController alertWithTitle:@"提示" content:@"不能打开相机,是否直接进入相册"];
- @weakify(self)
- [vc setCancelButtonTitle:@"暂时不进入" titleColor:nil action:^{
- @strongify(self)
- [self backAction];
- }];
- [vc setConfirmButtonTitle:@"立即进入" titleColor:nil action:^{
- @strongify(self)
- [self openPhotoAlbum];
- }];
- [self presentViewController:vc animated:false completion:nil];
- }
- }
- #pragma mark - Action
- - (void)setUp {
- //-- Setup Capture Session.
- _session = [[AVCaptureSession alloc] init];
- [_session beginConfiguration];
- //-- Set preset session size.
- if ([_session canSetSessionPreset:AVCaptureSessionPresetHigh]) {//设置分辨率
- _session.sessionPreset = AVCaptureSessionPresetHigh;
- }
- //-- Creata a video device and input from that Device. Add the input to the capture session.
- AVCaptureDevice * videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
- NSError *error;
- _dataInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
- if (error) {
- _canOpenCamera = false;
- return;
- }
- _canOpenCamera = true;
- [_session addInput:_dataInput];
- _previewlayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_session];
- _previewlayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
- _previewlayer.frame = self.view.bounds;
- [self.view.layer insertSublayer:_previewlayer atIndex:0];
- [self setupUI];
- //-- Create the output for the capture session.
- _dataOutput = [[AVCaptureStillImageOutput alloc] init];
- [_session addOutput:_dataOutput];
- [_session commitConfiguration];
- [_session startRunning];
- }
- - (void)takePhotoAction {
- AVCaptureConnection *videoConnection = nil;
- for (AVCaptureConnection *connection in _dataOutput.connections) {
- for (AVCaptureInputPort *port in [connection inputPorts]) {
- if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
- videoConnection = connection; //先找出目标connections(见图)
- break;
- }
- }
- if (videoConnection) { break; }
- }
- //锁定connection后就可以获取静态图了。
- @weakify(self)
- [_dataOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef _Nullable imageDataSampleBuffer, NSError * _Nullable error) {
- @strongify(self)
- if (imageDataSampleBuffer) {
- NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
- UIImage *image = [[UIImage alloc] initWithData:imageData];
- self->_imageView.image = image;
- [self handleImage:image];
- [self->_session stopRunning];
- } else {
- [self.view showToastWithTitle:@"获取图像失败请重试"];
- }
- }];
- }
- - (void)handleImage:(UIImage *)image {
- self.view.userInteractionEnabled = false;
- [self.view showLoadingToastWithTitle:@"正在处理" userClick:false];
- @weakify(self)
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
- @strongify(self)
- debugLog(@"%lf-----%lf", image.size.width, image.size.height);
- debugLog(@"%lf-----%lf", jxh_screenWidth(), jxh_screenHeight());
- UIImage *_image = [UIImage fixOrientation:image];
- CGFloat scale = _image.size.height / jxh_screenHeight();
- CGFloat x = (_image.size.width - _image.size.height * jxh_screenWidth() / jxh_screenHeight()) / 2 + self->_leftShadViewWidth * scale;
- CGFloat width = (jxh_screenWidth() - self->_leftShadViewWidth * 2) * scale;
- CGImageRef imageRef = CGImageCreateWithImageInRect(_image.CGImage, CGRectMake(x, self->_topShadeViewHeight * scale, width, width * SPSBIdentifierCardScale));
- _image = [UIImage imageWithCGImage:imageRef];
- CGImageRelease(imageRef);
- _image = [self changeTheDirectionOfTheImage:_image];
- _image = [self scaleImage:_image];
- @weakify(self)
- dispatch_async(dispatch_get_main_queue(), ^{
- [self.view dismissToast];
- [self dismissViewControllerAnimated:true completion:^{
- @strongify(self)
- if (self->_spsb_caughtImage) {
- self->_spsb_caughtImage(_image);
- }
- }];
- });
- });
-
- }
- - (UIImage *)scaleImage:(UIImage *)image {
- UIImage *img = [UIImage imageWithImage:image scale:480];
- debugLog(@"%lf-----%lf", img.size.width, img.size.height);
- return img;
- }
- - (UIImage *)changeTheDirectionOfTheImage:(UIImage *)image {
- CGFloat rotate = M_PI_2;
- CGRect rect = CGRectMake(0, 0, image.size.height, image.size.width);
- CGFloat translateX = 0;
- CGFloat translateY = -rect.size.width;
- CGFloat scaleY = rect.size.width/rect.size.height;
- CGFloat scaleX = rect.size.height/rect.size.width;
- UIGraphicsBeginImageContext(rect.size);
- CGContextRef context = UIGraphicsGetCurrentContext();
- //做CTM变换
- CGContextTranslateCTM(context, 0.0, rect.size.height);
- CGContextScaleCTM(context, 1.0, -1.0);
- CGContextRotateCTM(context, rotate);
- CGContextTranslateCTM(context, translateX, translateY);
-
- CGContextScaleCTM(context, scaleX, scaleY);
- //绘制图片
- CGContextDrawImage(context, CGRectMake(0, 0, rect.size.width, rect.size.height), image.CGImage);
-
- UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
- return img;
- }
- //打开相册
- - (void)openPhotoAlbum {
- //
- if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
- UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
- imagePicker.modalPresentationStyle = UIModalPresentationFullScreen;
- imagePicker.delegate = self;
- imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
- [imagePicker setEditing:true animated:true]; //允许编辑
- [self presentViewController:imagePicker animated:true completion:^{
-
- }];
- } else {
- [self.view showToastWithTitle:@"相册无法打开"];
- [self dismissViewControllerAnimated:true completion:nil];
- }
- }
- - (void)backAction {
- [self dismissViewControllerAnimated:true completion:nil];
- }
- #pragma mark - UIImagePickerControllerDelegate
- //打开相册之后选择的方法
- - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
- //获得媒体类型
- NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];
- if ([mediaType hasSuffix:@"image"])
- {
- UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
- if (image) {
- [self pushSelectSinglePhotoViewControllerWithImage:image controller:picker];
- return;
- }
- NSURL *url = [info valueForKey:UIImagePickerControllerReferenceURL];
- NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithString:url.absoluteString];
- __block NSString *localIdentifiers;
- [urlComponents.queryItems enumerateObjectsUsingBlock:^(NSURLQueryItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- if ([obj.name isEqualToString:@"id"]) {
- localIdentifiers = obj.value;
- *stop = true;
- }
- }];
- if (localIdentifiers) {
- PHFetchResult * re = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifiers] options:nil];
- [[PHCachingImageManager defaultManager] requestImageDataForAsset:re.firstObject options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
-
- UIImage * img = [UIImage imageWithData:imageData];
- if (img) {
- if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
- //将照片存入相册中
- UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
- }
- [self pushSelectSinglePhotoViewControllerWithImage:img controller:picker];
- }
-
-
- }];
- }
- }
- }
- - (void)pushSelectSinglePhotoViewControllerWithImage:(UIImage *)image controller:(UIImagePickerController *)picker {
- SPSBSelectSinglePhotoViewController *vc = SPSBSelectSinglePhotoViewController.new;
- vc.spsb_needToDismiss = false;
- vc.spsb_dataImage = image;
- vc.spsb_proportion = SPSBIdentifierCardScale;
- @weakify(self)
- [vc passValue:^(NSValue * _Nonnull value) {
- @strongify(self)
- [vc.view showLoadingToastWithTitle:@"正在处理" userClick:false];
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
- UIImage *_image = [UIImage fixOrientation:image];
- CGImageRef imageRef = CGImageCreateWithImageInRect(_image.CGImage, value.CGRectValue);
- _image = [UIImage imageWithCGImage:imageRef];
- CGImageRelease(imageRef);
- _image = [self scaleImage:_image];
- dispatch_async(dispatch_get_main_queue(), ^{
- [vc.view dismissToast];
- [self dismissViewControllerAnimated:true completion:^{
- [self dismissViewControllerAnimated:true completion:nil];
- if (self->_spsb_caughtImage) {
- self->_spsb_caughtImage(_image);
- }
- }];
- });
- });
- }];
- [picker pushViewController:vc animated:true];
- }
- #pragma mark - 对焦
- - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
- UITouch *touch = [touches anyObject];
- CGPoint point = [touch locationInView:self.view];
- [self setFocusWithPoint:point];
- }
- - (void)setFocusWithPoint:(CGPoint)point {
- //将UI坐标转化为摄像头坐标
- CGPoint cameraPoint= [_previewlayer captureDevicePointOfInterestForPoint:point];
- [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
- if ([captureDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
- [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];
- }
- if ([captureDevice isFocusPointOfInterestSupported]) {
- [captureDevice setFocusPointOfInterest:cameraPoint];
- }
- }];
- }
- - (void)changeDeviceProperty:(void(^)(AVCaptureDevice *captureDevice))propertyChange {
- AVCaptureDevice *captureDevice = [_dataInput device];
- NSError *error;
- //注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁
- if ([captureDevice lockForConfiguration:&error]) {
- propertyChange(captureDevice);
- [captureDevice unlockForConfiguration];
- } else{
- debugLog(@"设置设备属性过程发生错误,错误信息:%@",error.localizedDescription);
- }
- }
- #pragma mark - Network Action
- #pragma mark - UI
- - (void)setupUI {
- [self createTools];
- }
- - (void)createTools {
- _imageView = [[UIImageView alloc] init];
- _imageView.contentMode = UIViewContentModeScaleAspectFill;
- [self.view addSubview:_imageView];
- [_imageView makeConstraints:^(JXHConstraintMaker *make) {
- make.edges.equalTo(UIEdgeInsetsMake(0, 0, 0, 0));
- }];
-
- CGFloat width = jxh_screenWidth() - 46 * 2;
- CGFloat height = width * SPSBIdentifierCardScale;
- CGFloat top = jxh_safeInsets(jxh_keyWindow()).bottom == 0 ? 50.f : 90.f;
- CGFloat bottom = jxh_safeInsets(jxh_keyWindow()).bottom == 0 ? 120.f : 158.f;
- CGFloat topInterval = (jxh_screenHeight() - top - bottom - jxh_safeInsets(jxh_keyWindow()).bottom - height) / 2;
-
- _topShadeViewHeight = top + topInterval;
- _leftShadViewWidth = 46.f;
- _bottomShadeViewHeight = bottom + jxh_safeInsets(jxh_keyWindow()).bottom + topInterval;
- UIView *topView = UIView.new;
- topView.backgroundColor = spsb_000000_color(1.f);
- [self.view addSubview:topView];
-
- [topView makeConstraints:^(JXHConstraintMaker *make) {
- make.top.leading.and.trailing.equalTo(0);
- make.height.equalTo(top);
- }];
-
- UIImageView *leftTop = [[UIImageView alloc] initWithImage:jxh_getImage(left_top)];
- [self.view addSubview:leftTop];
- [leftTop makeConstraints:^(JXHConstraintMaker *make) {
- make.leading.equalTo(self->_leftShadViewWidth);
- make.top.equalTo(self->_topShadeViewHeight);
- }];
-
- UIImageView *rightTop = [[UIImageView alloc] initWithImage:jxh_getImage(right_top)];
- [self.view addSubview:rightTop];
- [rightTop makeConstraints:^(JXHConstraintMaker *make) {
- make.trailing.equalTo(-self->_leftShadViewWidth);
- make.top.equalTo(self->_topShadeViewHeight);
- }];
-
- UIImageView *leftBottom = [[UIImageView alloc] initWithImage:jxh_getImage(left_bottom)];
- [self.view addSubview:leftBottom];
- [leftBottom makeConstraints:^(JXHConstraintMaker *make) {
- make.leading.equalTo(self->_leftShadViewWidth);
- make.bottom.equalTo(-self->_bottomShadeViewHeight);
- }];
-
- UIImageView *rightBottom = [[UIImageView alloc] initWithImage:jxh_getImage(right_bottom)];
- [self.view addSubview:rightBottom];
- [rightBottom makeConstraints:^(JXHConstraintMaker *make) {
- make.trailing.equalTo(-self->_leftShadViewWidth);
- make.bottom.equalTo(-self->_bottomShadeViewHeight);
- }];
-
- UIView *bottomView = UIView.new;
- bottomView.backgroundColor = spsb_000000_color(1.f);
- [self.view addSubview:bottomView];
-
- [bottomView makeConstraints:^(JXHConstraintMaker *make) {
- make.bottom.and.leading.and.trailing.equalTo(0);
- make.top.equalTo(self.view.safebottom).offset(-bottom);
- }];
-
- UIView *bottomTool = UIView.new;
- [bottomView addSubview:bottomTool];
- [bottomTool makeConstraints:^(JXHConstraintMaker *make) {
- make.top.and.leading.and.trailing.equalTo(0);
- make.bottom.equalTo(bottomView.safebottom);
- }];
-
- UIButton *takePhotoButton = [UIButton convenienceWithTarget:self action:@selector(takePhotoAction)];
- [takePhotoButton setImage:jxh_getImage(photo_btn_n) state:JXHButtonControlStateNormal];
- [bottomTool addSubview:takePhotoButton];
- [takePhotoButton makeConstraints:^(JXHConstraintMaker *make) {
- make.center.equalTo(0);
- }];
-
- UIButton *openPhotoAlbumButton = [UIButton convenienceWithFont:spsb_font(16) target:self action:@selector(openPhotoAlbum)];
- [openPhotoAlbumButton setTitle:@"相册" titleColor:spsb_FFFFFF_color(1.f) state:JXHButtonControlStateNormal];
- [bottomView addSubview:openPhotoAlbumButton];
- [openPhotoAlbumButton makeConstraints:^(JXHConstraintMaker *make) {
- make.leading.equalTo(40);
- make.centerY.equalTo(takePhotoButton);
- }];
-
- UIButton *cancelButton = [UIButton convenienceWithFont:spsb_font(16) target:self action:@selector(backAction)];
- [cancelButton setTitle:@"取消" titleColor:spsb_FFFFFF_color(1.f) state:JXHButtonControlStateNormal];
- [bottomView addSubview:cancelButton];
- [cancelButton makeConstraints:^(JXHConstraintMaker *make) {
- make.trailing.equalTo(-40);
- make.centerY.equalTo(takePhotoButton);
- }];
- _tipsLabel = [UILabel convenienceWithFont:spsb_font(16) text:@"请将身份证对准框内,建议横屏拍摄" textColor:spsb_FFFFFF_color(1.f) textAlignment:NSTextAlignmentCenter];
- _tipsLabel.backgroundColor = spsb_000000_color(0.3);
- [_tipsLabel setLayerCornerRadius:22.5 clipToBounds:true];
- [self.view addSubview:_tipsLabel];
- [_tipsLabel makeConstraints:^(JXHConstraintMaker *make) {
- make.centerX.equalTo(self.view);
- make.centerY.equalTo(self.view.top).offset(self->_topShadeViewHeight + height / 2);
- make.size.equalTo(CGSizeMake(286, 45));
- }];
- }
- @end
|