Пример #1
0
        public virtual void readMetadata(MediaProbe mediaProbe, Stream data, MetadataFactory.ReadOptions options, BaseMetadata media, CancellationToken token, int timeoutSeconds)
        {
            XMPLib.MetaData.ErrorCallbackDelegate errorCallbackDelegate = new XMPLib.MetaData.ErrorCallbackDelegate(errorCallback);

            //XMPLib.MetaData xmpMetaDataReader = new XMPLib.MetaData(errorCallbackDelegate, null);
            XMPLib.MetaData xmpMetaDataReader = new XMPLib.MetaData(null, null);

            try
            {
                FileInfo info = new FileInfo(media.Location);
                info.Refresh();
                media.LastModifiedDate = info.LastWriteTime < sqlMinDate ? sqlMinDate : info.LastWriteTime;
                media.FileDate         = info.CreationTime < sqlMinDate ? sqlMinDate : info.CreationTime;
                media.MimeType         = MediaFormatConvert.fileNameToMimeType(media.Name);

                if (media.SupportsXMPMetadata == false)
                {
                    return;
                }

                xmpMetaDataReader.open(media.Location, Consts.OpenOptions.XMPFiles_OpenForRead);

                readXMPMetadata(xmpMetaDataReader, media);
            }
            catch (Exception e)
            {
                Logger.Log.Error("Cannot read XMP metadata for: " + media.Location, e);
                media.MetadataReadError = e;
            } finally {
                xmpMetaDataReader.Dispose();
                xmpMetaDataReader = null;
            }
        }
Пример #2
0
        public virtual void writeMetadata(BaseMetadata media, CancellableOperationProgressBase progress = null)
        {
            Progress = progress;

            XMPLib.MetaData.ErrorCallbackDelegate errorCallbackDelegate = new XMPLib.MetaData.ErrorCallbackDelegate(errorCallback);
            // bug in xmplib, crashes on write when video is mpg and a progresscallback is active
            XMPLib.MetaData.ProgressCallbackDelegate progressCallbackDelegate = media.MimeType.Equals("video/mpeg") ? null : new XMPLib.MetaData.ProgressCallbackDelegate(progressCallback);

            XMPLib.MetaData xmpMetaDataWriter = new XMPLib.MetaData(errorCallbackDelegate, progressCallbackDelegate);

            try
            {
                if (media.SupportsXMPMetadata)
                {
                    xmpMetaDataWriter.open(media.Location, Consts.OpenOptions.XMPFiles_OpenForUpdate);

                    write(xmpMetaDataWriter, media);
                }
                else
                {
                    throw new Exception("Format does not support XMP metadata");
                }
            }
            finally
            {
                xmpMetaDataWriter.Dispose();
                xmpMetaDataWriter = null;
            }
        }
Пример #3
0
        public virtual void writeMetadata(BaseMetadata media, CancellableOperationProgressBase progress = null)
        {
            Progress = progress;       

            XMPLib.MetaData.ErrorCallbackDelegate errorCallbackDelegate = new XMPLib.MetaData.ErrorCallbackDelegate(errorCallback);
            // bug in xmplib, crashes on write when video is mpg and a progresscallback is active
            XMPLib.MetaData.ProgressCallbackDelegate progressCallbackDelegate = media.MimeType.Equals("video/mpeg") ? null : new XMPLib.MetaData.ProgressCallbackDelegate(progressCallback);

            XMPLib.MetaData xmpMetaDataWriter = new XMPLib.MetaData(errorCallbackDelegate, progressCallbackDelegate);

            try
            {
               if (media.SupportsXMPMetadata)
               {
                   xmpMetaDataWriter.open(media.Location, Consts.OpenOptions.XMPFiles_OpenForUpdate);

                   write(xmpMetaDataWriter, media);
               }
               else
               {
                  throw new Exception("Format does not support XMP metadata");
               }

            }
            finally
            {
                xmpMetaDataWriter.Dispose();
                xmpMetaDataWriter = null;
            }
        }
