una son quitar que online metadatos los las imagen fotos fotografias fotografia foca extraer con c# gps latitude-longitude exif

c# - son - quitar metadatos video online



Obtención de datos GPS del EXIF de una imagen en C# (8)

Estoy desarrollando un sistema que permite cargar una imagen a un servidor utilizando ASP.NET C #. Estoy procesando la imagen y todo está funcionando muy bien. He logrado encontrar un método que lee los datos EXIF ​​de Fecha de Creación y los estoy analizando como DateTime. Eso también funciona muy bien.

Ahora estoy tratando de leer datos de GPS desde el EXIF. Tengo ganas de capturar las cifras de latitud y longitud.

Estoy usando esta lista como referencia a los datos EXIF ​​(usando los números de los artículos de propiedad) http://www.exiv2.org/tags.html

Aquí está el método para capturar la fecha creada (que funciona).

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; }

A continuación es mi intento de hacer lo mismo para 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; }

El valor que está saliendo y en sdate es "5 / 0 / 0 / 0 / 0 / 0 / 0l / t / 0 / 0d / 0 / 0 / 0 / 0 / 0 / 0 / 0 / 0 / 0 / 0 /"

Y eso viene de una imagen que fue tomada por un iPhone 4 que lleva los datos del GPS EXIF.

Sé que hay clases por ahí que hacen esto, pero preferiría escribir las mías, aunque estoy abierto a sugerencias :-)

Gracias por adelantado.


¿Ha probado las etiquetas 0x0013-16 por http://msdn.microsoft.com/en-us/library/ms534416(v=vs.85).aspx que también se parece a la latitud del GPS?

No estoy seguro de qué es lo que distingue a estos de las etiquetas numeradas más bajas, pero vale la pena intentarlo.

Aquí están sus descripciones:

0x0013 - Cadena de caracteres terminada en nulo que especifica si la latitud del punto de destino es la latitud norte o sur. N especifica la latitud norte y S especifica la latitud sur.

0x0014 - Latitud del punto de destino. La latitud se expresa como tres valores racionales que dan los grados, minutos y segundos respectivamente. Cuando se expresan grados, minutos y segundos, el formato es dd / 1, mm / 1, ss / 1. Cuando se usan grados y minutos y, por ejemplo, se dan fracciones de minutos hasta dos decimales, el formato es dd / 1, mmmm / 100, 0/1.

0x0015 - Cadena de caracteres terminada en nulo que especifica si la longitud del punto de destino es la longitud este u oeste. E especifica la longitud este, y W especifica la longitud oeste.

0x0016 - Longitud del punto de destino. La longitud se expresa como tres valores racionales que dan los grados, minutos y segundos, respectivamente. Cuando se expresan grados, minutos y segundos, el formato es ddd / 1, mm / 1, ss / 1. Cuando se usan grados y minutos y, por ejemplo, las fracciones de minutos tienen hasta dos decimales, el formato es ddd / 1, mmmm / 100, 0/1.


Aquí está el código trabajando, encontré algunos errores trabajando con float. Espero que esto ayude a alguien.

private static double ExifGpsToDouble (PropertyItem propItemRef, PropertyItem propItem) { double degreesNumerator = BitConverter.ToUInt32(propItem.Value, 0); double degreesDenominator = BitConverter.ToUInt32(propItem.Value, 4); double degrees = degreesNumerator / (double)degreesDenominator; double minutesNumerator = BitConverter.ToUInt32(propItem.Value, 8); double minutesDenominator = BitConverter.ToUInt32(propItem.Value, 12); double minutes = minutesNumerator / (double)minutesDenominator; double secondsNumerator = BitConverter.ToUInt32(propItem.Value, 16); double secondsDenominator = BitConverter.ToUInt32(propItem.Value, 20); double seconds = secondsNumerator / (double)secondsDenominator; double coorditate = degrees + (minutes / 60d) + (seconds / 3600d); string gpsRef = System.Text.Encoding.ASCII.GetString(new byte[1] { propItemRef.Value[0] }); //N, S, E, or W if (gpsRef == "S" || gpsRef == "W") coorditate = coorditate*-1; return coorditate; }


De acuerdo con el enlace publicado anteriormente por tomfanning, el elemento de propiedad 0x0002 es la latitud expresada como PropertyTagTypeRational . El tipo racional se define como ...

Especifica que el miembro de datos de valor es una matriz de pares de enteros largos sin signo . Cada par representa una fracción; el primer entero es el numerador y el segundo entero es el denominador.

Está intentando analizarlo como una cadena cuando en realidad es solo una serie de bytes. De acuerdo con lo anterior, debe haber 3 pares de enteros sin signo de 32 bits empaquetados en esa matriz de bytes, que puede recuperar utilizando lo siguiente:

uint degreesNumerator = BitConverter.ToUInt32(propItem.Value, 0); uint degreesDenominator = BitConverter.ToUInt32(propItem.Value, 4); uint minutesNumerator = BitConverter.ToUInt32(propItem.Value, 8); uint minutesDenominator = BitConverter.ToUInt32(propItem.Value, 12); uint secondsNumerator = BitConverter.ToUInt32(propItem.Value, 16); uint secondsDenominator = BitConverter.ToUInt32(propItem.Value, 20);

Lo que hagas con estos valores después de obtenerlos es para que trabajes :) Esto es lo que dicen los documentos:

