老铁们,大家好,相信还有很多朋友对于如何通过JPEG文件EXIF信息调整照片方向和的相关问题不太懂,没关系,今天就由我来为大家分享分享如何通过JPEG文件EXIF信息调整照片方向以及的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!
怎样应对
这个问题影响两个方面:
相机预览画面方向拍摄的照片的存储方向。对于预览方向,可以通过CameraInfo.orientation参数获取上面提到的旋转角度,然后通过Camera.setDisplayOrientation(int Degree)方法设置预览角度;
至于存储方向,情况就比较复杂了。设置旋转角度的方法如下:
Camera.Parameters参数;
参数.setRotation(旋转);
mCamera.setParameters(参数);但这样操作后,不同手机的处理是不同的。有些手机会直接将照片旋转到指定角度,但照片文件中EXIF信息中的方向不会改变(即仍然是0);有些手机只会将EXIF信息中的方向保存为对应的角度,而不会操作照片。方向。
因此,我们需要读取照片(JPEG文件)中的EXIF信息,并根据其方向旋转Bitmap。在Android中,有ExifInterface类来获取文件的EXIF信息,但该接口只支持用文件实例化,如下:
ExifInterface exif=null;
尝试{
exif=new ExifInterface(文件路径);
} catch (IOException ex) {
Log.e(TAG, "无法读取exif", ex);
}
如果(exif!=null){
int 方向=exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, -1);
}在相机的takePicture(shutter, raw, jpeg)方法回调的PictureCallback中,onPictureTaken(final byte[] data, Camera camera)方法获取照片的byte[]形式。我们可以直接从中读出我们需要的方向吗?信息在哪里?
其实在Android 4.1.1的Camera源码中,已经实现了一个非常简单的方法,如下:
//返回顺时针方向的度数。值为0、90、180 或270。
公共静态int getOrientation(byte[] jpeg) {
如果(jpeg==null){
返回0;
}
整数偏移量=0;
整数长度=0;
//ISO/IEC 10918-1:1993(E)
while (offset + 3 jpeg.length (jpeg[offset++]0xFF)==0xFF) {
int 标记=jpeg[偏移]0xFF;
//检查标记是否是填充。
如果(标记==0xFF){
继续;
}
偏移++;
//检查标记是SOI 还是TEM。
if (标记==0xD8 || 标记==0x01) {
继续;
}
//检查标记是EOI 还是SOS。
if (标记==0xD9 || 标记==0xDA) {
休息;
}
//获取长度并检查是否合理。
长度=pack(jpeg, 偏移量, 2, false);
if (长度2 || 偏移量+ 长度jpeg.length) {
Log.e(TAG, "长度无效");
返回0;
}
//如果APP1 中的标记为EXIF,则中断。
if (标记==0xE1 长度=8
包(jpeg, 偏移量+ 2, 4, false)==0x45786966
包(jpeg, 偏移量+ 6, 2, false)==0) {
偏移+=8;
长度-=8;
休息;
}
//跳过其他标记。
偏移量+=长度;
长度=0;
}
//JEITA CP-3451 Exif 版本2.2
如果(长度8){
//识别字节顺序。
int 标签=pack(jpeg, 偏移量, 4, false);
如果(标签!=0x49492A00 标签!=0x4D4D002A){
Log.e(TAG, "无效的字节顺序");
返回0;
}
布尔littleEndian=(标签==0x49492A00);
//获取偏移量并检查是否合理。
int count=pack(jpeg, offset + 4, 4, LittleEndian) + 2;
if (计数10 || 计数长度) {
Log.e(TAG, "无效偏移");
返回0;
}
偏移量+=计数;
长度-=计数;
//获取计数并遍历所有元素。
count=pack(jpeg, 偏移量- 2, 2, LittleEndian);
while (计数-- 0 长度=12) {
//获取标签并检查它是否是方向。
标签=包(jpeg,偏移量,2,littleEndian);
如果(标签==0x0112){
//我们并不真正关心类型和计数,不是吗?
int 方向=pack(jpeg, offset + 8, 2, LittleEndian);
开关(方向){
案例1:
返回0;
案例3:
返回180;
案例6:
返回90;
案例8:
返回270;
}
Log.i(TAG, "不支持的方向");
返回0;
}
偏移+=12;
长度-=12;
}
}
Log.i(TAG, "未找到方向");
返回0;
}
private static int pack(byte[] 字节, int 偏移量, int 长度,
布尔littleEndian) {
整数步=1;
如果(小端){
偏移量+=长度-1;
步骤=-1;
}
整数值=0;
while (长度-- 0) {
值=(值8)| (字节[偏移]0xFF);
偏移+=步长;
}
返回值;
}获取照片的方向信息后,可以通过Bitmap操作得到正确方向的图像:
公共静态位图rotateBitmap(位图bm,浮动度){
矩阵矩阵=new Matrix();
矩阵.重置();
矩阵.setRotate(度);
位图temp=Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), 矩阵, true);
返回温度;
}
关于 EXIF 信息的格式
JPEG文件中的EXIF信息一般包括图像、相机和缩略图信息。 EXIF文件格式与JPEG文件格式基本相同,因此添加EXIF信息并不会影响JPEG文件的查看。
JPEG文件中存在一些0xFF**形式的数据,这些数据称为“标记”,代表JPEG信息数据段。例如,0xFFD8代表SOI(图像开始),0xFFD9代表EOI(图像结束)。这两个标志是特殊情况,因为它们后面没有数据。一般标志格式如下:
0xFF+Marker Number(1 byte)+Data size(2 bytes)+Data(n bytes)标记0xFFE0~0xFFEF 称为“应用标记”。它们对于解码JPEG文件不是必需的,可以用来存储配置信息等。EXIF也使用这个标志段来插入信息,具体是APP1(0xFFE1) Marker。所有的EXIF信息都存储在这个数据段中。我们可以根据具体的数据结构解析出所需的信息,比如方向。详细数据结构请参见参考文献1中的文章。
参考:
https://www.media.mit.edu/pia/Research/deepview/exif.html
好了,关于如何通过JPEG文件EXIF信息调整照片方向和的问题到这里结束啦,希望可以解决您的问题哈!
【如何通过JPEG文件EXIF信息调整照片方向】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
哇,这个方法太厉害了!之前不知道JPEG图片里还能藏着这么多的信息。
有19位网友表示赞同!
终于不用一个个手动旋转照片啦!太方便了。
有15位网友表示赞同!
原来照片的方向可以通过EXIF信息来调整的吗?我真知らなかった~
有18位网友表示赞同!
这个工具一定要试试,说不定能帮我在修图上省不少时间。
有13位网友表示赞同!
对摄影爱好者来说真是个好方法!
有7位网友表示赞同!
以后不用再担心照片拍反了的问题啦!
有10位网友表示赞同!
之前每次拍视频的时候都拍歪了,这一下可以解决了。
有9位网友表示赞同!
分享这种知识真的太棒了,我可以更方便地处理图片啦。
有9位网友表示赞同!
真是个高效的学习方法!以前没听说过这个EXIF信息的东西,现在我明白了。
有10位网友表示赞同!
不知道用什么工具来实现呢?有推荐吗?
有19位网友表示赞同!
这样的软件有没有免费的?
有7位网友表示赞同!
感觉这个方法应该很有用,我要试一试!
有12位网友表示赞同!
希望这种科技能够更普及,让我们的生活更便捷。
有18位网友表示赞同!
学习了这个知识点,我以后可以更高效地整理图片啦。
有9位网友表示赞同!
对那些经常拍照片的人来说,这个方法真的很有意义。
有11位网友表示赞同!
原来照片中隐藏着这么多信息!我很想了解更多关于EXIF的信息。
有19位网友表示赞同!
希望这种技术能够帮助我们更轻松地处理和编辑图片。
有13位网友表示赞同!
我有很多旧照片需要调整方向,这下可以省去很多麻烦了!
有15位网友表示赞同!