IOS: 使用imageIO获取和修改图片的exif信息

时间:2022-12-10 22:48:06

使用imageIO获取和修改图片的exif信息

  一幅图片除了包含我们能看见的像素信息,背后还包含了拍摄时间,光圈大小,曝光等信息。UIImage类将这些细节信息都隐藏了起来,只提供我们关心的图片尺寸,图片方向等。我们可以通过imageIO框架获取到图片背后的所有信息,下面就让我们一起看看。

一、获取图片信息

  imageIO框架是iOS中偏底层一点儿的框架,它内部提供的接口都是C风格的,关键数据也都是使用CoreFoundation进行存储。庆幸的是CoreFoundation中有很多数据类型都可以上层的数据Foundation框架中的数据类型进行无缝桥接。这也就大大方便了我们对图片信息的操作。

  CGImageSourceRef是整个imageIO的入口,通过它我们可以完成从文件的加载图片。加载完成以后我们就得到一个CGImageSourceRef,通过CGImageSourceRef我们就可以获取图片文件的大小,UTI(uniform type identifier),内部包含几张图片,访问每一张图片以及获取每张图片对应的exif信息等。

  你可能会有一个疑问,为什么会有几张图片呢?

  这块儿我解释一下,imageSourceRef和文件是一一对应的,通常我们见到的图片文件(例如jpg,png)内部都只有一张图片,这种情况我们通过CGImageSourceGetCount方法得到的就会是1。但是不能排除一个图片文件中会有多种图片的情况,例如gif文件,这个时候一个文件中就可能包含几张甚至几十张图片。前面我写的一片博客《IOS中如何解析并显示Gif》就是通过imageSource实现加载和解析gif的功能。

  下面是系统相机拍的照片的exif信息:

image property: {
ColorModel = RGB;
DPIHeight = ;
DPIWidth = ;
Depth = ;
Orientation = ;
PixelHeight = ;
PixelWidth = ;
"{Exif}" = {
ApertureValue = "2.526069";
BrightnessValue = "-0.5140446";
ColorSpace = ;
ComponentsConfiguration = (
,
,
, );
DateTimeDigitized = "2013:06:24 22:11:30";
DateTimeOriginal = "2013:06:24 22:11:30";
ExifVersion = (
,
, );
ExposureMode = ;
ExposureProgram = ;
ExposureTime = "0.06666667";
FNumber = "2.4";
Flash = ;
FlashPixVersion = (
, );
FocalLenIn35mmFilm = ;
FocalLength = "4.13";
ISOSpeedRatings = ( );
MeteringMode = ;
PixelXDimension = ;
PixelYDimension = ;
SceneCaptureType = ;
SensingMethod = ;
ShutterSpeedValue = "3.906905";
SubjectArea = (
,
,
, );
WhiteBalance = ;
};
"{GPS}" = {
Altitude = "27.77328";
AltitudeRef = ;
Latitude = "22.5645";
LatitudeRef = N;
Longitude = "113.8886666666667";
LongitudeRef = E;
TimeStamp = "14:11:23.36";
};
"{TIFF}" = {
DateTime = "2013:06:24 22:11:30";
Make = Apple;
Model = "iPhone 5";
Orientation = ;
ResolutionUnit = ;
Software = "6.1.4";
XResolution = ;
YResolution = ;
"_YCbCrPositioning" = ;
};
}

Exif info

  从中我们可以看出最开始的几项分别显示了当前图片的颜色模式,色深,x,y方向的DPI,实际像素以及图片的方向。我最开始看到这个方向时,心中一喜这不是UIImage中的imageOrientation,但是实验发现这个方向和UIImage中的imageOrientation并不相等,此处的方向是exif标准定义的方向,从1到8分别对应这UIImage中的8个方向,只是顺序不一样,它们对应关系如下:

