背景

首先,先要了解Exif是个什么东东,搬出百度百科

可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。

说到底Exif就是一种格式,用来存储图片的一些信息,这些信息和我们日常比较相关的有拍摄设备,拍摄地点,图片尺寸等,不过今天的主角是另外一个——那就是图片方向(orientation)。这个图片方向不是指我们平时使用图片编辑器旋转的方向,而是拍照时手机的方向。总共有八个方向:

下图是JPEG ORIENTATION对应图片方向的纠正算法,这里它通过三位二进制数代表八种方向,然后再通过每一位二进制数对应不同的操作来对图片进行纠正,如下:

最高位二进制数代表对角线翻转的操作,第二位二进制数代表旋转180度的操作,最低位代表水平翻转的操作。
例如001,就是水平翻转,所以可以看到001的图形和原图形关于水平轴对称。通过把八个方向的图形用3个二进制数即三种操作组合,就可以很方便的对图形做转换,编码伪代码如下:

if (value & 100b != 0)  image.flip-diagonally
if (value & 010b != 0)  image.rotate-180
if (value & 001b != 0)  image.flip-horizontally

那有人就会困惑了,自己怎么平时没有看到这种图片呢,这是因为我们使用的图片查看器或者是浏览器对orientation做了兼容,会对展示的图片做转换。

如下是windows文件夹的展示:

下面则是Android Studio的图片展示

所以可以看到,windows是默认对图片orientation做了处理,而Android的ImageView则没有处理所以看到的是图片本来的方向。
这是八个F的图片链接。

应用

在Android里面,三星手机的拍照是个奇葩的存在,三星手机的exif是旋转90度,别家手机则是0度,所以三星手机的照片需要做处理,这里是一张三星手机照片的exif信息:

三星手机的方向是Rotate 90CW,意思就是需要顺时针方向(ClockWise)旋转90度。
脑壳转的快的同学可以对照上面的F图,相信很快看出是101这张图。
那我们取出图片的orientation值进行验证:

        try {val exifInterface = ExifInterface(resources.openRawResource(id))val orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)Log.e("orientation", orientation.toString())} catch (e: IOException) {e.printStackTrace()}

打印结果是6,和上面的101对不上,其实在Android的orientation是需要做减1处理的,也就是说6其实对应的是101这种状态。另外,需要注意的是,如果打印结果是0,那么说明图片没有orientation这个信息。

那接下来我们进行编码,这是第一张方式:

  val options = BitmapFactory.Options()var bitmap = BitmapFactory.decodeResource(resources, R.mipmap.error_orientation, options)val matrix = Matrix()matrix.postRotate(getOrientation(R.mipmap.error_orientation).toFloat())bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)imageview.setImageBitmap(bitmap)private fun getOrientation(id:Int): Int {var degree = 0try {val exifInterface = ExifInterface(resources.openRawResource(id))val orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)when (orientation) {ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270}} catch (e: IOException) {e.printStackTrace()}return degree}