Пример #4
0
        public virtual void readMetadata(MediaProbe mediaProbe, Stream data, MetadataFactory.ReadOptions options, BaseMetadata media, CancellationToken token, int timeoutSeconds)
        {

            XMPLib.MetaData.ErrorCallbackDelegate errorCallbackDelegate = new XMPLib.MetaData.ErrorCallbackDelegate(errorCallback);

            //XMPLib.MetaData xmpMetaDataReader = new XMPLib.MetaData(errorCallbackDelegate, null);
            XMPLib.MetaData xmpMetaDataReader = new XMPLib.MetaData(null, null);

            try
            {
                
                FileInfo info = new FileInfo(media.Location);
                info.Refresh();
                media.LastModifiedDate = info.LastWriteTime < sqlMinDate ? sqlMinDate : info.LastWriteTime;
                media.FileDate = info.CreationTime < sqlMinDate ? sqlMinDate : info.CreationTime;
                media.MimeType = MediaFormatConvert.fileNameToMimeType(media.Name); 

                if (media.SupportsXMPMetadata == false) return;

                xmpMetaDataReader.open(media.Location, Consts.OpenOptions.XMPFiles_OpenForRead);
                                    
                readXMPMetadata(xmpMetaDataReader, media);
                
            }
            catch (Exception e)
            {
                Logger.Log.Error("Cannot read XMP metadata for: " + media.Location, e);
                media.MetadataReadError = e;

            } finally {
          
                xmpMetaDataReader.Dispose();
                xmpMetaDataReader = null;
            }
        }
Пример #5
0
        public static MetaDataTreeNode create(XMPLib.MetaData data)
        {
            List <MetaDataProperty> propsList = new List <MetaDataProperty>();

            data.iterate(Consts.IterOptions.XMP_IterJustLeafNodes, ref propsList);

            MetaDataTreeNode root = new MetaDataTreeNameSpaceNode("root");

            foreach (MetaDataProperty p in propsList)
            {
                string path = p.path;

                //Debug.Print(p.path);
                root.insertNode(p.path, p.value);
            }

            return(root);
        }
Пример #6
0
        protected virtual void readXMPMetadata(XMPLib.MetaData xmpMetaDataReader, BaseMetadata media)
        {
            string title = "";

            xmpMetaDataReader.getLocalizedText(Consts.XMP_NS_DC, "title", "en", "en-US", ref title);

            media.Title = title;

            string description = "";

            xmpMetaDataReader.getLocalizedText(Consts.XMP_NS_DC, "description", "en", "en-US", ref description);

            media.Description = description;

            string author = "";

            xmpMetaDataReader.getArrayItem(Consts.XMP_NS_DC, "creator", 1, ref author);

            media.Author = author;

            string copyright = "";

            xmpMetaDataReader.getLocalizedText(Consts.XMP_NS_DC, "rights", "en", "en-US", ref copyright);

            media.Copyright = copyright;

            string software = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_XMP, "CreatorTool", ref software);

            media.Software = software;

            Nullable <double> rating = new Nullable <double>();

            xmpMetaDataReader.getProperty_Float(Consts.XMP_NS_XMP, "Rating", ref rating);

            media.Rating = rating;

            Nullable <DateTime> date = new Nullable <DateTime>();

            xmpMetaDataReader.getProperty_Date(Consts.XMP_NS_XMP, "MetadataDate", ref date);
            if (date != null && date < sqlMinDate)
            {
                media.MetadataDate = null;
            }
            else
            {
                media.MetadataDate = date;
            }

            xmpMetaDataReader.getProperty_Date(Consts.XMP_NS_XMP, "CreateDate", ref date);
            if (date != null && date < sqlMinDate)
            {
                media.CreationDate = null;
            }
            else
            {
                media.CreationDate = date;
            }

            xmpMetaDataReader.getProperty_Date(Consts.XMP_NS_XMP, "ModifyDate", ref date);
            if (date != null && date < sqlMinDate)
            {
                media.MetadataModifiedDate = null;
            }
            else
            {
                media.MetadataModifiedDate = date;
            }

            string longitude = null;
            string latitude  = null;

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF, "GPSLatitude", ref latitude);
            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF, "GPSLongitude", ref longitude);

            GeoTagCoordinatePair geoPair = new GeoTagCoordinatePair(latitude, longitude);

            media.Latitude  = geoPair.LatDecimal;
            media.Longitude = geoPair.LonDecimal;

            media.Tags.Clear();

            int nrTags = xmpMetaDataReader.countArrayItems(Consts.XMP_NS_DC, "subject");

            for (int i = 1; i <= nrTags; i++)
            {
                string tagName = "";
                xmpMetaDataReader.getArrayItem(Consts.XMP_NS_DC, "subject", i, ref tagName);

                if (tagName != null)
                {
                    Tag newTag = new Tag();
                    newTag.Name = tagName.Trim();

                    media.Tags.Add(newTag);
                }
            }

            /*string imageData = "";
             *
             * bool exists = xmpMetaDataReader.getStructField(Consts.XMP_NS_XMP, "xmpGImg", Consts.XMP_NS_XMP_Image, "image", ref imageData);
             * if (exists)
             * {
             *  BitmapSource thumbnail = MediaViewer.Infrastructure.Utils.ImageUtils.jpegBase64StringToImage(imageData);
             *
             * }*/
        }
