internal static TreeDirectory GetHierarchicalDirectory(XmpDirectory directories) { TreeDirectory root = new TreeDirectory(); TreeDirectory[] treeNodes = directories.XmpMeta.Properties.Where(x => x.Path != null).Select(x => new TreeDirectory(x)).ToArray(); var possibleChildrean = treeNodes.Select(x => new { Element = x, PossibleChildrean = treeNodes.Where(y => y.Element.Path != x.Element.Path && y.Element.Path.StartsWith(x.Element.Path)).ToArray() }).ToArray(); var childOfRoot = possibleChildrean.Where(x => !possibleChildrean.Any(y => y.PossibleChildrean.Contains(x.Element))).ToArray(); root.Childrean.AddRange(childOfRoot.Select(x => x.Element)); foreach (var child in childOfRoot) { child.Element.Parent = root; } foreach (var node in possibleChildrean) { TreeDirectory[] childOfNode = node.PossibleChildrean.Where(x => !possibleChildrean.Any(y => node.PossibleChildrean.Contains(y.Element) && y.PossibleChildrean.Contains(x))).ToArray(); node.Element.Childrean.AddRange(childOfNode); foreach (TreeDirectory child in childOfNode) { child.Parent = node.Element; } } return(root); }
public static Metadata ParseXmpDirectory(XmpDirectory directory, Metadata metadata) { var xmpProperties = directory.GetXmpProperties(); // aux https://www.exiv2.org/tags-xmp-aux.html if (xmpProperties.TryGetValue("aux:Lens", out var lensType)) { metadata.Camera.LensModel = lensType; } if (xmpProperties.TryGetValue("aux:SerialNumber", out var lensSerialNumber)) { metadata.Camera.LensSerialNumber = lensSerialNumber; } // exifEX https://www.exiv2.org/tags-xmp-exifEX.html if (xmpProperties.TryGetValue("exifEX:LensMake", out var lensMakeExifEx)) { metadata.Camera.LensMake = lensMakeExifEx; } if (xmpProperties.TryGetValue("exifEX:LensModel", out var lensTypeExifEx)) { metadata.Camera.LensModel = lensTypeExifEx; } if (xmpProperties.TryGetValue("exifEX:LensSerialNumber", out var lensSerialNumberExifEx)) { metadata.Camera.LensSerialNumber = lensSerialNumberExifEx; } return(metadata); }
} // 짐벌 yaw : GimbalYawDegree public MetaData(string file_path) { try { var readers = new IJpegSegmentMetadataReader[] { new ExifReader(), new XmpReader() }; var directories = JpegMetadataReader.ReadMetadata(file_path, readers); // JPEG 파일 정보 ExifSubIfdDirectory sub_directory = directories.OfType <ExifSubIfdDirectory>().FirstOrDefault(); SetExifData(sub_directory); // DJI XMP 정보 설정 // 드론, 짐벌 정보 XmpDirectory xmp_directory = directories.OfType <XmpDirectory>().FirstOrDefault(); SetXmpData(xmp_directory); } catch (JpegProcessingException e) { throw e; } catch (IOException e) { throw e; } }
public XmpReaderTest() { var jpegSegments = new [] { new JpegSegment(JpegSegmentType.App1, TestDataUtil.GetBytes("Data/withXmpAndIptc.jpg.app1.1"), offset: 0) }; var directories = new XmpReader().ReadJpegSegments(jpegSegments); _directory = directories.OfType <XmpDirectory>().ToList().Single(); Assert.False(_directory.HasError); }
public XmpReaderTest() { var jpegSegments = new [] { File.ReadAllBytes("Tests/Data/withXmpAndIptc.jpg.app1.1") }; var directories = new XmpReader().ReadJpegSegments(jpegSegments, JpegSegmentType.App1); _directory = directories.OfType <XmpDirectory>().ToList().Single(); Assert.False(_directory.HasError); }
private static IReadOnlyList <XmpDirectory> ReadJpegSegments(IEnumerable <JpegSegment> segments) { // This is a modified version of XmpReader.ReadJpegSegments // The original version specifically tests the buffer against the classic XMP preamble and discards everything else. // Here we also test against the extended XMP preamble and regroup all the extended segments into a single buffer. // Note that we do not import any of the usual tags as in ProcessXmpTags(). Users of the class have to go // through XmpMeta methods. var directories = new List <XmpDirectory>(); byte[] extendedData = null; int maxPreambleLength = Math.Max(XmpJpegPreamble.Length, XmpJpegExtendedPreamble.Length); try { foreach (var segment in segments) { string extractedPreamble = Encoding.UTF8.GetString(segment.Bytes, 0, maxPreambleLength); if (extractedPreamble.StartsWith(XmpJpegPreamble)) { ParseNormalXmpSegment(directories, segment.Bytes); } else if (extractedPreamble.StartsWith(XmpJpegExtendedPreamble)) { ParseExtendedXmpSegment(ref extendedData, segment.Bytes); } } } catch (JpegProcessingException) { return(directories); } if (extendedData == null) { return(directories); } // We have collected extended XMP data, let's parse the reconstructed buffer. XmpDirectory directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(extendedData); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } directories.Add(directory); return(directories); }
public void SetXmpData(XmpDirectory xmp) { if (xmp == null) { return; } foreach (var property in xmp.XmpMeta.Properties) { if (property.Path == null) { continue; } if (property.Path.Contains("GpsLatitude")) { latitude = float.Parse(property.Value); } else if (property.Path.Contains("GpsLongitude")) { longitude = float.Parse(property.Value); } else if (property.Path.Contains("AbsoluteAltitude")) { absolute_altitude = float.Parse(property.Value); } else if (property.Path.Contains("RelativeAltitude")) { relative_altitude = float.Parse(property.Value); } else if (property.Path.Contains("FlightPitchDegree")) { drone_pitch = float.Parse(property.Value); } else if (property.Path.Contains("FlightRollDegree")) { drone_roll = float.Parse(property.Value); } else if (property.Path.Contains("FlightYawDegree")) { drone_yaw = float.Parse(property.Value); } else if (property.Path.Contains("GimbalPitchDegree")) { gimbal_pitch = float.Parse(property.Value); } else if (property.Path.Contains("GimbalRollDegree")) { gimbal_roll = float.Parse(property.Value); } else if (property.Path.Contains("GimbalYawDegree")) { gimbal_yaw = float.Parse(property.Value); } } }
private static void ParseNormalXmpSegment(List <XmpDirectory> directories, byte[] segmentBytes) { byte[] xmpBytes = new byte[segmentBytes.Length - XmpJpegPreamble.Length]; Array.Copy(segmentBytes, XmpJpegPreamble.Length, xmpBytes, 0, xmpBytes.Length); XmpDirectory directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } directories.Add(directory); }
public void ExifRead_GetExifDateTimeTest_GetXmpData() { var container = new List <Directory>(); var dir2 = new XmpDirectory(); dir2.SetXmpMeta(new XmpMeta()); if (dir2.XmpMeta == null) { throw new NullReferenceException( "ExifRead_GetExifDateTimeTest_GetXmpData xmpMeta Field"); } dir2.XmpMeta.SetProperty("http://ns.adobe.com/photoshop/1.0/", "photoshop:DateCreated", "2020-03-14T14:00:51"); container.Add(dir2); var result = new ReadMetaExif(null).GetExifDateTime(container); var expectedExifDateTime = new DateTime(2020, 3, 14, 14, 0, 51); Assert.AreEqual(expectedExifDateTime, result); }
/// <summary> /// Pull out the XMP face area so we can convert it to a real face in the DB /// </summary> /// <param name="xmpDirectory"></param> /// <returns></returns> private List <ImageObject> ReadXMPFaceRegionData(XmpDirectory xmpDirectory, Image image, string orientation) { try { var newFaces = new List <ImageObject>(); var nvps = xmpDirectory.XmpMeta.Properties .Where(x => !string.IsNullOrEmpty(x.Path)) .ToDictionary(x => x.Path, y => y.Value); int iRegion = 0; var(flipH, flipV) = FlipHorizVert(orientation); while (true) { iRegion++; var regionBase = $"mwg-rs:Regions/mwg-rs:RegionList[{iRegion}]/mwg-rs:"; // Check if there's a name for the next region. If not, we've probably done them all if (!nvps.ContainsKey($"{regionBase}Name")) { break; } var name = nvps[$"{regionBase}Name"]; var type = nvps[$"{regionBase}Type"]; var xStr = nvps[$"{regionBase}Area/stArea:x"]; var yStr = nvps[$"{regionBase}Area/stArea:y"]; var wStr = nvps[$"{regionBase}Area/stArea:w"]; var hStr = nvps[$"{regionBase}Area/stArea:h"]; double x = Convert.ToDouble(xStr); double y = Convert.ToDouble(yStr); double w = Convert.ToDouble(wStr); double h = Convert.ToDouble(hStr); if (flipH) { x = 1 - x; } if (flipV) { y = 1 - y; } var newPerson = new Person { Name = name, LastUpdated = DateTime.UtcNow, State = Person.PersonState.Identified }; var newFace = new ImageObject { RecogntionSource = ImageObject.RecognitionType.ExternalApp, ImageId = image.ImageId, // Note that x and y in this case are the centrepoints of the faces. // Make sure we offset the rects by half their width and height // to centre them on the face. RectX = (int)((x - (w / 2)) * image.MetaData.Width), RectY = (int)((y - (h / 2)) * image.MetaData.Height), RectHeight = (int)(h * image.MetaData.Height), RectWidth = (int)(w * image.MetaData.Width), TagId = 0, Type = ImageObject.ObjectTypes.Face.ToString(), Score = 100, Person = newPerson }; newFaces.Add(newFace); } return(newFaces); } catch (Exception ex) { Logging.LogError($"Exception while parsing XMP face/region data: {ex}"); } return(new List <ImageObject>()); }