在 C# 中从图像的 EXIF 获取 GPS 数据
我正在开发一个系统,允许使用 ASP.NET C# 将图像上传到服务器。我正在处理图像,一切正常。我设法找到一种方法来读取创建日期 EXIF 数据并将其解析为日期时间。这也很好用。
我现在正在尝试从 EXIF 读取 GPS 数据。我想捕获纬度和经度数字。
我使用此列表作为 EXIF 数据的参考(使用属性项的数字)http://www.exiv2.org /tags.html
这是捕获创建日期的方法(有效)。
public DateTime GetDateTaken(Image targetImg)
{
DateTime dtaken;
try
{
//Property Item 306 corresponds to the Date Taken
PropertyItem propItem = targetImg.GetPropertyItem(0x0132);
//Convert date taken metadata to a DateTime object
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
string secondhalf = sdate.Substring(sdate.IndexOf(" "), (sdate.Length - sdate.IndexOf(" ")));
string firsthalf = sdate.Substring(0, 10);
firsthalf = firsthalf.Replace(":", "-");
sdate = firsthalf + secondhalf;
dtaken = DateTime.Parse(sdate);
}
catch
{
dtaken = DateTime.Parse("1956-01-01 00:00:00.000");
}
return dtaken;
}
下面是我对 GPS 做同样的尝试。
public float GetLatitude(Image targetImg)
{
float dtaken;
try
{
//Property Item 0x0002 corresponds to the Date Taken
PropertyItem propItem = targetImg.GetPropertyItem(2);
//Convert date taken metadata to a DateTime object
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
dtaken = float.Parse(sdate);
}
catch
{
dtaken = 0;
}
return dtaken;
}
输出并进入 sdate 的值是“5\0\0\0\0\0\0l\t\0\0d\0\0\0\0\ 0\0\0\0\0\0"
这来自 iPhone 4 拍摄的图像,该图像确实携带 GPS EXIF 数据。
我知道有一些课程可以做到这一点,但我更愿意编写自己的课程 - 不过我愿意接受建议:-)
提前致谢。
I am developing a system that allows for an image to be uploaded to a server using ASP.NET C#. I am processing the image and all is working great. I have managed to find a method that reads the Date Created EXIF data and am parsing it as a DateTime. That works great too.
I am now trying to read GPS data from the EXIF. I am wanting to capture the Latitude and Longitude figures.
I am using this list as a reference to the EXIF data (using the numbers for the property items) http://www.exiv2.org/tags.html
Here is the method to capture the date created (which works).
public DateTime GetDateTaken(Image targetImg)
{
DateTime dtaken;
try
{
//Property Item 306 corresponds to the Date Taken
PropertyItem propItem = targetImg.GetPropertyItem(0x0132);
//Convert date taken metadata to a DateTime object
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
string secondhalf = sdate.Substring(sdate.IndexOf(" "), (sdate.Length - sdate.IndexOf(" ")));
string firsthalf = sdate.Substring(0, 10);
firsthalf = firsthalf.Replace(":", "-");
sdate = firsthalf + secondhalf;
dtaken = DateTime.Parse(sdate);
}
catch
{
dtaken = DateTime.Parse("1956-01-01 00:00:00.000");
}
return dtaken;
}
Below is my attempt at doing the same for GPS..
public float GetLatitude(Image targetImg)
{
float dtaken;
try
{
//Property Item 0x0002 corresponds to the Date Taken
PropertyItem propItem = targetImg.GetPropertyItem(2);
//Convert date taken metadata to a DateTime object
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
dtaken = float.Parse(sdate);
}
catch
{
dtaken = 0;
}
return dtaken;
}
The value that's coming out and into sdate is "5\0\0\0\0\0\0l\t\0\0d\0\0\0\0\0\0\0\0\0\0"
And that is coming from an image that was taken by an iPhone 4 which does carry the GPS EXIF data.
I know there are classes out there that do this but would prefer to write my own - I am open to suggestions though :-)
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我知道这是一篇旧帖子,但我想提供一个对我有帮助的答案。
我使用位于此处的 ExifLibrary 从图像文件写入和读取元数据:
https://code.google.com/p/exiflibrary/wiki/ExifLibrary
这简单易用。我希望这对其他人有帮助。
I know this is an old post, but I wanted to provide an answer that helped me.
I used ExifLibrary located on here to both write and read metadata from image files:
https://code.google.com/p/exiflibrary/wiki/ExifLibrary
This was simple and easy to use. I hope this helps someone else.
您首先必须读取指示 EXIF 数据是大端还是小端格式的字节,这样您就不会弄乱所有内容。
然后,您需要扫描图像的每个 IFD,查找 GPSInfo 标签(0x25 0x88),如果在任何 IFD 中都没有找到此标签,则意味着该图像没有任何 GPS 信息。如果您找到此标签,请读取其值的 4 个字节,这将为您提供到另一个 IFD(GPS IFD)的偏移量,在此 IFD 内,您只需要检索以下标签的值:
0x00 0x02 - 对于纬度
0x00 0x04
- 对于经度0x00 0x06
- 对于海拔高度这些值中的每一个都是无符号有理数。
在这里您可以找到几乎所有操作的方法:http://www.media .mit.edu/pia/Research/deepview/exif.html
You first have to read the bytes that indicate whether the EXIF data is in big endian or little endian format so you don't mess up everything.
Then you need to scan each IFD of the image looking for the GPSInfo tag (0x25 0x88), if you do NOT find this tag inside any IFD means that the image doesn't have any GPS info. If you do find this tag, read the 4 bytes of it's values, which gives you an offset to another IFD, the GPS IFD, inside this IFD you only need to retrieve the values of the following tags:
0x00 0x02
- For the latitude0x00 0x04
- For the longitude0x00 0x06
- For the altitudeEach of these values are unsigned rationals.
Here you can find how to do almost everything: http://www.media.mit.edu/pia/Research/deepview/exif.html
如果您使用 ImageMagick 库,这非常简单。
假设您从图像流开始:
如下所示:
If you're using the ImageMagick library, this is very straightforward.
Assuming you start off with an image stream:
Like so:
您是否尝试过 http://msdn.microsoft.com/en-us/library/ms534416(v=vs.85).aspx" rel="nofollow noreferrer">http:// /msdn.microsoft.com/en-us/library/ms534416(v=vs.85).aspx 看起来也像 GPS 纬度?
不确定这些标签与编号较低的标签有什么区别,但值得一试。
以下是他们的描述:
Have you tried tags 0x0013-16 per http://msdn.microsoft.com/en-us/library/ms534416(v=vs.85).aspx which also looks like GPS latitude?
Not sure what distinguishes these from the lower numbered tags, but worth a try.
Here are their descriptions:
谢谢,代码很好,但至少有一个失败,
uint 分钟=分钟分子/分钟分母;
当分钟分母不等于 1 时,不能给出准确的结果,例如在我的 exif=16 中,
Thanks, the code is fine but at least one failor,
uint minutes = minutesNumerator / minutesDenominator;
give not an exact result, when the minutesDenominator is not equal 1, in example in my exif=16,
一种简单(且快速!)的方法是使用我的开源 MetadataExtractor 库:
该库是用纯 C# 编写的,支持多种图像格式并解码特定于多种相机型号的数据。
它可以通过 NuGet 或 GitHub。
A simple (and fast!) way is to use my open source MetadataExtractor library:
The library is written in pure C# and supports many image formats and decodes data specific to many camera models.
It's available via NuGet or GitHub.
根据 tomfanning 发布的上面的链接 ,属性项 0x0002 是表示为
PropertyTagTypeRational
的纬度。有理类型定义为.. 。当它实际上只是一系列字节时,您试图将其解析为字符串。根据上面的内容,应该有 3 对 32 位无符号整数打包到该字节数组中,您可以使用以下方法检索它们:
获得这些值后,您可以计算出它们的用途:)这是文档所说的:
According to the link posted above by tomfanning, property item 0x0002 is the latitude expressed as a
PropertyTagTypeRational
. The rational type is defined as...You are trying to parse it as a string when it's actually just a series of bytes. According to the above, there should be 3 pairs of 32-bit unsigned integers packed into that byte array, which you can retrieve using the following:
What you do with these values after you've got them is for you to work out :) Here's what the docs say:
我遇到了这个问题,寻找一种将 EXIF GPS 数据作为一组浮点数获取的方法。我改编了乔恩·格兰特的代码,如下......
I ran across this looking for a way to get the EXIF GPS data as a set of floats. I've adapted the code from Jon Grant as follows...
这是正在运行的代码,我发现使用浮动时出现一些错误。
我希望这对某人有帮助。
Here is the code working, I found some errors working with float.
I hope this help somebody.