一般来说,我们只需要处理这三种角度,上面三个角度对应的orientation是6 3 8,也就是101,010,111这三种状态。为什么一般只需要处理这三种状态呢,自己脑补一下拿相机的角度,不外乎就四种情况,除了正常的情况下,不就只需要处理三种情况吗?嘿嘿,我真是个小机灵鬼。
当然,如果要严谨一点,还是需要按照JPEG那种操作方式来,如下:

 val options = BitmapFactory.Options()var bitmap = BitmapFactory.decodeResource(resources, R.mipmap.f7t, options)val matrix = genOrientationMatrix(R.mipmap.f7t)bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)imageview.setImageBitmap(bitmap)private fun genOrientationMatrix(id:Int): Matrix {val matrix = Matrix()try {val exifInterface = ExifInterface(resources.openRawResource(id))var orientation =  exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)if (orientation > 0) {orientation--if (orientation and 0b100 != 0) { //对角线翻转matrix.postScale(-1.0f, 1.0f)matrix.postRotate(-90f)}if (orientation and 0b010 != 0) { //旋转180度matrix.postRotate(180f)}if (orientation and 0b001 != 0) { //水平翻转matrix.postScale(-1.0f, 1.0f)}}return matrix} catch (e: IOException) {e.printStackTrace()}return matrix}

其实就是将JPEG对于orientation的转换利用代码进行实现,对矩阵进行相应的变换。

总结

Exif是一种存储了相片一些信息的格式,平常我们在进行Android开发的时候,一般需要考虑方向的问题,但是在日常生活,这个也是暴露我们隐私的入口,所以手机在拍照的时候,最好将保存位置这些选项关闭,避免泄漏自己的隐私。

参考

Android性能优化:图片保存,还能更快

JPEG Orientation

Exif图片方向的一些发现相关推荐

  1. 基于exif信息进行图片方向旋转修正

    基于exif信息进行图片方向旋转修正 在处理标注数据的时候,发现标注框不吻合经过分析发现标注软件在读取图片时,读取了图片的exif信息,并对图片进行了旋转,所以标注的坐标时旋转后的坐标. 解决方法有两 ...

  2. C# 根据图片exif调整方向

    今天在用webuploader插件做上传图片,发现用IOS系统上传的图片,在预览的时候方向是正常的,但是传到后台后,方向错误,所以找了下面的方法,在储存以前先对图片方向进行调整: /// <su ...

  3. JS获取图片的EXIF信息+纠正图片方向

    前端图片处理碰到的一个离奇 bug , 关于图片的 EXIF 信息,特地记录下来 . 然后使用一下代码可以获取Orientation信息,并纠正Orientation带来的图片旋转问题 // from ...

  4. java自动旋转矫正图片方向

    java自动旋转矫正图片方向 maven引用 <dependencies><dependency><groupId>com.drewnoakes</group ...

  5. 如何批量旋转图片方向,包教会方法分享

    如何批量旋转图片方向,这个怎么搞呢?小编曾经遇到一个问题,就是我将手机上的照片上传到电脑后发现所有的图片都是倒立的,这让查看变得非常不方便.尽管小编已经尝试过打开每张图片并逐个旋转后再另存为,但这种方 ...

  6. 使用七牛图片遇到的图片方向翻转问题

    需求场景: 移动端项目,用户上传图片,然后前端进行滤镜处理并加入文字在图片上,返回给用户处理过后的图片,结果页可分享. 最开始的想法是通过canvas处理本地图片,然后将canvas转成图片,再把转换 ...

  7. 在web中如何调整上传过的图片方向 (exif)

    前提: 相机中拍的照片放到web上不会自动识别方向,如有些竖向显示的照片放到web上横向显示.这些照片在windows上是正确显示的.但是web不会自动旋转照片到正确方向.下面我们通过两种方法来实现这 ...

  8. android 图片方向,Android图片处理:识别图像方向并显示

    在Android中使用ImageView显示图片的时候发现图片显示不正.方向偏了或者倒过来了. 解决问题非常自然想到的分两步走: 1.自己主动识别图像方向,计算旋转角度. 2.对图像进行旋转并显示. ...

  9. android摄像头方向与屏方向,Android通过ExifInterface判断Camera图片方向的方法

    Android的Camera相关应用开发中,有一个必须搞清楚的知识点,就是Camera的预览方向和拍照方向 图像的Sensor方向:手机Camera的图像数据都是来自于摄像头硬件的图像传感器(Imag ...

最新文章

  1. 入门Python,限时1元!
  2. 一篇关于Qt开发技巧的文章收藏
  3. 分布式认知在计算机应用系统,人机交互作业
  4. linux网络配置、ssh、scp及命令优先级作业
  5. pku 1463 Strategic game 树形DP
  6. 江西省普通高考2021艺术楼统考成绩查询,统考成绩查询
  7. linux 文件编码格式转换-转
  8. ssm read time out的原因_为什么得肝病的男人越来越多?爱喝酒不是原因,或跟老婆有关系!...
  9. gbk编码在线转换工具_珍藏的4个PDF格式转换网站「在线工具,无需下载,还免费哦。」...
  10. 性能可靠服务器虚拟化,服务器虚拟化分析
  11. ETL调优的一些分享
  12. Java并发编程之ThreadLocal详解
  13. Mybatis selectKey标签的keyProperty属性报错,关键字间隔不能有空格
  14. 2018年大学生创业项目推荐
  15. 系统版本与服务器版本不一致,服务器sql版本不一致,请问如何恢復备份
  16. 数据管理能力成熟度DCMM-简介
  17. 马建威android视频,5.25春季班高级班第三期第五节课课堂总结
  18. mysql指令sum_MySQL Sum()函数
  19. 计算机取代人脑的英语作文,关于电脑和人脑差别的英语作文
  20. 新的任务发布平台源码

热门文章

  1. 年轻人最in的选择!HCK哈士奇x可口可乐联名限量款冰吧
  2. 经典的排错过程 expected unqualified-id before string constant
  3. 电压和电流反馈判别及例子,绝对让你通透,其实也没有那么难,一次就看懂!从此终于搞懂了电压反馈和电流反馈!
  4. python控制ppt翻页_详解Python操作PPT的各种骚操作!
  5. java 数据写入txt乱码_java写入文件是乱码
  6. 如何用PPT编制方案 — 1. PPT的总体规划
  7. ModelSim-Altera路径找不到或者不正确的解决办法
  8. php通过udp上报日志,PHP日志扩展SeasLog-1.6.0,支持TCP,UDP发送
  9. Python入门: 贪吃蛇详解
  10. 2021年司钻(井下)考试及司钻(井下)考试报名