Exemple #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);
            }
        }
Exemple #2
0
    /// <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);
    }