Exemple #1
0
        // Populate the database with the metadata for the selected note field
        private async Task <ObservableCollection <Tuple <string, string, string> > > PopulateAsync(MetadataToolEnum metadataToolSelected)
        {
            // This list will hold key / value pairs that will be bound to the datagrid feedback,
            // which is the way to make those pairs appear in the data grid during background worker progress updates
            ObservableCollection <Tuple <string, string, string> > feedbackData = new ObservableCollection <Tuple <string, string, string> >();

            // if there are no metadata / label pairs, we are done.
            if (this.MetadataGrid.SelectedMetadata.Count == 0)
            {
                // Catch the case where there are no selected pairs, at least for now.
                feedbackData.Clear();
                feedbackData.Add(new Tuple <string, string, string>("Nothing was selected", "", "No changes were made"));
                return(feedbackData);
            }

            return(await Task.Run(() =>
            {
                // For each row in the database, get the image filename and try to extract the chosen metadata value.
                // If we can't decide if we want to leave the data field alone or to clear it depending on the state of the isClearIfNoMetadata (set via the checkbox)
                // Report progress as needed.

                // This tuple list will hold the id, key and value that we will want to update in the database
                List <ColumnTuplesWithWhere> imagesToUpdate = new List <ColumnTuplesWithWhere>();
                TimeZoneInfo imageSetTimeZone = DateTimeHandler.GetNeutralTimeZone();
                int percentDone = 0;

                double totalImages = this.FileDatabase.CountAllCurrentlySelectedFiles;
                Dictionary <string, ImageMetadata> metadata = new Dictionary <string, ImageMetadata>();
                string[] tags = this.MetadataGrid.SelectedTags;// Only needed by ExifTool, but cheap to get
                for (int imageIndex = 0; imageIndex < totalImages; ++imageIndex)
                {
                    // Provide feedback if the operation was cancelled during the database update
                    if (Token.IsCancellationRequested == true)
                    {
                        feedbackData.Clear();
                        feedbackData.Add(new Tuple <string, string, string>("Cancelled", "", "No changes were made"));
                        return feedbackData;
                    }

                    ImageRow image = this.FileDatabase.FileTable[imageIndex];

                    if (metadataToolSelected == MetadataToolEnum.MetadataExtractor)
                    {
                        // MetadataExtractor specific code
                        metadata = ImageMetadataDictionary.LoadMetadata(image.GetFilePath(this.FileDatabase.FolderPath));
                    }
                    else // if metadataToolSelected == MetadataToolEnum.ExifTool
                    {
                        // ExifTool specific code - note that we transform results into the same dictionary structure used by the MetadataExtractor
                        // Unlike MetadataExtractor, ExifTool returns TagName instad of Directory.TagName (I think - but does that mean it would break on duplicate values?
                        metadata.Clear();
                        Dictionary <string, string> exifData = this.MetadataGrid.ExifToolManager.FetchExifFrom(image.GetFilePath(this.FileDatabase.FolderPath), tags);
                        foreach (string tag in tags)
                        {
                            if (exifData.ContainsKey(tag))
                            {
                                metadata.Add(tag, new Timelapse.Util.ImageMetadata(String.Empty, tag, exifData[tag]));
                            }
                        }
                    }
                    // At this point, the metadata Key should be the tag name, rather than Directory.TagName
                    // (see ImageMetadataDiction.LoadDictionary to change it back so the key is the directory.name. I think Exif never returns the directory name, so thats ok too.

                    if (this.ReadyToRefresh())
                    {
                        percentDone = Convert.ToInt32(imageIndex / totalImages * 100.0);
                        this.Progress.Report(new ProgressBarArguments(percentDone, String.Format("{0}/{1} images. Processing {2}", imageIndex, totalImages, image.File), true, false));
                        Thread.Sleep(Constant.ThrottleValues.RenderingBackoffTime);  // Allows the UI thread to update every now and then
                    }

                    string dataLabelToUpdate = "";

                    foreach (KeyValuePair <string, string> kvp in this.MetadataGrid.SelectedMetadata)
                    {
                        string metadataTag = kvp.Key;
                        dataLabelToUpdate = kvp.Value;

                        if (false == metadata.ContainsKey(metadataTag))
                        {
                            // This just skips this metadata as it was not found in the file's metadata
                            // However, we still need to supply feedback and (if the user has asked for that option) to clear the data field
                            if (this.clearIfNoMetadata)
                            {
                                List <ColumnTuple> clearField = new List <ColumnTuple>()
                                {
                                    new ColumnTuple(dataLabelToUpdate, String.Empty)
                                };
                                imagesToUpdate.Add(new ColumnTuplesWithWhere(clearField, image.ID));
                                feedbackData.Add(new Tuple <string, string, string>(image.File, metadataTag, "No metadata found - data field cleared"));
                            }
                            else
                            {
                                feedbackData.Add(new Tuple <string, string, string>(image.File, metadataTag, "No metadata found - data field unchanged"));
                            }
                            continue;
                        }
                        string metadataValue = metadata[metadataTag].Value;
                        ColumnTuplesWithWhere imageUpdate;
                        if (this.useDateMetadataOnly)
                        {
                            if (DateTimeHandler.TryParseMetadataDateTaken(metadataValue, imageSetTimeZone, out DateTimeOffset metadataDateTime))
                            {
                                image.SetDateTimeOffset(metadataDateTime);

                                imageUpdate = image.GetDateTimeColumnTuples();
                                feedbackData.Add(new Tuple <string, string, string>(image.File, metadataTag, metadataValue));
                            }
                            else
                            {
                                feedbackData.Add(new Tuple <string, string, string>(image.File, metadataTag, String.Format("Data field unchanged - '{0}' is not a valid date/time.", metadataValue)));
                                continue;
                            }
                        }
                        else
                        {
                            imageUpdate = new ColumnTuplesWithWhere(new List <ColumnTuple>()
                            {
                                new ColumnTuple(dataLabelToUpdate, metadataValue)
                            }, image.ID);
                            feedbackData.Add(new Tuple <string, string, string>(image.File, metadataTag, metadataValue));
                        }
                        imagesToUpdate.Add(imageUpdate);
                    }
                }
                this.isAnyDataUpdated = true;
                this.Progress.Report(new ProgressBarArguments(100, String.Format("Writing metadata for {0} files. Please wait...", totalImages), false, true));
                Thread.Sleep(Constant.ThrottleValues.RenderingBackoffTime);  // Allows the UI thread to update every now and then
                this.FileDatabase.UpdateFiles(imagesToUpdate);
                return feedbackData;
            }, this.Token).ConfigureAwait(true));
        }
        // Populate the database with the metadata for the selected note field
        private async Task <ObservableCollection <KeyValuePair <string, string> > > PopulateAsync(bool?metadataExtractorRBIsChecked)
        {
            // This list will hold key / value pairs that will be bound to the datagrid feedback,
            // which is the way to make those pairs appear in the data grid during background worker progress updates
            ObservableCollection <KeyValuePair <string, string> > keyValueList = new ObservableCollection <KeyValuePair <string, string> >();

            return(await Task.Run(() =>
            {
                // For each row in the database, get the image filename and try to extract the chosen metadata value.
                // Report progress as needed.
                // This tuple list will hold the id, key and value that we will want to update in the database
                List <ColumnTuplesWithWhere> imagesToUpdate = new List <ColumnTuplesWithWhere>();
                TimeZoneInfo imageSetTimeZone = DateTimeHandler.GetNeutralTimeZone();
                int percentDone = 0;

                double totalFiles = this.fileDatabase.CountAllCurrentlySelectedFiles;
                Dictionary <string, ImageMetadata> metadata = new Dictionary <string, ImageMetadata>();
                List <ImageRow> filesToAdjust = new List <ImageRow>();

                // Start up the progress bar, so it shows something as even small data sets will have a delay in it.
                this.Progress.Report(new ProgressBarArguments(percentDone, "Initializing...", true, false));
                Thread.Sleep(Constant.ThrottleValues.RenderingBackoffTime);  // Allows the UI thread to update every now and then

                int metadataUpdateCount = 0;
                for (int imageIndex = 0; imageIndex < totalFiles; ++imageIndex)
                {
                    // Provide feedback if the operation was cancelled during the database update
                    if (Token.IsCancellationRequested == true)
                    {
                        keyValueList.Clear();
                        keyValueList.Add(new KeyValuePair <string, string>("Cancelled", "No changes were made"));
                        return keyValueList;
                    }

                    ImageRow image = this.fileDatabase.FileTable[imageIndex];
                    if (metadataExtractorRBIsChecked == true)
                    {   // MetadataExtractor specific code
                        metadata = ImageMetadataDictionary.LoadMetadata(image.GetFilePath(this.fileDatabase.FolderPath));
                    }
                    else
                    {
                        // ExifTool specific code - note that we transform results into the same dictionary structure used by the MetadataExtractor
                        string[] tags = { this.metadataFieldName };
                        metadata.Clear();
                        Dictionary <string, string> exifData = this.exifTool.FetchExifFrom(image.GetFilePath(this.fileDatabase.FolderPath), tags);
                        if (exifData.ContainsKey(tags[0]))
                        {
                            metadata.Add(tags[0], new Timelapse.Util.ImageMetadata(String.Empty, tags[0], exifData[tags[0]]));
                        }
                    }

                    if (this.ReadyToRefresh())
                    {
                        percentDone = Convert.ToInt32(imageIndex / totalFiles * 100.0);
                        this.Progress.Report(new ProgressBarArguments(percentDone, String.Format("{0}/{1} images. Processing {2}", imageIndex, totalFiles, image.File), true, false));
                        Thread.Sleep(Constant.ThrottleValues.RenderingBackoffTime);  // Allows the UI thread to update every now and then
                    }

                    if (metadata.ContainsKey(this.metadataFieldName) == false)
                    {
                        keyValueList.Add(new KeyValuePair <string, string>(image.File, String.Format("Data field unchanged - file is missing metatdata {0} ", this.metadataFieldName)));

                        // System.Diagnostics.Debug.Print(String.Format("{0}: No metadata", image.File));
                        continue;
                    }
                    metadataUpdateCount++;
                    string metadataValue = metadata[this.metadataFieldName].Value;
                    ColumnTuplesWithWhere imageUpdate;
                    if (DateTimeHandler.TryParseMetadataDateTaken(metadataValue, imageSetTimeZone, out DateTimeOffset metadataDateTime))
                    {
                        image.SetDateTimeOffset(metadataDateTime);
                        imageUpdate = image.GetDateTimeColumnTuples();
                        keyValueList.Add(new KeyValuePair <string, string>(image.File, metadataValue));
                    }
                    else
                    {
                        keyValueList.Add(new KeyValuePair <string, string>(image.File, String.Format("Data field unchanged - '{0}' is not a valid date/time.", metadataValue)));
                        continue;
                    }
                    imagesToUpdate.Add(imageUpdate);
                }
                this.IsAnyDataUpdated = true;
                this.Progress.Report(new ProgressBarArguments(100, String.Format("Writing metadata for the {0}/{1} files that contain this metadata field. Please wait...", metadataUpdateCount, totalFiles), false, true));
                Thread.Sleep(Constant.ThrottleValues.RenderingBackoffTime);  // Allows the UI thread to update every now and then
                this.fileDatabase.UpdateFiles(imagesToUpdate);
                return keyValueList;
            }, this.Token).ConfigureAwait(true));
        }