Пример #7
0
        protected override void readXMPMetadata(XMPLib.MetaData xmpMetaDataReader, BaseMetadata media)
        {
            base.readXMPMetadata(xmpMetaDataReader, media);

            ImageMetadata image = media as ImageMetadata;

            Nullable <int> intVal = new Nullable <int>();
            String         temp   = "";
            bool           exists = false;

            exists = xmpMetaDataReader.getStructField(Consts.XMP_NS_EXIF, "Flash", Consts.XMP_NS_EXIF, "exif:Fired", ref temp);
            if (exists)
            {
                try
                {
                    image.FlashFired = Boolean.Parse(temp);
                }
                catch (Exception)
                {
                    image.FlashFired = null;
                }
            }
            else
            {
                image.FlashFired = null;
            }

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "LightSource", ref intVal);
            if (intVal == null)
            {
                image.LightSource = null;
            }
            else
            {
                image.LightSource = (short)intVal;
            }

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "MeteringMode", ref intVal);
            if (intVal == null)
            {
                image.MeteringMode = null;
            }
            else
            {
                image.MeteringMode = (short)intVal;
            }

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "Saturation", ref intVal);
            if (intVal == null)
            {
                image.Saturation = null;
            }
            else
            {
                image.Saturation = (short)intVal;
            }


            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "SceneCaptureType", ref intVal);
            if (intVal == null)
            {
                image.SceneCaptureType = null;
            }
            else
            {
                image.SceneCaptureType = (short)intVal;
            }

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "SensingMethod", ref intVal);
            if (intVal == null)
            {
                image.SensingMethod = null;
            }
            else
            {
                image.SensingMethod = (short)intVal;
            }

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "Sharpness", ref intVal);
            if (intVal == null)
            {
                image.Sharpness = null;
            }
            else
            {
                image.Sharpness = (short)intVal;
            }

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_TIFF, "Orientation", ref intVal);
            if (intVal == null)
            {
                image.Orientation = null;
            }
            else
            {
                image.Orientation = (short)intVal;
            }

            string subjectDistance = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF, "SubjectDistance", ref subjectDistance);
            image.SubjectDistance = parseRational(subjectDistance);

            string shutterSpeedValue = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF, "ShutterSpeedValue", ref shutterSpeedValue);
            image.ShutterSpeedValue = parseRational(shutterSpeedValue);

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "SubjectDistanceRange", ref intVal);
            if (intVal == null)
            {
                image.SubjectDistanceRange = null;
            }
            else
            {
                image.SubjectDistanceRange = (short)intVal;
            }

            string isoSpeedRating = "";

            int nrSpeedRatings = xmpMetaDataReader.countArrayItems(Consts.XMP_NS_EXIF, "ISOSpeedRatings");

            if (nrSpeedRatings > 0)
            {
                xmpMetaDataReader.getArrayItem(Consts.XMP_NS_EXIF, "ISOSpeedRatings", 1, ref isoSpeedRating);
                int value = 0;
                if (int.TryParse(isoSpeedRating, out value))
                {
                    image.ISOSpeedRating = value;
                }
            }
            else
            {
                image.ISOSpeedRating = null;
            }

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "WhiteBalance", ref intVal);
            if (intVal == null)
            {
                image.WhiteBalance = null;
            }
            else
            {
                image.WhiteBalance = (short)intVal;
            }

            String cameraMake = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_TIFF, "Make", ref cameraMake);
            image.CameraMake = cameraMake;

            String cameraModel = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_TIFF, "Model", ref cameraModel);
            image.CameraModel = cameraModel;

            String lens = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF_Aux, "Lens", ref lens);
            image.Lens = lens;

            String serialNumber = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF_Aux, "SerialNumber", ref serialNumber);
            image.SerialNumber = serialNumber;

            string exposureTime = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF, "ExposureTime", ref exposureTime);
            image.ExposureTime = parseRational(exposureTime);

            string fnumber = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF, "FNumber", ref fnumber);
            image.FNumber = parseRational(fnumber);

            string exposureBiasValue = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF, "ExposureBiasValue", ref exposureBiasValue);
            image.ExposureBiasValue = parseRational(exposureBiasValue);

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "ExposureProgram", ref intVal);
            if (intVal == null)
            {
                image.ExposureProgram = null;
            }
            else
            {
                image.ExposureProgram = (short)intVal;
            }

            string focalLength = "";

            xmpMetaDataReader.getProperty(Consts.XMP_NS_EXIF, "FocalLength", ref focalLength);
            image.FocalLength = parseRational(focalLength);

            xmpMetaDataReader.getProperty_Int(Consts.XMP_NS_EXIF, "Contrast", ref intVal);
            if (intVal == null)
            {
                image.Contrast = null;
            }
            else
            {
                image.Contrast = (short)intVal;
            }
        }
