• 卡片机时代

  1. 很重要的一点是,相机本身是没有方向概念的,它不理解拍摄的内容,只会以相机自己的坐标系去保存数据,下图展示了相机对“F”进行四个角度拍摄时返回的图片数据。

  1. 最初的卡片机时代,照片都会经由底片洗出来,那时不存在照片的方向问题,我们总可以把洗出来的照片通过简单的旋转来进行观看。比如这张照片墙中的照片,你能否说哪些照片是横着?哪些颠倒着?你甚至都无法判断每张照片相机是以何种角度拍摄的,因为每张都已经旋转至适合观看的角度。

  • 数码时代

  1. 可是到了数码时代,不再需要底片,照片需要被存成一个图像文件。对于上面的拍摄角度,存储方式并没有变化,所有的场景仍然是以相机的坐标系来保存。于是这些照片仍像上面一样,原封不动的保存了下来。
  2. 虽然存储方式不变,和卡机机时代的实体相片不同的是,由于电子设备可不知道照片应该如何旋转,只能够以它存储于磁盘中的方向来展示。这便是为何照片传到电脑上之后,会出现横了,或者颠倒的情况。
  • 方向传感器

  1. 为了克服这一情况,让照片可以真实的反应人们拍摄时看到的场景,现在很多相机中就加入了方向传感器,它能够记录下拍摄时相机的方向,并将这一信息保存在照片中。照片的存储方式还是没有任何改变,它仍然是以相机的坐标系来保存,只是当相机来浏览这些照片时,相机可以根据照片中的方向信息,结合此时相机的方向,对照片进行旋转,从而转到适合人们观看的角度。
  • iPhone上的情况

  1. iOS的设备中也包含了方向传感器,它但是它默认的照片方向并不是竖着拿手机时的情况,而是横向,即Home键在右侧,如下:

  1. 如此一来,如果竖着拿手机拍摄时,就相当于对手机顺时针旋转了90度,也即上面相机图片中的最后一幅

  • iPhone拍照方向问题处理

