public DirectoryList ReadJpegSegments(IEnumerable <JpegSegment> segments) { // Ensure collection materialised (avoiding multiple lazy enumeration) segments = segments.ToList(); var directories = segments .Where(IsXmpSegment) .Select(segment => Extract(segment.Bytes, JpegSegmentPreambleBytes.Length, segment.Bytes.Length - JpegSegmentPreambleBytes.Length)) .Cast <Directory>() .ToList(); var extensionGroups = segments.Where(IsExtendedXmpSegment).GroupBy(GetExtendedDataGuid); foreach (var extensionGroup in extensionGroups) { var buffer = new MemoryStream(); foreach (var segment in extensionGroup) { var N = JpegSegmentPreambleExtensionBytes.Length + 32 + 4 + 4; buffer.Write(segment.Bytes, N, segment.Bytes.Length - N); } buffer.Position = 0; var directory = new XmpDirectory(); var xmpMeta = XmpMetaFactory.Parse(buffer); directory.SetXmpMeta(xmpMeta); directories.Add(directory); } return(directories); }
public void copyDateCreatedToDateTimeOriginal() { IXmpMeta xmpMeta; using (var fileStream = File.OpenRead(XmpFile.FullName)) { xmpMeta = XmpMetaFactory.Parse(fileStream); if (xmpMeta.DoesPropertyExist("http://ns.adobe.com/photoshop/1.0/", "photoshop:DateCreated")) { IXmpDateTime xmpMetaCreateDate = xmpMeta.GetPropertyDate("http://ns.adobe.com/photoshop/1.0/", "photoshop:DateCreated"); List <FileInfo> correspondingImageFiles = this.getCorrespondingImageFile(); foreach (FileInfo correspondingImageFile in correspondingImageFiles) { DateTime?DateTimeOriginal = this.getDateTimeOriginal(correspondingImageFile); if (DateTimeOriginal == null) { ExifToolWrapper exifTool = new ExifToolWrapper(); ExifToolResponse jsonExifToolOutput = exifTool.execute(string.Concat("-m -S -overwrite_original \"-DateTimeOriginal=", xmpMetaCreateDate.ToIso8601String(), "\""), correspondingImageFile); } else { Program.MainLogger.Information($"DateTimeOriginal TAG in file {correspondingImageFile} already set to {DateTimeOriginal}"); } } } else { Program.MainLogger.Information($"Cant't find 'photoshop:DateCreated' property in namespace 'http://ns.adobe.com/photoshop/1.0/'"); } } }
/// <summary> /// Some image editing apps such as Lightroom, On1, etc., do not persist the keyword metadata /// in the images by default. This can mean you keyword-tag them, but those keywords are only /// stored in the sidecars. Damselfly only scans keyword metadata from the EXIF image data /// itself. /// So to rectify this, we can either read the sidecar files for those keywords, and optionally /// write the missing keywords to the Exif Metadata as we index them. /// </summary> /// <param name="img"></param> /// <param name="keywords"></param> private void ProcessSideCarKeywords(Image img, string[] keywords) { var sideCarTags = new List <string>(); var sidecarSearch = Path.ChangeExtension(img.FileName, "*"); DirectoryInfo dir = new DirectoryInfo(img.Folder.Path); var files = dir.GetFiles(sidecarSearch); var on1Sidecar = files.FirstOrDefault(x => x.Extension.Equals(".on1", StringComparison.OrdinalIgnoreCase)); if (on1Sidecar != null) { var on1MetaData = On1Sidecar.LoadMetadata(on1Sidecar); if (on1MetaData != null) { var missingKeywords = on1MetaData.Keywords .Except(keywords, StringComparer.OrdinalIgnoreCase) .ToList(); if (missingKeywords.Any()) { Logging.LogVerbose($"Image {img.FileName} is missing {missingKeywords.Count} keywords present in the On1 Sidecar."); sideCarTags = sideCarTags.Union(missingKeywords, StringComparer.OrdinalIgnoreCase).ToList(); } } } var xmpSidecar = files.FirstOrDefault(x => x.Extension.Equals(".xmp", StringComparison.OrdinalIgnoreCase)); if (xmpSidecar != null) { using var stream = File.OpenRead(xmpSidecar.FullName); IXmpMeta xmp = XmpMetaFactory.Parse(stream); var xmpKeywords = xmp.Properties.FirstOrDefault(x => x.Path == "pdf:Keywords"); if (xmpKeywords != null) { var missingKeywords = xmpKeywords.Value .Split(",") .Select(x => x.Trim()) .Except(keywords) .ToList(); if (missingKeywords.Any()) { Logging.LogVerbose($"Image {img.FileName} is missing {missingKeywords.Count} keywords present in the XMP Sidecar."); sideCarTags = sideCarTags.Union(missingKeywords, StringComparer.OrdinalIgnoreCase).ToList(); } } } if (sideCarTags.Any()) { // Now, submit the tags; note they won't get created immediately, but in batch. Logging.Log($"Applying {sideCarTags.Count} keywords from sidecar files to image {img.FileName}"); _ = MetaDataService.Instance.UpdateTagsAsync(new[] { img }, sideCarTags, null); } }
private void GenerateEAttachmentDocument(PdfAWriter writer, XmpWriter xmpWriter, EAttactment attachment) { // Use default intent if output intent of this instance was not set if (attachment.outputIntents == null) { //byte[] iccProfile = File.ReadAllBytes("/Resources/sRGB Color Space Profile.icm"); byte[] iccProfile = Properties.Resources.sRGB_Color_Space_Profile; ICC_Profile icc = ICC_Profile.GetInstance(iccProfile); writer.SetOutputIntents("sRGB IEC61966-2.1", "", "http://www.color.org", "sRGB IEC61966-2.1", icc); } else { OutputIntents outputIntents = attachment.outputIntents; byte[] iccProfileByteArray = File.ReadAllBytes(outputIntents.colorProfilePath); ICC_Profile icc = ICC_Profile.GetInstance(iccProfileByteArray); writer.SetOutputIntents(outputIntents.outputConditionIdentifier, outputIntents.outputCondition, outputIntents.registryName, outputIntents.info, icc); } //============= Create Exchange ECertificate ================= // 1 add ContentInformation.xml to document PdfArray attachmentArray = new PdfArray(); writer.ExtraCatalog.Put(new PdfName("AF"), attachmentArray); PdfFileSpecification contentSpec = this.EmbeddedAttachment(attachment.contentInformationXMLPath, attachment.attachmentName, attachment.attachmentMIME, new PdfName(attachment.attachmentType), writer, attachment.attachmentDescription); attachmentArray.Add(contentSpec.Reference); foreach (var item in attachment.fileAttachments) { contentSpec = this.EmbeddedAttachment(item.attachmentPath, item.attachmentName, item.attachmentMIME, new PdfName(item.attachmentType), writer, item.attachmentDescription); attachmentArray.Add(contentSpec.Reference); } // 2 add Electronic Document XMP Metadata ElectronicDocumentSchema ed = ElectronicDocumentSchema.generateED(attachment.attachmentName, attachment.documentVersion, attachment.documentID, attachment.documentOID); xmpWriter.AddRdfDescription(ed); string pdfaSchema = Properties.Resources.EDocument_PDFAExtensionSchema; // convert string to stream byte[] byteArray = Encoding.UTF8.GetBytes(pdfaSchema); //byte[] byteArray = Encoding.ASCII.GetBytes(contents); MemoryStream stream = new MemoryStream(byteArray); IXmpMeta edPDFAextension = XmpMetaFactory.Parse(stream); IXmpMeta originalXMP = xmpWriter.XmpMeta; XmpUtils.AppendProperties(edPDFAextension, originalXMP, true, true); }
private static void HandleFile(FileInfo file) { // Console.WriteLine("{0}", file.Name); IXmpMeta xmp; String curFile = file.FullName.ToString(); // using (var stream = File.OpenRead(file.DirectoryName + "/" + file.Name)) using (var stream = File.OpenRead(curFile)) xmp = XmpMetaFactory.Parse(stream); Boolean success = false; foreach (var property in xmp.Properties) { success = false; //Console.WriteLine($"Path={property.Path} Namespace={property.Namespace} Value={property.Value}"); // Console.WriteLine($"Path={property.Path} Value={property.Value}"); // if (property.Path == "crs:Look/crs:Name"|| property.Path == "crs:Name[1]") if (property.Path == "crs:Name[1]") { string newfilename = property.Value.Trim().Replace('/', '-') + ".xmp"; if (string.Compare(newfilename, file.Name.ToString(), CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase) == 0) // if (newfilename != file.Name) { break; } else { file.CopyTo(file.DirectoryName + "/" + file.Name + "_old", true); file.CopyTo(file.DirectoryName + "/" + newfilename, true); Console.WriteLine(property.Value); success = true; break; } } } if (success == true) { file.Delete(); } }
/// <summary> /// Given a sidecar object, parses the files (ON1 or XMP) and pulls out /// the list of keywords in the sidecar file. /// </summary> /// <param name="sidecar"></param> /// <returns></returns> public static IList <string> GetKeywords(this ImageSideCar sidecar) { var sideCarTags = new List <string>(); // If there's an On1 sidecar, read it try { if (sidecar.Type == SidecarUtils.SidecarType.ON1) { var on1MetaData = On1Sidecar.LoadMetadata(sidecar.Filename); if (on1MetaData != null && on1MetaData.Keywords != null && on1MetaData.Keywords.Any()) { sideCarTags = on1MetaData.Keywords .Select(x => x.Trim()) .ToList(); } } // If there's an XMP sidecar if (sidecar.Type == SidecarUtils.SidecarType.XMP) { using var stream = File.OpenRead(sidecar.Filename.FullName); IXmpMeta xmp = XmpMetaFactory.Parse(stream); var xmpKeywords = xmp.Properties.FirstOrDefault(x => x.Path == "pdf:Keywords"); if (xmpKeywords != null) { sideCarTags = xmpKeywords.Value.Split(",") .Select(x => x.Trim()) .ToList(); } } } catch (Exception ex) { Logging.LogError($"Exception processing {sidecar.Type} sidecar: {sidecar.Filename.FullName}: {ex.Message}"); } return(sideCarTags); }