1 , 自定义相机,拿到照片,校正方向

AVCapturePhotoCaptureDelegate 的这个代理方法

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)

拿照片,


extension ZLCustomCamera: AVCapturePhotoCaptureDelegate {public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {if error != nil {return}if let imgData = photo.fileDataRepresentation(){self.session.stopRunning()if let img = UIImage(data: imgData){self.takedImage = img.fixOrientation()}self.takedImageView.image = self.takedImageself.takedImageView.isHidden = falseself.resetSubViewStatus()}}}

拿到照片后,让照片的头部朝上

extension UIImage {// 修复转向func fixOrientation() -> UIImage {if self.imageOrientation == .up {return self}var transform = CGAffineTransform.identityswitch self.imageOrientation {case .down, .downMirrored:transform = CGAffineTransform(translationX: self.size.width, y: self.size.height)transform = transform.rotated(by: .pi)case .left, .leftMirrored:transform = CGAffineTransform(translationX: self.size.width, y: 0)transform = transform.rotated(by: CGFloat.pi / 2)case .right, .rightMirrored:transform = CGAffineTransform(translationX: 0, y: self.size.height)transform = transform.rotated(by: -CGFloat.pi / 2)default:break}switch self.imageOrientation {case .upMirrored, .downMirrored:transform = transform.translatedBy(x: self.size.width, y: 0)transform = transform.scaledBy(x: -1, y: 1)case .leftMirrored, .rightMirrored:transform = transform.translatedBy(x: self.size.height, y: 0)transform = transform.scaledBy(x: -1, y: 1)default:break}guard let ci = self.cgImage, let colorSpace = ci.colorSpace else {return self}let context = CGContext(data: nil, width: Int(self.size.width), height: Int(self.size.height), bitsPerComponent: ci.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: ci.bitmapInfo.rawValue)context?.concatenate(transform)switch self.imageOrientation {case .left, .leftMirrored, .right, .rightMirrored:context?.draw(ci, in: CGRect(x: 0, y: 0, width: self.size.height, height: self.size.width))default:context?.draw(ci, in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))}guard let newCgimg = context?.makeImage() else {return self}return UIImage(cgImage: newCgimg)}
}

照片朝上,不用管,

朝左、朝右、朝下,都有一个旋转,

旋转后,相应的翻转坐标系,

然后从绘图上下文中,取出照片

2 , 旋转照片


var angleX: CGFloat = 0func rotateRhs() {guard let img = takedImage else {return}let radian = CGFloat.pi * 0.5angleX += 1takedImageView.transform = CGAffineTransform(rotationAngle: radian * angleX)if Int(angleX) % 2 == 1{takedImageView.frame = view.bounds}else{let ratio = img.size.height / img.size.widthlet w = UI.std.widthlet h = w * ratiotakedImageView.frame = CGRect(x: 0, y: 0, width: w, height: h)}takedImageView.center = CGPoint(x: UI.std.width * 0.5, y: UI.std.height * 0.5)}
弄一个属性,记录已经旋转了多少个 90 度,

旋转图片视图 takedImageView,

限定图片视图的 frame,

图片视图的 frame, 要么跟屏幕一致,要么根据分辨率

根据分辨率:
  • 此时, image.height > image.width

视图的 width = 屏幕 width,

然后等图片比例放大,可接受

就算 image.height > 屏幕 height,

也 OK

  • 此时, image.height <= image.width

视图的 width = 屏幕 width,

等图片比例放大,可接受

然后指定中心点

3, 重拍

    @objcfunc retakeBtnClick(){angleX = 0takedImageView.transform = .identitytakedImageView.frame = view.boundssession.startRunning()resetSubViewStatus()takedImage = nil}

恢复,记录的旋转角度

takedImageView 的 frame 和 transform 都重置

4, 结束旋转

@objc func doneBtnClick() {recordVideoPlayerLayer?.player?.pause()recordVideoPlayerLayer?.player = nildismiss(animated: true) {self.takeDoneBlock?(self.takedImage?.image(rotated: Int(self.angleX)))}}

根据旋转的角度,拿原图绘制,新图

extension UIImage{func image(rotated time: Int) -> UIImage{guard time != 0 else {return self}let radian = CGFloat(time) * CGFloat.pi / 2let rotatedSize = CGRect(origin: .zero, size: size).applying(CGAffineTransform(rotationAngle: radian)).integral.sizeUIGraphicsBeginImageContext(rotatedSize)if let context = UIGraphicsGetCurrentContext() {let origin = CGPoint(x: rotatedSize.width / 2.0,y: rotatedSize.height / 2.0)context.translateBy(x: origin.x, y: origin.y)context.rotate(by: radian)draw(in: CGRect(x: -origin.y, y: -origin.x,width: size.width, height: size.height))let rotatedImage = UIGraphicsGetImageFromCurrentImageContext()UIGraphicsEndImageContext()return rotatedImage ?? self}return self}}

