2014-09-01 5 views
2

WIC (Windows Imaging Component)를 내부적으로 사용하는 WPF 클래스 BitmapMetadata을 사용하여 누구든지 GPS 데이터를 성공적으로 읽었습니까?WIC/WPF : System.GPS.Longitude 및 System.GPS.Latitude는 항상 BitmapMetadata를 통해 NULL을 반환합니다.

Windows (8.1) 탐색기와 XnView와 같은 외부 도구가 GPS 좌표를 표시하는 이미지가 있습니다.

내가 클래스 BitmapFrame의 재산 Metadata를 통해 사용할 수있는 클래스 BitmapMetadata 사용하여 이러한 데이터를 추출하려고 : altitude

var md = (BitmapMetdata)extractedFrame.Metadata; 
var altitude = md.GetQuery("System.GPS.Altitude"); 
var altitudeProxy = md.GetQuery("System.GPS.Altitude.Proxy"); 
var altitudeRef = md.GetQuery("System.GPS.AltitudeRef"); 
var longitude = md.GetQuery("System.GPS.Longitude"); 
var longitudeProxy = md.GetQuery("System.GPS.Longitude.Proxy"); 
var longitudeRef = md.GetQuery("System.GPS.LongitudeRef"); 
var latitude = md.GetQuery("System.GPS.Latitude"); 
var latitudeProxy = md.GetQuery("System.GPS.Latitude.Proxy"); 
var latitudeRef = md.GetQuery("System.GPS.LatitudeRef"); 

결과 (System.Double), altitudeRef (System.Byte), longitudeRef을 (시스템 .String) 및 latitudeRef (System.String)은 모두 정상이며 적절한 데이터 ("510.70", "0", "N", "E")를 검색합니다.

longitudelatitude은 System.Double 의 배열이어야하지만 항상 NULL입니다.

".Proxy"접미사를 사용하는 결과는 이상한 문자열 데이터를 반환합니다. 이상한 문자열 데이터는 구문 분석 방법과 culture가 불변하거나 그렇지 않은 경우에 반환됩니다. MSDN 문서는 문자열에 대해서는 전혀 다른 것을 알려줍니다. 적어도 경도와 위도에 대한 "유효한"데이터가있을 것입니다.

누락 된 버그 또는 내 잘못입니까?

답변

6

여기 코드를 사용하여 위도와 경도에 액세스했습니다. http://khason.net/blog/how-to-read-gps-metadata-from-image/ N, S, E, W +/- 부분은 처리하지 않습니다. 따라서 위의 LongitudeRef 및 LatitudeRef를 사용하여 좌표의 부호를 변경할지 여부를 결정해야합니다. 기본적으로 :

JpegBitmapDecoder decoder = new JpegBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.None); 
BitmapMetadata meta = (BitmapMetadata)decoder.Frames[0].Metadata; 
ulong[] latitude = meta.GetQuery("/app1/ifd/gps/subifd:{ulong=2}") as ulong[]; 
ulong[] longitude = meta.GetQuery("/app1/ifd/gps/subifd:{ulong=4}") as ulong[]; 
double lat   = ConvertCoordinate(latitude); 
double longit  = ConvertCoordinate(longitude); 

static double ConvertCoordinate(ulong[] coordinates) 
{ 
    int lDash = (int)(coordinates[0] - ((ulong)0x100000000)); 
    int lF  = (int)(coordinates[1] - ((ulong)0x100000000)); 
    double lR = ((double)(coordinates[2] - ((ulong)0x6400000000)))/100; 
    double tRes = (lDash + (((double)lF)/60)) + (lR/3600); 
    return (Math.Floor((double)(tRes * 1000000))/1000000); 
} 

편집 위는 오래된 EXIF ​​형식 일했다. 최신 형식은 좌표에 숫자가 더 많아서 잘못 변환되었습니다. 나는 변환이 좌표를 업데이트했다 :

static double ConvertCoordinate(ulong[] coordinates) 
{ 
    if (coordinates == null) 
     return 0; 

    double degrees = ConvertToUnsignedRational(coordinates[ 0 ]); 
    double minutes = ConvertToUnsignedRational(coordinates[ 1 ]); 
    double seconds = ConvertToUnsignedRational(coordinates[ 2 ]); 
    return degrees + (minutes/60.0) + (seconds/3600); 

} 
static double ConvertToUnsignedRational(ulong value) 
{ 
    return (value & 0xFFFFFFFFL)/(double) ((value & 0xFFFFFFFF00000000L) >> 32); 
} 
+0

@StefanFalk 대답이 아니라 질문입니다. 응답이 합리적인 값을 반환하기 때문에 당신이 downvoter 있다면 나는 이것을 되돌릴 것을 제안합니다. – springy76

+0

@ springy76 죄송합니다! 나는 그 실수를 리뷰하면서 생각하고 이것이 실제적인 질문이라고 생각했다. 나는 내 downvote를 취소 할 것이다. 그러나 SO가 나의 투표 결정을 그때까지 잠그기 때문에 그녀가 나의 편집을 받아 들일 때까지 나는 기다려야한다. – displayname

+0

BTW : 'ulong []': "/ xmp/exif : GPSLatitude"와 "/ xmp/exif : GPSLongitude"를 반환 할 수있는'meta.GetQuery() – springy76

1

그것은 대답 아마도 너무 늦게, 그러나 .Proxy 값의 형식은 다음과 같습니다

MetaDataValue "16,0.4965000000000145E" object {string} 

은 16 개도, 0.49 분을 의미한다. 따라서 분 및 초로 변환해야합니다.