Пример #8
0
        protected override void write(XMPLib.MetaData xmpMetaDataWriter, BaseMetadata media)
        {
            ImageMetadata image = media as ImageMetadata;

            if (image.FlashFired != null)
            {
                xmpMetaDataWriter.setStructField(Consts.XMP_NS_EXIF, "Flash", "http://ns.adobe.com/exif/1.0/", "exif:Fired", image.FlashFired.Value.ToString(), 0);
            }
            else
            {
                xmpMetaDataWriter.deleteStructField(Consts.XMP_NS_EXIF, "Flash", "http://ns.adobe.com/exif/1.0/", "exif:Fired");
            }

            // integers

            if (image.LightSource != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "LightSource", image.LightSource.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "LightSource");
            }

            if (image.MeteringMode != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "MeteringMode", image.MeteringMode.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "MeteringMode");
            }

            if (image.Saturation != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "Saturation", image.Saturation.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "Saturation");
            }

            if (image.SceneCaptureType != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "SceneCaptureType", image.SceneCaptureType.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "SceneCaptureType");
            }

            if (image.SensingMethod != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "SensingMethod", image.SensingMethod.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "SensingMethod");
            }

            if (image.Sharpness != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "Sharpness", image.Sharpness.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "Sharpness");
            }

            if (image.Orientation != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "Orientation", image.Orientation.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "Orientation");
            }

            if (image.Contrast != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "Contrast", image.Contrast.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "Contrast");
            }

            if (image.SubjectDistanceRange != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "SubjectDistanceRange", image.SubjectDistanceRange.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "SubjectDistanceRange");
            }

            if (image.WhiteBalance != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "WhiteBalance", image.WhiteBalance.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "WhiteBalance");
            }

            if (image.ExposureProgram != null)
            {
                xmpMetaDataWriter.setProperty_Int(Consts.XMP_NS_EXIF, "ExposureProgram", image.ExposureProgram.Value);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "ExposureProgram");
            }

            // strings

            if (image.CameraMake != null)
            {
                xmpMetaDataWriter.setProperty(Consts.XMP_NS_TIFF, "Make", image.CameraMake, Consts.PropOptions.XMP_NoOptions);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_TIFF, "Make");
            }

            if (image.CameraModel != null)
            {
                xmpMetaDataWriter.setProperty(Consts.XMP_NS_TIFF, "Model", image.CameraModel, Consts.PropOptions.XMP_NoOptions);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_TIFF, "Model");
            }

            if (image.Lens != null)
            {
                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF_Aux, "Lens", image.Lens, Consts.PropOptions.XMP_NoOptions);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF_Aux, "Lens");
            }

            if (image.SerialNumber != null)
            {
                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF_Aux, "SerialNumber", image.SerialNumber, Consts.PropOptions.XMP_NoOptions);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF_Aux, "SerialNumber");
            }

            // fractions

            if (image.ExposureTime != null)
            {
                String result = approximateFraction(image.ExposureTime.Value);

                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF, "ExposureTime", result, 0);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "ExposureTime");
            }

            if (image.FNumber != null)
            {
                String result = approximateFraction(image.FNumber.Value);

                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF, "FNumber", result, 0);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "FNumber");
            }

            if (image.ExposureBiasValue != null)
            {
                String result = approximateFraction(image.ExposureBiasValue.Value);

                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF, "ExposureBiasValue", result, 0);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "ExposureBiasValue");
            }

            if (image.FocalLength != null)
            {
                String result = approximateFraction(image.FocalLength.Value);

                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF, "FocalLength", result, 0);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "FocalLength");
            }

            if (image.SubjectDistance != null)
            {
                String result = approximateFraction(image.SubjectDistance.Value);

                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF, "SubjectDistance", result, 0);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "SubjectDistance");
            }

            if (image.ShutterSpeedValue != null)
            {
                String result = approximateFraction(image.ShutterSpeedValue.Value);

                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF, "ShutterSpeedValue", result, 0);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "ShutterSpeedValue");
            }

            if (image.ISOSpeedRating != null)
            {
                if (xmpMetaDataWriter.doesArrayItemExist(Consts.XMP_NS_EXIF, "ISOSpeedRatings", 1))
                {
                    xmpMetaDataWriter.setArrayItem(Consts.XMP_NS_EXIF, "ISOSpeedRatings", 1, image.ISOSpeedRating.Value.ToString(), 0);
                }
                else
                {
                    xmpMetaDataWriter.appendArrayItem(Consts.XMP_NS_EXIF, "ISOSpeedRatings",
                                                      Consts.PropOptions.XMP_PropArrayIsOrdered, image.ISOSpeedRating.Value.ToString(), 0);
                }
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "ISOSpeedRatings");
            }

            base.write(xmpMetaDataWriter, media);
        }