iPhone通过API获取到的是图片内容数据,不带方向信息,此时,我们需要手动的根据传感器方向将方向信息填充进去,并且根据方向信息对照片进行相应的旋转,得到人类视角正向的图片。代码如下:

  1. //iOS11以上支持AVCapturePhotoOutput代理
  2. - (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo
  3. error:(NSError *)error {
  4. if (error) {
  5. NSLog(@"获取图片错误 --- %@",error.localizedDescription);
  6. }
  7. if (photo) {
  8. UIImageOrientation orient = UIImageOrientationUp;
  9. //后置摄像头
  10. if (self.shootingOrientation == UIDeviceOrientationLandscapeRight){
  11. orient = UIImageOrientationDown;
  12. }else if(self.shootingOrientation == UIDeviceOrientationPortrait){
  13. orient = UIImageOrientationRight;
  14. }else if(self.shootingOrientation == UIDeviceOrientationLandscapeLeft){
  15. orient = UIImageOrientationUp;
  16. }else if(self.shootingOrientation == UIDeviceOrientationPortraitUpsideDown){
  17. orient = UIImageOrientationLeft;
  18. }
  19. //前置摄像头
  20. AVCaptureDevice *currentDevice = [self.videoWriterManager.videoInput device];
  21. AVCaptureDevicePosition currentPosition = [currentDevice position];
  22. if (currentPosition == AVCaptureDevicePositionFront){
  23. //前置摄像头
  24. if (self.shootingOrientation == UIDeviceOrientationLandscapeRight){
  25. orient = UIImageOrientationUp;
  26. }else if(self.shootingOrientation == UIDeviceOrientationLandscapeLeft){
  27. orient = UIImageOrientationDown;
  28. }
  29. }
  30. UIImage *image = [UIImage imageWithCGImage:photo.CGImageRepresentation scale:1 orientation:orient];
  31. //图片修正为人类视角看起来正向的图片
  32. //[self fixOrientation:image];
  33. }
  34. }
  35. //将原始图片数据调整为 人类视角正向的图片
  36. - (UIImage *)fixOrientation:(UIImage *)image{
  37. // No-op if the orientation is already correct
  38. if (image.imageOrientation == UIImageOrientationUp) return image;
  39. // We need to calculate the proper transformation to make the image upright.
  40. // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
  41. CGAffineTransform transform = CGAffineTransformIdentity;
  42. CGFloat imageWidth = CGImageGetWidth(image.CGImage);
  43. CGFloat imageHeight = CGImageGetHeight(image.CGImage);
  44. //创建的位图宽高
  45. CGFloat contextWidth = imageWidth < imageHeight ? imageWidth : imageHeight;
  46. CGFloat contextHeight = imageWidth > imageHeight ? imageWidth : imageHeight;
  47. switch (image.imageOrientation) {
  48. case UIImageOrientationDown:
  49. case UIImageOrientationDownMirrored:{
  50. //创建横着显示的位图上下文,宽大于高
  51. CGFloat temp = contextWidth;
  52. contextWidth = contextHeight;
  53. contextHeight = temp;
  54. //旋转180度
  55. transform = CGAffineTransformTranslate(transform, contextWidth, contextHeight);
  56. transform = CGAffineTransformRotate(transform, M_PI);
  57. }
  58. break;
  59. case UIImageOrientationLeft:
  60. case UIImageOrientationLeftMirrored:
  61. //逆时针旋转90度
  62. transform = CGAffineTransformTranslate(transform, contextWidth, 0);
  63. transform = CGAffineTransformRotate(transform, M_PI_2);
  64. break;
  65. case UIImageOrientationRight:
  66. case UIImageOrientationRightMirrored:
  67. //顺时针90度
  68. transform = CGAffineTransformTranslate(transform, 0, contextHeight);
  69. transform = CGAffineTransformRotate(transform, -M_PI_2);
  70. break;
  71. default:
  72. break;
  73. }
  74. switch (image.imageOrientation) {
  75. case UIImageOrientationUpMirrored:
  76. case UIImageOrientationDownMirrored:
  77. //镜像图片Y轴翻转坐标系
  78. transform = CGAffineTransformTranslate(transform, contextWidth, 0);
  79. transform = CGAffineTransformScale(transform, -1, 1);
  80. break;
  81. case UIImageOrientationLeftMirrored:
  82. case UIImageOrientationRightMirrored:
  83. //镜像图片Y轴翻转坐标系
  84. transform = CGAffineTransformTranslate(transform, contextHeight, 0);
  85. transform = CGAffineTransformScale(transform, -1, 1);
  86. break;
  87. default:
  88. break;
  89. }
  90. //创建竖直显示的画布
  91. CGContextRef ctx = CGBitmapContextCreate(NULL, contextWidth, contextHeight,
  92. CGImageGetBitsPerComponent(image.CGImage), 0,
  93. CGImageGetColorSpace(image.CGImage),
  94. CGImageGetBitmapInfo(image.CGImage));
  95. CGContextConcatCTM(ctx, transform);
  96. CGContextDrawImage(ctx, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);
  97. // And now we just create a new UIImage from the drawing context
  98. CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
  99. UIImage *img = [UIImage imageWithCGImage:cgimg];
  100. CGContextRelease(ctx);
  101. CGImageRelease(cgimg);
  102. return img;
  103. }

图片来源于(https://feihu.me/blog/2015/how-to-handle-image-orientation-on-iOS/)

参考 https://feihu.me/blog/2015/how-to-handle-image-orientation-on-iOS/

iOS自定义拍照框拍照&裁剪(一)的更多相关文章

  1. iOS Swift WisdomScanKit二维码扫码SDK,自定义全屏拍照SDK,系统相册图片浏览,编辑SDK

    iOS Swift WisdomScanKit 是一款强大的集二维码扫码,自定义全屏拍照,系统相册图片编辑多选和系统相册图片浏览功能于一身的 Framework SDK [1]前言:    今天给大家 ...

  2. 如何用uniapp+vue开发自定义相机插件——拍照+录像功能

    调用手机的相机功能并实现拍照和录像是很多APP与插件都必不可少的一个功能,今天智密科技就来分享一下如何基于uniapp + vue实现自定义相机界面,并且实现: 1: 自定义拍照 2: 自定义录像 3 ...

  3. Android Camera开发系列(下)——自定义Camera实现拍照查看图片等功能

    Android Camera开发系列(下)--自定义Camera实现拍照查看图片等功能 Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 上 ...

  4. ios手机竖屏拍照图片旋转90°问题解决方法

    手机拍照会给图片添加一个Orientaion信息(即拍照方向),如下: 用ios手机拍照,系统会给图片加上一个方向的属性, ios相机默认的拍照方向是后摄Home键在右为正,前摄Home键在左为正. ...

  5. iOS开发UI篇 -- UISearchBar 属性、方法详解及应用(自定义搜索框样式)

    很多APP都会涉及到搜索框,苹果也为我们提供了默认的搜索框UISearchBar.但实际项目中我们通常需要更改系统默认搜索框的样式.为了实现这一目标,我们需要先搞懂 UISearchBar 的属性及方 ...

  6. iOS自定义的UISwitch按钮

    UISwitch开关控件 开关代替了点选框.开关是到目前为止用起来最简单的控件,不过仍然可以作一定程度的定制化. 一.创建 UISwitch* mySwitch = [[ UISwitchalloc] ...

  7. vue3系列:vue3.0自定义弹框组件V3Popup|vue3.x手机端弹框组件

    基于Vue3.0开发的轻量级手机端弹框组件V3Popup. 之前有分享一个vue2.x移动端弹框组件,今天给大家带来的是Vue3实现自定义弹框组件. V3Popup 基于vue3.x实现的移动端弹出框 ...

  8. 【iOS自定义键盘及键盘切换】详解

    [iOS自定义键盘]详解 实现效果展示: 一.实现的协议方法代码 #import <UIKit/UIKit.h> //创建自定义键盘协议 @protocol XFG_KeyBoardDel ...

  9. 在ASP.NET中引用自定义提示框

    在html网页中自定义提示框 正文: 在一般的B/S架构中项目,与用户的交互信息是非常重要的.在一般的情况下,设计人员都在把用户信息呈现在html中,用div和span去弹出相关信息.对于一般的情况而 ...

随机推荐

  1. mysql:刚刚知道的冷知识(一)

    唯一索引的值可以null 1.创建一张user表,name字段指定为唯一索引 create table user( id int primary key auto_increment, name va ...

  2. [源码解析] 深度学习流水线并行之PopeDream(1)--- Profile阶段

    [源码解析] 深度学习流水线并行之PopeDream(1)--- Profile阶段 目录 [源码解析] 深度学习流水线并行之PopeDream(1)--- Profile阶段 0x00 摘要 0x0 ...

  3. C++之常指针,指针常量,函数指针,const用法总结

    1.const char *p,char const *p,char * const p 对于C++而言,没有const * 修饰符,所以,const只可以修饰类型或者变量名.因而const char ...

  4. 痞子衡嵌入式:MCUXpresso IDE下将关键函数重定向到RAM中执行的几种方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是MCUXpresso IDE下将关键函数重定向到RAM中执行的几种方法. 前段时间痞子衡写了一篇 <在IAR开发环境下将关键函数重 ...

  5. 第23篇-虚拟机对象操作指令之getstatic

    Java虚拟机规范中定义的对象操作相关的字节码指令如下表所示. 0xb2 getstatic 获取指定类的静态域,并将其值压入栈顶 0xb3 putstatic 为指定的类的静态域赋值 0xb4 ge ...

  6. Python - poetry(2)命令介绍

    poetry 语法格式 poetry [-h] [-q] [-v [<...>]] [-V] [--ansi] [--no-ansi] [-n] <command> [< ...

  7. (7)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Boot Starter的介绍及使用

    ​ Spring Boot 的便利性体现在,它简化了很多烦琐的配置,这对于开发人员来说是一个福音,通过引入各种 Spring Boot Starter 包可以快速搭建出一个项目的脚手架推荐分布式架构源 ...

  8. k8s 部署elasticsearch报 max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

    1.由于登不上云的节点 不采用修改节点配置的方式 修改部署的stateful 加上 initContainers 它和 containers 同一层级的 initContainers: - name: ...

  9. 使用Java api对HBase 2.4.5进行增删改查

    1.运行hbase 2.新建maven项目 2.将hbase-site.xml放在项目的resources文件夹下 3.修改pom.xml文件,引入hbase相关资源 <repositories ...

  10. webpack learn1-初始化项目1

    使用Visual  Studio Code软件使用准备,先安装一些插件,加快开发效率(还有Language Packs 选择简体中文安装后重启软件,可切换为中文): 下面是项目初始化步骤: 1 软件打 ...