如何使用Delphi中的CCR.EXIF从JPG EXIF中读取GPS坐标?

3
使用GPSLatitude和GPSLongitude属性的Assign方法设置GPS坐标非常容易,但是读取坐标让我困惑了。我尝试访问TGPSLongitude类,但是这些属性或方法都没有给我提供实际/浮点数甚至是坐标的DMS。
示例图片:http://www.cde.co.za/share/IMG_5889.JPG 我的当前代码无法编译:
imgJpg: TJpegImageEx;
GPS_D: Real;

try
  imgJpg.LoadFromFile(FolderName+'\'+SR.Name);
  GPS_D:= imgJpg.ExifData.GPSLatitude.Degrees;
except
  GPS_D:= 0;
end;

当我尝试将GPS_D赋值时,编译器会停止并显示错误信息“[DCC Error] Main.pas(205): E2010 Incompatible types: 'Real' and 'TTiffLongWordFraction'”,这显然是因为无法将Degrees属性分配给Real类型。问题在于如何从TGPSLongitude中提取度数或小数值?


我的当前代码无法编译。有什么编译错误,出现在哪一行?另外,TdmSH是什么,以及它的DMStoDec方法是什么功能? - Tom Brunberg
@TomBrunberg DMStoDec接受3个实数值并将其转换为GPS十进制。但是我已经简化了源示例。编译器在我尝试使用错误"[DCC Error] Main.pas(205):E2010不兼容类型:'Real'和'TTiffLongWordFraction'"分配GPS_D时停止。这显然是因为我无法将度属性分配给实数。问题是如何从TGPSLongitude中提取度或小数值?感谢您的时间。 - Hein du Plessis
3个回答

2

来自 CCRExif 1.5.1 内文档 -

GPS

Exif 标准允许设置 GPS(即定位)数据,该数据存储在其自己的部分/子IFD中。使用 TExifData,您既可以读取也可以写入这些数据,标准的一组 GPS 标签会作为该类的属性暴露出来。需要注意的重要事项是,GPS 坐标可以用两种不同的方式表示,分别是单个小数值或以度、分和秒表示。Exif 使用后一种形式,因此,如果您希望将 GPS 坐标分配给图像,并且您拥有所需的以小数形式表示的值,则需要首先转换为另一种形式。(对于“单次”转换,您可以使用以下网站: http://www.fcc.gov/mb/audio/bickel/DDDMMSS-decimal.html。)但是,一旦您获得了所需格式的坐标,将它们分配给图像的过程如下:

with TExifData.Create do 
try
  LoadFromGraphic(ImageFile); 
  GPSLatitude.Assign(51, 25, 32.1, ltNorth);
  GPSLongitude.Assign(0, 12, 29.2, lnEast); 
  SaveToGraphic(ImageFile);
finally 
 Free; 
end;

查看源代码可以了解:
TGPSLatitude = class(TGPSCoordinate)

“TGPSCoordinate”类的声明在公共部分中。
property Degrees: TExifFraction index 0 read GetValue;
property Minutes: TExifFraction index 1 read GetValue;
property Seconds: TExifFraction index 2 read GetValue;
property Direction: AnsiChar read GetDirectionChar write SetDirectionChar;

此外,压缩文件中还有几个演示应用程序。
注:在阅读评论后,我再次查看了演示,在ExifList演示中,您可以在ExifListFrame.pas中找到以下代码:
 procedure AddValue(const Name: string; Coord: TGPSCoordinate); overload;
  var
    DirectionStr: string;
  {$IFDEF BUGGYCOMPILER}
    Degrees, Minutes, Seconds: TExifFraction; //work around D2006 compiler bug with intermediate vars
  {$ENDIF}
  begin
    if Coord.MissingOrInvalid then Exit;
    case Coord.Direction of
      'N': DirectionStr := 'north';
      'S': DirectionStr := 'south';
      'W': DirectionStr := 'west';
      'E': DirectionStr := 'east';
    else DirectionStr := '';
    end;
  {$IFDEF BUGGYCOMPILER}
    Degrees := Coord.Degrees;
    Minutes := Coord.Minutes;
    Seconds := Coord.Seconds;
    AddValue(Name, '%g°, %g minutes and %g seconds %s', [Degrees.Quotient,
      Minutes.Quotient, Seconds.Quotient, DirectionStr]);
  {$ELSE}
    AddValue(Name, '%g°, %g minutes and %g seconds %s', [Coord.Degrees.Quotient,
      Coord.Minutes.Quotient, Coord.Seconds.Quotient, DirectionStr]);
  {$ENDIF}
  end;

我手头没有 Delphi 安装包,所以无法为您提供该类的完整使用示例。 - RBA
谢谢,我已经仔细阅读了文档,您的代码片段展示了如何给TGPSCoordinate实例赋值,即写入它。我有一张已经地理标记的JPG图片,我需要从中获取坐标。度、分、秒属性是TExifFraction类型的,这是一个带有组件的压缩记录,不清楚如何获取实际值。请参见我上面添加的源代码尝试。 - Hein du Plessis

2

深入查看源代码后,似乎可以使用“商数”属性。开发者选择存储分子、分母和商数组件,而不是存储十进制浮点数。

我认为这不是它的预期用途,但它确实有效!感谢大家的时间。

因此,要使用CCR.EXIF从JPG文件中读取GPS坐标,需要执行以下操作:

var
    imgJpg: TJpegImageEx;
    d,m,s,lat: real;

imgJpg.LoadFromFile(FolderName+'\'+SR.Name); {Load the particular JPG File }
d:= imgJpg.ExifData.GPSLatitude.Degrees.Quotient; {Degrees}
m:= imgJpg.ExifData.GPSLatitude.Minutes.Quotient; {Minutes}
s:= imgJpg.ExifData.GPSLatitude.Seconds.Quotient; {Seconds}

{Now determine the sign}
if imgJpg.ExifData.GPSLatitude.Direction=ltNorth then
  ref:= 1
else
  ref:= -1;

{Convert to decimal}
lat:= ref*(d+(m/60)+(s/60/60));

现在lat包含了纬度信息,当然long也可以这样做。


有人能告诉我如何在Lazarus中实现相同的功能吗? - user12346352
Hein,你的解决方案帮了我很大的忙。我想补充一下,CCRExif在许多情况下不可靠。在我的小米Mi 8的JPG中,它为GPSLatitudeRef、GPSLatitude.Direction、GPSLatitude.MissingOrInvalid等提供了虚假(空)值。在这种情况下,您可以使用GPSLatitude.ToString,其中包含方向('N'或'S')在最后一个字符中。此外,当不存在GPS标记时,它将是“0,0,0,N”,显然比MissingOrInvalid更可靠。 - stackmik
更正:实际上,当没有GPS标签时,它将是“0,0,0N”。 - stackmik

1

提取GPS信息的简便方法是将其作为字符串

var myLat, myLong : string;
...
myLat := myJpeg.ExifData.GPSLatitude.AsString ; 
myLong := myJpeg.ExifData.GPSLongitude.AsString ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接