Writing latitude and longitude using policies
- I am trying to write the above values, using the "System.GPS.Latitude" and "System.GPS.Longitude" policies.
First, I tried using the "Numerator"/"Denominator" option to write URational data, but since I have a URational[3] in here, it doesn't seem reasonable.
I couldn't find a way to write a coordinate using the policies. Only using the direct xmp or exif query strings.
with xmp, I should use a string, with exif, I use a ulong[3] array.
this.metadata.SetQuery("/xmp/exif:GPSLatitude", "3223");
or
this.metadata.SetQuery("/app1/ifd/gps/{ushort=2}", new ulong[]{1, 2, 3});
seem to work, but I am looking for something like
this.metadata.SetQuery("System.GPS.Latitude", value)
where value is ulong[3] or string (or whatever else it can be...), and it would set both the xmp and the exif to the proper values.
Am I hoping for too much?
All Replies
First of all, are you using Win7 Beta or Vista? On Win7 Beta, these keys should work just fine, but they are currently are not enabled on Vista (so you have to write directly to the gps ifd). For Win7 Beta, you should be able to use a string value for the numerator and denominator via a proxy key, i.e. this.metadata.SetQuery("System.GPS.Latitude.Proxy", "1/2").
- I am trying this on Vista.
The main problem with Latitude and Longitude is that it contains three URational values, not just one. At least in the exif container. It can contain just one rational for degrees (with minutes and seconds as fraction of degrees), I guess.
Yesterday I managed to execute the following code with some success:
this.metadata.SetQuery("System.GPS.Latitude", new ULong[]{ 30, 40, 20 });
and this did put the 30 40 20 values in the exif ULong array, but when I later try to read with
this.metadata.GetQuery("/xmp/exif:GPSLatitude")
or
this.metadata.GetQuery("System.GPS.Latitude.Proxy")
all I get is
"-2147483648,0.#INFN"
which is quite odd
I tried putting different values in the ULong array. they all ran alright (no exception, at least), and reading with
this.metadata.GetQuery("/app1/ifd/gps/{ushort=2}")
just gives me back exactly what I put in. the xmp and proxy strings got me more strange results, like
"-2147483648,-2147483648.#INDN"
Is it all just not supported by Vista? Should I try sticking to reading and writing from exif, for lat and long?
- You're almost there. Each rational type is actually composed of two 32-bit numbers -- the upper 32-bits is a numerator, and the bottom 32-bits is a denominator. The rational is interpreted by dividing these two numbers. So if you with write "30", you need to write "30/1", which means you create a 64-bit ULong by taking 30 and shifting it up by 32 bits and then adding one.
- Did you solve your problem? I've just finishing up a blog on this. The code you need for reading is:
// Grab GpsAltitude as a ulong
ulong rational = (ulong)bitmapMetadata.GetQuery("/app1/ifd/Gps/subifd:{uint=6}");// Now shift & mask out the upper and lower parts to get the numerator and the denominator
uint numerator = (uint)(rational & 0xFFFFFFFFL);
uint denominator = (uint)((rational & 0xFFFFFFFF00000000L) >> 32);// And finally turn it into a double
I'll post the blog here in the next week or so:
double altitude = Math.Round(Convert.ToDouble(numerator) / Convert.ToDouble(denominator), 3);
http://www.tassography.com/blog.aspx?tag=Windows+Imaging+Component