enum {
exifOrientationUp = , // UIImageOrientationUp
exifOrientationDown = , // UIImageOrientationDown
exifOrientationLeft = , // UIImageOrientationLeft
exifOrientationRight = , // UIImageOrientationRight // these four exifOrientation does not support by all camera, but IOS support these orientation
exifOrientationUpMirrored = , // UIImageOrientationUpMirrored
exifOrientationDownMirrored = , // UIImageOrientationDownMirrored
exifOrientationLeftMirrored = , // UIImageOrientationLeftMirrored
exifOrientationRightMirrored = , // UIImageOrientationRightMirrored
};
typedef NSInteger ExifOrientation;

  目前市面上的大部分数码相机和手机都会内置一个方向感应器,拍出的照片中会写如方向信息,但是通常都只会有前四种方向。这几种Mirrored方向通常都是手机前置摄像头自拍的时候才会设置。

  exif为什么要搞这么一个方向呢?

  几乎所有的摄像头在出场的时候成相芯片都是有方向的,拍出来的照片的像素都是默认方向的。如果每拍一张照片就对这些像素进行旋转,如果数码相机每秒连拍20张来算,旋转操作将会非常耗时。更聪明的做法是拍照时只记录一个方向,然后显示的时候按方向显示出来即可。因此exif定义了一个标准的方向参数,只要读图的软件都来遵守规则,加载时候读取图片方向,然后做相应的旋转即可。这样既可以达到快速成像的目的,又能达到正确的显示,何乐而不为呢。

  常见的图片浏览和编辑软件都遵守这个规则,但是有一个我们最常用的看图软件(windows自带的看图程序)不会去读这个方向,因此我们将数码相机和手机拍出来的图片导入windows上时,会经常遇到方向错误的问题。不知道windows帝国是怎么想的,或许和定义exif的组织有什么过节吧。

  图片信息中除了上面看提到的那些,还有拍摄的GPS信息,iOS自带的相册软件中的地点tab就是按照GPS信息实现的。还有很多其他的信息,感兴趣的可以自己写个程序研究研究,这里就不展开了。

二、修改图片exif信息

  我们除了可以通过CGImageSourceRef读取图片信息,还可以通过CGImageDestinationRef来创建图片文件,在创建的时候我们可以指定很多信息。例如我们可以通过CGImageDestinationRef来修改现有图片的GPS信息,图片方向,甚至还可以自己写一个制作gif的小工具。

  这块儿我做了个实验,通过修改图片信息的方向,来完成旋转图片的功能。原图方向为1(exif方向),我修改为3。保存后发现图片的确翻转过来了。于是更进一步想着试一下看看能不能完成90°旋转的功能,于是把图片方向改为6,保存后发现通过UIImage加载的图片显示出现问题了,虽然方向是转过来了,但是显示却被拉伸了。但是把保存后的图片存到系统相册,发现一切正常。

  到底是哪块儿出了问题呢?

  我想了一下是不是应该在修改方向的同时修改一下图片的pixelWidth和pixelHeight参数,于是满心欢喜的尝试了一下,结果还是UIImage加载出来还是拉伸显示,导入系统相册依旧正常。郁闷了到底是什么参数没设置对呢?暂时还没有什么思路,各路英雄要是有什么思路的话欢迎一起讨论。

  

  测试工程下载地址: https://github.com/smileEvday/SvImageInfo

  测试工程中包含读取图片信息和修改图片方向的工具类,以及简单的测试代码。上面修改图片方向的那个问题还是没有解决,希望路过的英雄能帮忙看看问题出在哪里,给点儿建议,谢谢。

 

  注1: 文章中关于exif信息中图片方向的知识主要参考国外一个博客JPEG Rotation and EXIF Orientation,真佩服他们研究问题的那种精神,写的很细致,大家感兴趣可以看看。

  注2:转载请著名出处,我的QQ: 1592232964,关于博客中提到的那个问题有任何好的建议欢迎联系我,感激不尽!!!