La latitud se expresa como tres valores racionales que dan los grados, minutos y segundos respectivamente. Cuando se expresan grados, minutos y segundos, el formato es dd / 1, mm / 1, ss / 1. Cuando se usan grados y minutos y, por ejemplo, se dan fracciones de minutos hasta dos decimales, el formato es dd / 1, mmmm / 100, 0/1.


Gracias, el código está bien, pero al menos un error,

uint minutes = minutesNumerator / minutesDenominator;

no se da un resultado exacto, cuando los minutosDenominador no es igual a 1, en mi ejemplo exif = 16,


Me encontré con esto buscando una manera de obtener los datos GPS EXIF ​​como un conjunto de flotadores. He adaptado el código de Jon Grant de la siguiente manera ...

public static float? GetLatitude(Image targetImg) { try { //Property Item 0x0001 - PropertyTagGpsLatitudeRef PropertyItem propItemRef = targetImg.GetPropertyItem(1); //Property Item 0x0002 - PropertyTagGpsLatitude PropertyItem propItemLat = targetImg.GetPropertyItem(2); return ExifGpsToFloat(propItemRef, propItemLat); } catch (ArgumentException) { return null; } } public static float? GetLongitude(Image targetImg) { try { ///Property Item 0x0003 - PropertyTagGpsLongitudeRef PropertyItem propItemRef = targetImg.GetPropertyItem(3); //Property Item 0x0004 - PropertyTagGpsLongitude PropertyItem propItemLong = targetImg.GetPropertyItem(4); return ExifGpsToFloat(propItemRef, propItemLong); } catch (ArgumentException) { return null; } } private static float ExifGpsToFloat(PropertyItem propItemRef, PropertyItem propItem) { uint degreesNumerator = BitConverter.ToUInt32(propItem.Value, 0); uint degreesDenominator = BitConverter.ToUInt32(propItem.Value, 4); float degrees = degreesNumerator / (float)degreesDenominator; uint minutesNumerator = BitConverter.ToUInt32(propItem.Value, 8); uint minutesDenominator = BitConverter.ToUInt32(propItem.Value, 12); float minutes = minutesNumerator / (float)minutesDenominator; uint secondsNumerator = BitConverter.ToUInt32(propItem.Value, 16); uint secondsDenominator = BitConverter.ToUInt32(propItem.Value, 20); float seconds = secondsNumerator / (float)secondsDenominator; float coorditate = degrees + (minutes / 60f) + (seconds / 3600f); string gpsRef = System.Text.Encoding.ASCII.GetString(new byte[1] { propItemRef.Value[0] } ); //N, S, E, or W if (gpsRef == "S" || gpsRef == "W") coorditate = 0 - coorditate; return coorditate; }


Primero debe leer los bytes que indican si los datos EXIF ​​están en formato big endian o little endian para que no arruine todo.

Luego, debe escanear cada IFD de la imagen buscando la etiqueta GPSInfo (0x25 0x88), si NO encuentra esta etiqueta dentro de cualquier IFD significa que la imagen no tiene información de GPS. Si encuentra esta etiqueta, lea los 4 bytes de sus valores, lo que le da un desplazamiento a otro IFD, el GPS IFD, dentro de este IFD solo necesita recuperar los valores de las siguientes etiquetas:

0x00 0x02 - Para la latitud

0x00 0x04 - Para la longitud

0x00 0x06 - Para la altitud.

Cada uno de estos valores son racionales sin signo.

Aquí puede encontrar cómo hacer casi todo: http://www.media.mit.edu/pia/Research/deepview/exif.html


Sé que este es un post antiguo, pero quería dar una respuesta que me haya ayudado.

Utilicé ExifLibrary ubicada aquí para escribir y leer metadatos de archivos de imágenes: https://code.google.com/p/exiflibrary/wiki/ExifLibrary

Esto era simple y fácil de usar. Espero que esto ayude a alguien más.


Una forma simple (y rápida) es usar mi biblioteca de código abierto MetadataExtractor :

var gps = ImageMetadataReader.ReadMetadata(path) .OfType<GpsDirectory>() .FirstOrDefault(); var location = gps.GetGeoLocation(); Console.WriteLine("Image at {0},{1}", location.Latitude, location.Longitude);

La biblioteca está escrita en C # puro y admite muchos formatos de imagen y decodifica datos específicos de muchos modelos de cámaras.

Está disponible a través de NuGet o GitHub .