Exemple #3
0
        // Populate the database with the metadata for the selected note field
        private async Task <ObservableCollection <KeyValuePair <string, string> > > PopulateAsync(bool?metadataExtractorRBIsChecked)
        {
            // This list will hold key / value pairs that will be bound to the datagrid feedback,
            // which is the way to make those pairs appear in the data grid during background worker progress updates
            ObservableCollection <KeyValuePair <string, string> > keyValueList = new ObservableCollection <KeyValuePair <string, string> >();

            return(await Task.Run(() =>
            {
                // For each row in the database, get the image filename and try to extract the chosen metadata value.
                // If we can't decide if we want to leave the data field alone or to clear it depending on the state of the isClearIfNoMetadata (set via the checkbox)
                // Report progress as needed.
                // This tuple list will hold the id, key and value that we will want to update in the database
                string dataLabelToUpdate = this.dataLabelByLabel[this.dataFieldLabel];
                List <ColumnTuplesWithWhere> imagesToUpdate = new List <ColumnTuplesWithWhere>();
                TimeZoneInfo imageSetTimeZone = this.fileDatabase.ImageSet.GetSystemTimeZone();
                int percentDone = 0;

                double totalImages = this.fileDatabase.CountAllCurrentlySelectedFiles;
                Dictionary <string, ImageMetadata> metadata = new Dictionary <string, ImageMetadata>();
                for (int imageIndex = 0; imageIndex < totalImages; ++imageIndex)
                {
                    // Provide feedback if the operation was cancelled during the database update
                    if (Token.IsCancellationRequested == true)
                    {
                        keyValueList.Clear();
                        keyValueList.Add(new KeyValuePair <string, string>("Cancelled", "No changes were made"));
                        return keyValueList;
                    }

                    ImageRow image = this.fileDatabase.FileTable[imageIndex];
                    if (metadataExtractorRBIsChecked == true)
                    {   // MetadataExtractor specific code
                        metadata = ImageMetadataDictionary.LoadMetadata(image.GetFilePath(this.fileDatabase.FolderPath));
                    }
                    else
                    {
                        // ExifTool specific code - note that we transform results into the same dictionary structure used by the MetadataExtractor
                        string[] tags = { this.metadataFieldName };
                        metadata.Clear();
                        Dictionary <string, string> exifData = this.exifTool.FetchExifFrom(image.GetFilePath(this.fileDatabase.FolderPath), tags);
                        if (exifData.ContainsKey(tags[0]))
                        {
                            metadata.Add(tags[0], new Timelapse.Util.ImageMetadata(String.Empty, tags[0], exifData[tags[0]]));
                        }
                    }

                    if (this.ReadyToRefresh())
                    {
                        percentDone = Convert.ToInt32(imageIndex / totalImages * 100.0);
                        this.Progress.Report(new ProgressBarArguments(percentDone, String.Format("{0}/{1} images. Processing {2}", imageIndex, totalImages, image.File), true, false));
                        Thread.Sleep(Constant.ThrottleValues.RenderingBackoffTime);  // Allows the UI thread to update every now and then
                    }

                    if (metadata.ContainsKey(this.metadataFieldName) == false)
                    {
                        if (this.clearIfNoMetadata)
                        {
                            // Clear the data field if there is no metadata...
                            if (dataLabelToUpdate == Constant.DatabaseColumn.DateTime)
                            {
                                image.SetDateTimeOffsetFromFileInfo(this.fileDatabase.FolderPath);
                                imagesToUpdate.Add(image.GetDateTimeColumnTuples());
                                keyValueList.Add(new KeyValuePair <string, string>(image.File, "No metadata found - date/time reread from file"));
                            }
                            else
                            {
                                List <ColumnTuple> clearField = new List <ColumnTuple>()
                                {
                                    new ColumnTuple(this.dataLabelByLabel[this.dataFieldLabel], String.Empty)
                                };
                                imagesToUpdate.Add(new ColumnTuplesWithWhere(clearField, image.ID));
                                keyValueList.Add(new KeyValuePair <string, string>(image.File, "No metadata found - data field is cleared"));
                            }
                        }
                        else
                        {
                            keyValueList.Add(new KeyValuePair <string, string>(image.File, "No metadata found - data field remains unaltered"));
                        }

                        continue;
                    }

                    string metadataValue = metadata[this.metadataFieldName].Value;
                    ColumnTuplesWithWhere imageUpdate;
                    if (dataLabelToUpdate == Constant.DatabaseColumn.DateTime)
                    {
                        if (DateTimeHandler.TryParseMetadataDateTaken(metadataValue, imageSetTimeZone, out DateTimeOffset metadataDateTime))
                        {
                            image.SetDateTimeOffset(metadataDateTime);
                            imageUpdate = image.GetDateTimeColumnTuples();
                            keyValueList.Add(new KeyValuePair <string, string>(image.File, metadataValue));
                        }
                        else
                        {
                            keyValueList.Add(new KeyValuePair <string, string>(image.File, String.Format("'{0}' - data field remains unaltered - not a valid date/time.", metadataValue)));
                            continue;
                        }
                    }
                    else
                    {
                        imageUpdate = new ColumnTuplesWithWhere(new List <ColumnTuple>()
                        {
                            new ColumnTuple(dataLabelToUpdate, metadataValue)
                        }, image.ID);
                        keyValueList.Add(new KeyValuePair <string, string>(image.File, metadataValue));
                    }
                    imagesToUpdate.Add(imageUpdate);
                }
                this.IsAnyDataUpdated = true;
                this.Progress.Report(new ProgressBarArguments(100, String.Format("Writing metadata for {0} files. Please wait...", totalImages), false, true));
                Thread.Sleep(Constant.ThrottleValues.RenderingBackoffTime);  // Allows the UI thread to update every now and then
                this.fileDatabase.UpdateFiles(imagesToUpdate);
                return keyValueList;
            }, this.Token).ConfigureAwait(true));
        }