Пример #9
0
        protected virtual void write(XMPLib.MetaData xmpMetaDataWriter, BaseMetadata media)
        {
            if (media.Title != null)
            {
                xmpMetaDataWriter.setLocalizedText(Consts.XMP_NS_DC, "title", "en", "en-US", media.Title);
            }

            if (media.Rating != null)
            {
                xmpMetaDataWriter.setProperty_Float(Consts.XMP_NS_XMP, "Rating", media.Rating.Value);
                //xmpMetaDataWriter.setProperty(Consts.XMP_NS_XMP, "Rating", media.Rating.ToString(), Consts.PropOptions.XMP_DeleteExisting);
            }

            if (media.Description != null)
            {
                xmpMetaDataWriter.setLocalizedText(Consts.XMP_NS_DC, "description", "en", "en-US", media.Description);
            }

            if (media.Software != null)
            {
                xmpMetaDataWriter.setProperty(Consts.XMP_NS_XMP, "CreatorTool", media.Software,
                                              Consts.PropOptions.XMP_DeleteExisting);
            }

            if (media.Author != null)
            {
                if (xmpMetaDataWriter.doesArrayItemExist(Consts.XMP_NS_DC, "creator", 1))
                {
                    xmpMetaDataWriter.setArrayItem(Consts.XMP_NS_DC, "creator", 1, media.Author, 0);
                }
                else
                {
                    xmpMetaDataWriter.appendArrayItem(Consts.XMP_NS_DC, "creator",
                                                      Consts.PropOptions.XMP_PropArrayIsOrdered, media.Author, 0);
                }
            }

            /*if (media.Thumbnail != null)
             * {
             *  string imageData = MediaViewer.Infrastructure.Utils.ImageUtils.imageToJpegBase64String(media.Thumbnail.Image);
             *
             *  xmpMetaDataWriter.setStructField(Consts.XMP_NS_XMP, "xmpGImg", Consts.XMP_NS_XMP_Image, "format", "JPEG", (uint)Consts.PropOptions.XMP_NoOptions);
             *  xmpMetaDataWriter.setStructField(Consts.XMP_NS_XMP, "xmpGImg", Consts.XMP_NS_XMP_Image, "width", media.Thumbnail.Image.Width.ToString(), (uint)Consts.PropOptions.XMP_NoOptions);
             *  xmpMetaDataWriter.setStructField(Consts.XMP_NS_XMP, "xmpGImg", Consts.XMP_NS_XMP_Image, "height", media.Thumbnail.Image.Height.ToString(), (uint)Consts.PropOptions.XMP_NoOptions);
             *  xmpMetaDataWriter.setStructField(Consts.XMP_NS_XMP, "xmpGImg", Consts.XMP_NS_XMP_Image, "image", imageData, (uint)Consts.PropOptions.XMP_NoOptions);
             * }*/

            if (media.Copyright != null)
            {
                xmpMetaDataWriter.setLocalizedText(Consts.XMP_NS_DC, "rights", "en", "en-US", media.Copyright);
            }

            if (media.CreationDate != null)
            {
                xmpMetaDataWriter.setProperty_Date(Consts.XMP_NS_XMP, "CreateDate", media.CreationDate.Value);
            }

            if (media.MetadataDate == null)
            {
                xmpMetaDataWriter.setProperty_Date(Consts.XMP_NS_XMP, "MetadataDate", DateTime.Now);
            }
            else
            {
                xmpMetaDataWriter.setProperty_Date(Consts.XMP_NS_XMP, "ModifyDate", DateTime.Now);
            }


            int nrTags = xmpMetaDataWriter.countArrayItems(Consts.XMP_NS_DC, "subject");

            for (int i = nrTags; i > 0; i--)
            {
                xmpMetaDataWriter.deleteArrayItem(Consts.XMP_NS_DC, "subject", i);
            }

            foreach (Tag tag in media.Tags)
            {
                xmpMetaDataWriter.appendArrayItem(Consts.XMP_NS_DC, "subject",
                                                  Consts.PropOptions.XMP_PropArrayIsUnordered, tag.Name, 0);
            }

            GeoTagCoordinatePair geoTag = new GeoTagCoordinatePair(media.Latitude, media.Longitude);

            if (!geoTag.IsEmpty)
            {
                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF, "GPSLatitude", geoTag.LatCoord, 0);
                xmpMetaDataWriter.setProperty(Consts.XMP_NS_EXIF, "GPSLongitude", geoTag.LonCoord, 0);
            }
            else
            {
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "GPSLatitude");
                xmpMetaDataWriter.deleteProperty(Consts.XMP_NS_EXIF, "GPSLongitude");
            }

            if (xmpMetaDataWriter.canPutXMP())
            {
                xmpMetaDataWriter.putXMP();
            }
            else
            {
                throw new Exception("Format does not support XMP metadata");
            }
        }