github 链接

iOS 自定义相机,拍照旋转相关推荐

  1. uni-app 自定义相机拍照录像,可设置分辨率、支持横竖屏(ios、android)

    插件市场:uni-app 自定义相机拍照录像,可设置分辨率.支持横竖屏(ios.android)

  2. android自定义相机拍照

     Android中开发相机的两种方式: Android系统提供了两种使用手机相机资源实现拍摄功能的方法,一种是直接通过Intent调用系统相机组件,这种方法快速方便,适用于直接获得照片的场景,如上传相 ...

  3. Android自定义相机拍照、图片裁剪的实现

    原文:Android自定义相机拍照.图片裁剪的实现 最近项目里面又要加一个拍照搜题的功能,也就是用户对着不会做的题目拍一张照片,将照片的文字使用ocr识别出来,再调用题库搜索接口搜索出来展示给用户,类 ...

  4. android 自定义拍照模糊,Android自定义相机拍照模糊处理

    问题分析:随着用户对于拍照清晰度的需求,android手机对于摄像头也是一升再升,这就导致了作为android开发工程师对于兼容性维护的继续跟进以及问题处理. 针对于自定义相机拍照模糊的问题,经过几天 ...

  5. 微信小程序自定义相机拍照,计算大小,以及上传

    需求:近来微信小程序有个需求,自定义相机拍照,并且要在相机中画一个框,提示用户把拍摄内容放入框中,类似于上传身份证时那个头像,国徽对其的框.(因为我们上传的是一份A4纸的病例),所以需要这样.然后后台 ...

  6. ios 自定义拍照页面_iOS开发笔记:自定义相机拍照

    目录 之前用AVFoundation自定义相机做了拍照与视频相关的东西,为什么要自定义呢?主要是提供更个性化的交互设计,符合app主题,对于视频来说,也便于提供更多丰富有趣的功能.前段时间整理了下拍照 ...

  7. iOS自定义相机实现拍照和连拍

    我们常用的拍照模块,大部分代码都是一样的,甚至都不用改就可以直接拖进项目里面使用.但是这仅仅是简单的相机拍照功能,如果我们希望使用更多的功能,比如说连拍等,就需要多一点处理. 我们还是使用UIImag ...

  8. ios 自定义拍照页面_iOS 自定义相机拍照,手动对焦和自动对焦

    天下虚怀接空谷,何处高峰不入云. 一.相机界面绘制需要的一些宏 #define kScreenBounds [UIScreen mainScreen].bounds #define kPhotogra ...

  9. IOS 自定义相机, 使用 AVFoundation(附实现部分腾讯水印相机功能 demo)

    原文链接:http://www.jianshu.com/p/c64bf543f16a 这是一款使用 AVFoundation 自定义的相机,与系统原生相机有一样的外观但比系统的相机更好.更符合实际的开 ...

最新文章

  1. linux命令lscpu
  2. day1||python
  3. GYM 101669F - Binary Transformations
  4. 采用HttpModules来重写URLS
  5. 猫眼电影评论_电影的人群意见和评论家的意见一样好吗?
  6. C++/C--在堆栈中使用数组的区别
  7. 什么是暗物质?有没有理科大神解答一下啊?
  8. 无锁队列以及ABA问题
  9. call、apply和bind的用法与说明
  10. 修改卡巴斯基注册表,无限试用
  11. 水下无线光通信关键技术与未来展望
  12. 手游中控台多开脚本实战
  13. Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果)
  14. 华东师范大学软件工程专硕考研398分复习经验总结
  15. QGIS编译(跨平台编译)之三十九:QCA编译、QCA安装(Windows、Linux、MacOS环境下编译、安装)
  16. 华为交换机关闭服务端口
  17. TTS离线语音合成应用方案【一】
  18. anaconda创建一个新的虚拟环境
  19. 使用Jil序列化JSON提升Asp.net web api 性能
  20. 数据库原理之重要语法

热门文章

  1. Honeywell RTU2020使用.软件篇
  2. Freda的越野跑(openjudge)
  3. SAP SD MM PP HR FI CO EWM 等PA认证考试报名/指南/题库
  4. 删除Skypee顽固病毒(AutoIt3木马)
  5. IntelliJ IDEA默认的keymap设置是哪个?
  6. echarts拓扑图一些功能实现
  7. 游戏元素属性的设计原则
  8. MySQL常用SQL(含复杂SQL查询)
  9. 4路 HX5+Emulex 8Gb 实现 BOFM 实施 -chenjhh@dc
  10. 王者转区显示服务器列表错误,王者荣耀转区功能-王者转区服务-王者转移号-王者转服...