需求
需求:卖家版应用需要用到800*800的正方形照片才能上传;而且所见即所得,不能裁切照片。这就要求我们自定义相机界面、获取照片、处理。
说明
iOS 自定义相机 |(以后置拍照为例)
自定义像素分辨率 | (以800x800px为例)
自定义尺寸的照片 | (以正方形为例)
代码
#import
#import "UIImage+fixOrientation.h"
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
//强迫症的最爱
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@interface ViewController ()
//捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入)
@property (nonatomic, strong) AVCaptureDevice *device;
//AVCaptureDeviceInput 代表输入设备,他使用AVCaptureDevice 来初始化
@property (nonatomic, strong) AVCaptureDeviceInput *input;
//输出图片
@property (nonatomic ,strong) AVCaptureStillImageOutput *imageOutput;
//session:由他把输入输出结合在一起,并开始启动捕获设备(摄像头)
@property (nonatomic, strong) AVCaptureSession *session;
//图像预览层,实时显示捕获的图像
@property (nonatomic ,strong) AVCaptureVideoPreviewLayer *previewLayer;
@property (nonatomic ,strong) UIImage *image;
@property (nonatomic,strong) UILabel * msgLabel;
@end
- (void)viewDidLoad {
[super viewDidLoad];
// ---------------------------------// ---------------------------------
[self setupUI];
// ---------------------------------// ---------------------------------
[self cameraDistrict];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
self.view.backgroundColor = [UIColor whiteColor];
//设备取景开始
[self.session startRunning];
self.msgLabel.text = @"提示:点击拍照按钮";
}
- (void)setupUI {
// ---------------------------------// ---------------------------------
UIButton * photoBtn = [[UIButton alloc] init];
photoBtn.frame = CGRectMake(SCREEN_WIDTH * 0.5 - 50, SCREEN_HEIGHT - 200, 100, 100);
photoBtn.backgroundColor = [UIColor blackColor];
[photoBtn addTarget:self action:@selector(photoBtnDidClick) forControlEvents:UIControlEventTouchUpInside];
[photoBtn setTitle:@"拍照" forState:UIControlStateNormal];
[self.view addSubview:photoBtn];
// ---------------------------------// ---------------------------------
self.msgLabel = [[UILabel alloc] init];
self.msgLabel.text = @"提示:点击拍照按钮";
self.msgLabel.frame = CGRectMake(50, 100, SCREEN_WIDTH, 100);
[self.view addSubview:self.msgLabel];
self.msgLabel.textColor = [UIColor redColor];
// ---------------------------------// ---------------------------------
UISwitch * lightSwith = [[UISwitch alloc] initWithFrame:CGRectMake(50, 50, 100, 50)];
[lightSwith addTarget:self action:@selector(lightClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:lightSwith];
}
- (void)cameraDistrict
{
// AVCaptureDevicePositionBack 后置摄像头
// AVCaptureDevicePositionFront 前置摄像头
self.device = [self cameraWithPosition:AVCaptureDevicePositionBack];
self.input = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:nil];
self.imageOutput = [[AVCaptureStillImageOutput alloc] init];
self.session = [[AVCaptureSession alloc] init];
// 拿到的图像的大小可以自行设定
// AVCaptureSessionPresetHigh
// AVCaptureSessionPreset320x240
// AVCaptureSessionPreset352x288
// AVCaptureSessionPreset640x480
// AVCaptureSessionPreset960x540
// AVCaptureSessionPreset1280x720
// AVCaptureSessionPreset1920x1080
// AVCaptureSessionPreset3840x2160
self.session.sessionPreset = AVCaptureSessionPreset1920x1080;
//输入输出设备结合
if ([self.session canAddInput:self.input]) {
[self.session addInput:self.input];
}
if ([self.session canAddOutput:self.imageOutput]) {
[self.session addOutput:self.imageOutput];
}
//预览层的生成
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
self.previewLayer.frame = CGRectMake(0, SCREEN_HEIGHT * 0.5 - SCREEN_WIDTH * 0.5, SCREEN_WIDTH, SCREEN_WIDTH);
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer:self.previewLayer];
//设备取景开始
[self.session startRunning];
if ([_device lockForConfiguration:nil]) {
//自动闪光灯,
if ([_device isFlashModeSupported:AVCaptureFlashModeAuto]) {
[_device setFlashMode:AVCaptureFlashModeOff];
}
//自动白平衡,但是好像一直都进不去
if ([_device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]) {
[_device setWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];
}
[_device unlockForConfiguration];
}
}
//闪光灯开关
- (void)lightClick: (UISwitch *)lightSwitch{
if (lightSwitch.isOn) {
if ([_device lockForConfiguration:nil]) {
//自动闪光灯,
if ([_device isFlashModeSupported:AVCaptureFlashModeAuto]) {
[_device setFlashMode:AVCaptureFlashModeAuto];
}
}
}else {
if ([_device lockForConfiguration:nil]) {
//自动闪光灯,
if ([_device isFlashModeSupported:AVCaptureFlashModeAuto]) {
[_device setFlashMode:AVCaptureFlashModeOff];
}
}
}
}
///拍照点击
- (void)photoBtnDidClick
{
AVCaptureConnection *conntion = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];
if (!conntion) {
NSLog(@"拍照失败!");
return;
}
[self.imageOutput captureStillImageAsynchronouslyFromConnection:conntion completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (imageDataSampleBuffer == nil) {
return ;
}
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
self.image = [UIImage imageWithData:imageData];
[self.session stopRunning];
self.image = [self cropImage:self.image toRect:CGRectMake(0, (self.image.size.height - self.image.size.width) * 0.5, self.image.size.width, self.image.size.width)];
CGFloat width = 800;//宽度
CGFloat height = 800;//高度
UIGraphicsBeginImageContext(CGSizeMake(width, height));
[self.image drawInRect:CGRectMake(0,0, width, height)];
self.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self saveImageToPhotoAlbum:self.image];
}];
}
- (UIImage *)cropImage:(UIImage *)image toRect:(CGRect)rect {
CGFloat x = rect.origin.x;
CGFloat y = rect.origin.y;
CGFloat width = rect.size.width;
CGFloat height = rect.size.height;
CGRect croprect = CGRectMake(floor(x), floor(y), round(width), round(height));
UIImage *toCropImage = [image fixOrientation];// 纠正方向
CGImageRef cgImage = CGImageCreateWithImageInRect(toCropImage.CGImage, croprect);
UIImage *cropped = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
return cropped;
}
效果
UI界面仅供参考
[800*800成品照片]
[苹果相册不支持查看相片信息,我们借助第三方APP确认]