IOS: 使用imageIO获取和修改图片的exif信息的更多相关文章

  1. 在Android下通过ExifInterface类操作图片的Exif信息

    什么是Exif 先来了解什么是Exif.Exif是一种图像文件格式,它的数据存储于JPEG格式是完全相同的,实际上Exif格式就是JPEG格式头插入了 数码照片的信息,包括拍摄的光圈.快门.平衡白.I ...

  2. C# 获取图片的EXIF 信息

    关于 EXIF 信息的介绍. 1  EXIF,是英文Exchangeable Image File(可交换图像文件)的缩写.EXIF是一种图像文件格式,只是文件的后缀名为jpg.EXIF信息是由数码相 ...

  3. 用C#读取图片的EXIF信息的方法

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Dr ...

  4. 利用php获取图片完整Exif信息类 获取图片详细完整信息类

    <?php /** * @Author: TonyLevid * @Copyright: TonyLevid.com * @Name: Image Exif Class * @Version: ...

  5. 获取图片的EXIF信息

    对于专业的摄影师来说,Exif信息是很重要的信息,也包含了非常多的东西 1.EXIF EXIF(Exchangeable Image File)是“可交换图像文件”的缩写,当中包含了专门为数码相机的照 ...

  6. 使用Java程序读取JPG Tif等格式图片的exif信息

    package com.util; import java.io.File;import java.util.Iterator; import com.drew.imaging.ImageProces ...

  7. IOS 修改图片的地理位置信息

    直接上代码: // // ViewController.m // changeLocation // // Created by 陈飞 on 16/10/31. // Copyright © 2016 ...

  8. Android--操作图片Exif信息

    前言 在Android系统中,图片文件在内存中以像素点的二维数组加载,存放像素信息,还会在开头加上一些额外的照片拍摄参数信息,这些信息就是Exif.Android2.0之后,媒体库加入了操作图片Exi ...

  9. Android 图片Exif信息相关的获取与修改

    1 Exif是什么 Exif是一种图像文件格式,它的数据存储于JPEG格式是完全相同的,实际上Exif格式就是JPEG格式头插入了 数码照片的信息,包括拍摄的光圈.快门.平衡白.ISO.焦距.日期时间 ...

随机推荐

  1. java 去掉html标签

    使用正则表达式删除HTML标签. import java.util.regex.Matcher; import java.util.regex.Pattern; public class HTMLSp ...

  2. website architecture

    如果在不仔细考虑网站架构的情况下就去做一个网站,这就像在没有规划行程前而去贸然旅行.你可能最终到了你的目的终点,但是你可能也不知道在这过程中,你已经走过了多少的弯路.做网站适用同样的道理.在开工之前, ...

  3. 如何在Linux下重命名多个文件

    在Linux中,当你想要改变一个文件名,使用mv命令就好了.然而mv不能使用通配符重命名多个文件.可以用sed.awk或者与xargs结合使用来处理多个文件的情况.然而,这些命令行即繁琐又不友好,并且 ...

  4. C51 函数&sol;程序段的定位

    在Keil C中可能需要指定某个函数或者某段程序链接后存放在程序区中的位置. 1. 如何指定某个函数在程序区中的位置. QUESTION How do I locate a C function at ...

  5. Android 如何修改自动同步数据的默认开关 M

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  6. kvm的sshd起不来

    同事不知道在一台KVM虚拟机执行了chmod -R 777 /  将更目录中的所有文件的权限都改为777,重启该虚拟机之后发现该虚拟机登不上去了,来找我,我尝试重启了几次虚拟机之后,发现总是可以被pi ...

  7. 在VS2010中使用Git管理源代码

    前文我们讲了使用TortoiseGit管理源代码,但是对于使用VS2010的朋友来说,源代码管理起来还是不怎么方便.要是直接在VS2010中能使用Git就好了,下面我们就来看看怎么在VS2010中使用 ...

  8. 20155321 《网络攻防》 Exp8 Web基础

    20155321 <网络攻防> Exp8 Web基础 基础问题回答 什么是表单? 表单是主要负责数据采集功能.主要是以下三个部分构成: 表单标签:包含处理表单数据所用的程序的URL以及数据 ...

  9. Spring源码分析(六)解析和注册BeanDefinitions

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 当把文件转换为Document后,接下来的提取及注册bean就是我们的重 ...

  10. java 获得字符串中最大重复子串长度

    参考:http://blog.csdn.net/csdn_yaobo/article/details/50338025 要找一串字符串中,重复的字串长度,.例如ABCX1&ABC,中ABC重复 ...