浏览代码

Add "Remove Image Data" feature with translations and command handling #211

Ruben 3 月之前
父节点
当前提交
3047e84f32

+ 10 - 1
src/PicView.Avalonia/Views/ImageInfoView.axaml

@@ -120,6 +120,16 @@
                 </MenuItem.Icon>
             </MenuItem>
 
+            <!--  Remove image data  -->
+            <MenuItem
+                Command="{CompiledBinding Exif.RemoveImageDataCommand}"
+                CommandParameter="{CompiledBinding PicViewer.FileInfo.Value,
+                                                   FallbackValue=''}"
+                Header="{CompiledBinding Translation.RemoveImageData.Value,
+                                         Mode=OneWay}"
+                IsEnabled="{CompiledBinding PicViewer.FileInfo.Value,
+                                            Converter={x:Static ObjectConverters.IsNotNull}}" />
+
             <!--  Set as wallpaper  -->
             <MenuItem
                 Header="{CompiledBinding Translation.SetAsWallpaper.Value,
@@ -194,7 +204,6 @@
                 </MenuItem>
 
 
-
                 <!--  Set as wallpaper centered  -->
                 <MenuItem
                     Command="{CompiledBinding Tools.SetAsWallpaperCenteredCommand}"

+ 46 - 15
src/PicView.Avalonia/Views/ImageInfoView.axaml.cs

@@ -9,6 +9,7 @@ using PicView.Avalonia.Resizing;
 using PicView.Avalonia.UI;
 using PicView.Avalonia.ViewModels;
 using PicView.Core.Extensions;
+using PicView.Core.FileHandling;
 using PicView.Core.Titles;
 using R3;
 
@@ -17,6 +18,7 @@ namespace PicView.Avalonia.Views;
 public partial class ImageInfoView : UserControl
 {
     private readonly CompositeDisposable _disposables = new();
+
     public ImageInfoView()
     {
         InitializeComponent();
@@ -67,19 +69,11 @@ public partial class ImageInfoView : UserControl
                 return;
             }
 
-            Observable.EveryValueChanged(vm.PicViewer.FileInfo, x => x.Value, UIHelper.GetFrameProvider).Subscribe(x =>
-            {
-                ExifHandling.UpdateExifValues(vm);
-                if (DirectoryNameTextBox.Text != x.DirectoryName)
-                {
-                    DirectoryNameTextBox.Text = x.DirectoryName;
-                }
-                FileSizeBox.Text = vm.PicViewer.FileInfo?.CurrentValue?.Length.GetReadableFileSize();
-                ConversionHelper.DetermineIfOptimizeImageShouldBeEnabled(vm);
-                GoogleLinkButton.IsEnabled = !string.IsNullOrWhiteSpace(vm.Exif.GoogleLink.CurrentValue);
-                BingLinkButton.IsEnabled = !string.IsNullOrWhiteSpace(vm.Exif.BingLink.CurrentValue);
-            }).AddTo(_disposables);
-            
+            Observable.EveryValueChanged(vm.PicViewer.FileInfo, x => x.Value, UIHelper.GetFrameProvider)
+                .Subscribe(UpdateValues).AddTo(_disposables);
+
+            vm.Exif.RemoveImageDataCommand.SubscribeAwait(RemoveValues);
+
             ResetButton.Click += (_, _) =>
             {
                 PixelWidthTextBox.Text = vm.PicViewer.PixelWidth.ToString();
@@ -161,6 +155,40 @@ public partial class ImageInfoView : UserControl
         };
     }
 
+    private async ValueTask RemoveValues(FileInfo arg1, CancellationToken arg2)
+    {
+        if (DataContext is not MainViewModel vm)
+        {
+            return;
+        }
+        
+        while (FileHelper.IsFileInUse(vm.PicViewer.FileInfo.CurrentValue.FullName))
+        {
+            await Task.Delay(100, arg2).ConfigureAwait(false);
+        }
+        
+        UpdateValues(arg1);
+    }
+
+    private void UpdateValues(FileInfo? fileInfo)
+    {
+        if (DataContext is not MainViewModel vm)
+        {
+            return;
+        }
+
+        ExifHandling.UpdateExifValues(vm);
+        if (DirectoryNameTextBox.Text != fileInfo.DirectoryName)
+        {
+            DirectoryNameTextBox.Text = fileInfo.DirectoryName;
+        }
+
+        FileSizeBox.Text = vm.PicViewer.FileInfo?.CurrentValue?.Length.GetReadableFileSize();
+        ConversionHelper.DetermineIfOptimizeImageShouldBeEnabled(vm);
+        GoogleLinkButton.IsEnabled = !string.IsNullOrWhiteSpace(vm.Exif.GoogleLink.CurrentValue);
+        BingLinkButton.IsEnabled = !string.IsNullOrWhiteSpace(vm.Exif.BingLink.CurrentValue);
+    }
+
     private async Task SendToImageSaver(string? location, string destination, string? width, string? height,
         string ext)
     {
@@ -168,8 +196,10 @@ public partial class ImageInfoView : UserControl
         {
             return;
         }
+
         var sameFile = destination.Equals(location, StringComparison.OrdinalIgnoreCase);
-        await SaveImageHandler.SaveImageWithPossibleNavigation(DataContext as MainViewModel, location, destination,  sameFile, ext, widthValue, heightValue,
+        await SaveImageHandler.SaveImageWithPossibleNavigation(DataContext as MainViewModel, location, destination,
+            sameFile, ext, widthValue, heightValue,
             null, null, true);
     }
 
@@ -206,7 +236,8 @@ public partial class ImageInfoView : UserControl
             return;
         }
 
-        var printSizes = AspectRatioHelper.GetPrintSizes(width, height, vm.Exif.DpiX.CurrentValue, vm.Exif.DpiY.CurrentValue);
+        var printSizes =
+            AspectRatioHelper.GetPrintSizes(width, height, vm.Exif.DpiX.CurrentValue, vm.Exif.DpiY.CurrentValue);
         PrintSizeInchTextBox.Text = printSizes.PrintSizeInch;
         PrintSizeCmTextBox.Text = printSizes.PrintSizeCm;
         SizeMpTextBox.Text = printSizes.SizeMp;

+ 1 - 0
src/PicView.Core/Config/Languages/da.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Seneste filer",
   "RedEyeReduction": "Røde øjne reduktion",
   "Reload": "Genindlæs",
+  "RemoveImageData": "Fjern billedmetadata",
   "RemoveStarRating": "Fjern vurdering",
   "RenameFile": "Omdøb fil",
   "Reset": "Nulstil",

+ 1 - 0
src/PicView.Core/Config/Languages/de.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Zuletzt geöffnete Dateien",
   "RedEyeReduction": "Rote-Augen-Reduktion",
   "Reload": "Neu laden",
+  "RemoveImageData": "Bildmetadaten entfernen",
   "RemoveStarRating": "Bewertung entfernen",
   "RenameFile": "Datei umbenennen",
   "Reset": "Zurücksetzen",

+ 1 - 0
src/PicView.Core/Config/Languages/en.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Recent files",
   "RedEyeReduction": "Red eye reduction",
   "Reload": "Reload",
+  "RemoveImageData": "Remove image metadata",
   "RemoveStarRating": "Remove rating",
   "RenameFile": "Rename file",
   "Reset": "Reset",

+ 1 - 0
src/PicView.Core/Config/Languages/es.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Archivos recientes",
   "RedEyeReduction": "Reducción de ojos rojos",
   "Reload": "Recargar",
+  "RemoveImageData": "Eliminar metadatos de la imagen",
   "RemoveStarRating": "Eliminar clasificación",
   "RenameFile": "Renombrar archivo",
   "Reset": "Restablecer",

+ 1 - 0
src/PicView.Core/Config/Languages/fr.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Fichiers récents",
   "RedEyeReduction": "Réduction des yeux rouges",
   "Reload": "Recharger",
+  "RemoveImageData": "Supprimer les métadonnées de l'image",
   "RemoveStarRating": "Supprimer la note",
   "RenameFile": "Renommer le fichier",
   "Reset": "Réinitialiser",

+ 1 - 0
src/PicView.Core/Config/Languages/he.json

@@ -269,6 +269,7 @@
   "RecentFiles": "קבצים אחרונים",
   "RedEyeReduction": "הפחתת עיניים אדומות",
   "Reload": "טען מחדש",
+  "RemoveImageData": "הסר את נתוני המטא-מידע של התמונה",
   "RemoveStarRating": "הסר דירוג כוכבים",
   "RenameFile": "שנה שם קובץ",
   "Reset": "אפס",

+ 1 - 0
src/PicView.Core/Config/Languages/hu.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Legutóbbi fájlok",
   "RedEyeReduction": "Vörös szem hatás csökkentése",
   "Reload": "Újratöltés",
+  "RemoveImageData": "Kép metaadatok eltávolítása",
   "RemoveStarRating": "Értékelés eltávolítása",
   "RenameFile": "Fájl átnevezése",
   "Reset": "Visszaállítás",

+ 1 - 0
src/PicView.Core/Config/Languages/it.json

@@ -269,6 +269,7 @@
   "RecentFiles": "File recenti",
   "RedEyeReduction": "Riduzione occhi rossi",
   "Reload": "Ricaricare",
+  "RemoveImageData": "Rimuovi i metadati dell'immagine",
   "RemoveStarRating": "Rimuovi il rating",
   "RenameFile": "Rinomina il file",
   "Reset": "Reimposta",

+ 1 - 0
src/PicView.Core/Config/Languages/ja.json

@@ -269,6 +269,7 @@
   "RecentFiles": "最近使ったファイル",
   "RedEyeReduction": "赤目軽減",
   "Reload": "再読み込み",
+  "RemoveImageData": "画像のメタデータを削除",
   "RemoveStarRating": "評価を削除",
   "RenameFile": "ファイルの名前変更",
   "Reset": "リセット",

+ 1 - 0
src/PicView.Core/Config/Languages/ko.json

@@ -269,6 +269,7 @@
   "RecentFiles": "최근 파일",
   "RedEyeReduction": "적목 감소",
   "Reload": "다시 불러오기",
+  "RemoveImageData": "이미지 메타데이터 제거",
   "RemoveStarRating": "등급 제거",
   "RenameFile": "파일 이름 바꾸기",
   "Reset": "재설정",

+ 1 - 0
src/PicView.Core/Config/Languages/nl.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Recente bestanden",
   "RedEyeReduction": "Rode ogen reductie",
   "Reload": "Herladen",
+  "RemoveImageData": "Verwijder afbeeldingsmetadata",
   "RemoveStarRating": "Beoordeling verwijderen",
   "RenameFile": "Bestand hernoemen",
   "Reset": "Resetten",

+ 1 - 0
src/PicView.Core/Config/Languages/pl.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Ostatnie pliki",
   "RedEyeReduction": "Redukcja efektu czerwonych oczu",
   "Reload": "Przeładuj",
+  "RemoveImageData": "Usuń metadane obrazu",
   "RemoveStarRating": "Usuń ocenę",
   "RenameFile": "Zmień nazwę",
   "Reset": "Zresetuj",

+ 1 - 0
src/PicView.Core/Config/Languages/pt-br.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Arquivos recentes",
   "RedEyeReduction": "Redução do olho vermelho",
   "Reload": "Recarregar",
+  "RemoveImageData": "Remover metadados da imagem",
   "RemoveStarRating": "Remover classificação",
   "RenameFile": "Renomear arquivo",
   "Reset": "Redefinir",

+ 1 - 0
src/PicView.Core/Config/Languages/ro.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Fișiere recente",
   "RedEyeReduction": "Reducere ochi roșii",
   "Reload": "Reîncărcare",
+  "RemoveImageData": "Eliminați metadatele imaginii",
   "RemoveStarRating": "Eliminare evaluare",
   "RenameFile": "Redenumire fișier",
   "Reset": "Resetează",

+ 1 - 0
src/PicView.Core/Config/Languages/ru.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Недавние файлы",
   "RedEyeReduction": "Уменьшение эффекта красных глаз",
   "Reload": "Перезагрузить",
+  "RemoveImageData": "Удалить метаданные изображения",
   "RemoveStarRating": "Убрать рейтинг",
   "RenameFile": "Переименовать файл",
   "Reset": "Сбросить",

+ 1 - 0
src/PicView.Core/Config/Languages/sv.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Senaste filer",
   "RedEyeReduction": "Ta bort röda ögon",
   "Reload": "Hämta igen",
+  "RemoveImageData": "Ta bort bildmetadata",
   "RemoveStarRating": "Ta bort omdöme",
   "RenameFile": "Ändra filnamn",
   "Reset": "Återställ",

+ 1 - 0
src/PicView.Core/Config/Languages/tr.json

@@ -269,6 +269,7 @@
   "RecentFiles": "Son dosyalar",
   "RedEyeReduction": "Kırmızı göz azaltma",
   "Reload": "Yeniden yükle",
+  "RemoveImageData": "Görüntü meta verilerini kaldır",
   "RemoveStarRating": "Derecelendirmeyi kaldır",
   "RenameFile": "Dosyayı yeniden adlandır",
   "Reset": "Sıfırla",

+ 1 - 0
src/PicView.Core/Config/Languages/zh-CN.json

@@ -269,6 +269,7 @@
   "RecentFiles": "最近文件",
   "RedEyeReduction": "减少红眼",
   "Reload": "重新载入",
+  "RemoveImageData": "移除图像元数据",
   "RemoveStarRating": "移除评分",
   "RenameFile": "重命名文件",
   "Reset": "重置",

+ 1 - 0
src/PicView.Core/Config/Languages/zh-TW.json

@@ -269,6 +269,7 @@
   "RecentFiles": "最近檔案",
   "RedEyeReduction": "紅眼縮減",
   "Reload": "重新載入",
+  "RemoveImageData": "移除影像元資料",
   "RemoveStarRating": "移除評分",
   "RenameFile": "重新命名檔案",
   "Reset": "重設",

+ 104 - 26
src/PicView.Core/ImageDecoding/EXIFHelper.cs

@@ -3,6 +3,7 @@ using System.Globalization;
 using System.Text;
 using ImageMagick;
 using PicView.Core.DebugTools;
+using PicView.Core.FileHandling;
 using PicView.Core.Localization;
 
 namespace PicView.Core.ImageDecoding;
@@ -31,6 +32,29 @@ public static class EXIFHelper
         Rotated270Cw = 8
     }
 
+    public static async Task<bool> RemoveExifProfile(FileInfo fileInfo)
+    {
+        try
+        {
+            using var magickImage = new MagickImage(fileInfo);
+            var profile = magickImage.GetExifProfile();
+            if (profile is null)
+            {
+                return false;
+            }
+
+            magickImage.RemoveProfile(profile);
+            await using var fileStream = FileHelper.GetOptimizedFileStream(fileInfo, true);
+            await magickImage.WriteAsync(fileStream);
+            return true;
+        }
+        catch (Exception e)
+        {
+            DebugHelper.LogDebug(nameof(EXIFHelper), nameof(RemoveExifProfile), e);
+            return false;
+        }
+    }
+
     public static EXIFOrientation GetImageOrientation(MagickImage magickImage)
     {
         var profile = magickImage.GetExifProfile();
@@ -55,14 +79,14 @@ public static class EXIFHelper
             _ => EXIFOrientation.None
         };
     }
-    
+
     public static EXIFOrientation GetImageOrientation(string filePath)
     {
         using var magickImage = new MagickImage();
         magickImage.Ping(filePath);
         return GetImageOrientation(magickImage);
     }
-    
+
     public static EXIFOrientation GetImageOrientation(FileInfo fileInfo)
     {
         return GetImageOrientation(fileInfo.FullName);
@@ -72,10 +96,15 @@ public static class EXIFHelper
     public static bool SetEXIFRating(string filePath, ushort rating)
     {
         if (!File.Exists(filePath))
+        {
             throw new FileNotFoundException();
+        }
 
         if (rating > 5)
+        {
             throw new ArgumentOutOfRangeException(nameof(rating));
+        }
+
         try
         {
             using var image = new MagickImage(filePath);
@@ -85,10 +114,14 @@ public static class EXIFHelper
                 profile = new ExifProfile(filePath);
                 // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                 if (profile is null || image is null)
+                {
                     throw new Exception("Failed to create EXIF profile or image.");
+                }
             }
             else if (image is null)
+            {
                 throw new Exception("Failed to create image.");
+            }
 
             profile.SetValue(ExifTag.Rating, rating);
             image.SetProfile(profile);
@@ -97,9 +130,10 @@ public static class EXIFHelper
         }
         catch (Exception e)
         {
-            DebugHelper.LogDebug(nameof(EXIFHelper),  nameof(SetEXIFRating), e);
+            DebugHelper.LogDebug(nameof(EXIFHelper), nameof(SetEXIFRating), e);
             return false;
         }
+
         return true;
     }
 
@@ -124,7 +158,8 @@ public static class EXIFHelper
             profile?.GetValue(ExifTag.DateTimeOriginal)?.Value ??
             profile?.GetValue(ExifTag.DateTimeDigitized)?.Value ?? string.Empty;
         if (!string.IsNullOrEmpty(getDateTaken) &&
-            DateTime.TryParseExact(getDateTaken, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out var formattedDateTime))
+            DateTime.TryParseExact(getDateTaken, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture,
+                DateTimeStyles.None, out var formattedDateTime))
         {
             return formattedDateTime.ToString(CultureInfo.CurrentCulture);
         }
@@ -144,6 +179,7 @@ public static class EXIFHelper
         {
             return null;
         }
+
         var gpsLong = profile.GetValue(ExifTag.GPSLongitude);
         var gpsLongRef = profile.GetValue(ExifTag.GPSLongitudeRef);
         var gpsLatitude = profile.GetValue(ExifTag.GPSLatitude);
@@ -155,14 +191,18 @@ public static class EXIFHelper
             return null;
         }
 
-        var latitudeValue = GetCoordinates(gpsLatitudeRef.ToString(), gpsLatitude.Value).ToString(CultureInfo.InvariantCulture);
-        var longitudeValue = GetCoordinates(gpsLongRef.ToString(), gpsLong.Value).ToString(CultureInfo.InvariantCulture);
+        var latitudeValue = GetCoordinates(gpsLatitudeRef.ToString(), gpsLatitude.Value)
+            .ToString(CultureInfo.InvariantCulture);
+        var longitudeValue =
+            GetCoordinates(gpsLongRef.ToString(), gpsLong.Value).ToString(CultureInfo.InvariantCulture);
 
         var googleLink = $"https://www.google.com/maps/search/?api=1&query={latitudeValue},{longitudeValue}";
         var bingLink = $"https://bing.com/maps/default.aspx?cp={latitudeValue}~{longitudeValue}&lvl=16.0&sty=c";
 
-        var latitudeString = $"{gpsLatitude.Value[0]}\u00b0{gpsLatitude.Value[1]}'{gpsLatitude.Value[2].ToDouble():0.##}\"{gpsLatitudeRef}";
-        var longitudeString = $"{gpsLong.Value[0]}\u00b0{gpsLong.Value[1]}'{gpsLong.Value[2].ToDouble():0.##}\"{gpsLongRef}";
+        var latitudeString =
+            $"{gpsLatitude.Value[0]}\u00b0{gpsLatitude.Value[1]}'{gpsLatitude.Value[2].ToDouble():0.##}\"{gpsLatitudeRef}";
+        var longitudeString =
+            $"{gpsLong.Value[0]}\u00b0{gpsLong.Value[1]}'{gpsLong.Value[2].ToDouble():0.##}\"{gpsLongRef}";
 
         return [latitudeString, longitudeString, googleLink, bingLink];
 
@@ -179,7 +219,10 @@ public static class EXIFHelper
 
             var coordinate = degrees + minutes / 60d + seconds / 3600d;
             if (gpsRef is "S" or "W")
+            {
                 coordinate *= -1;
+            }
+
             return coordinate;
         }
     }
@@ -191,6 +234,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return colorSpace switch
         {
             1 => "sRGB",
@@ -207,6 +251,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return exposureProgram switch
         {
             0 => TranslationManager.GetTranslation("NotDefined"),
@@ -240,6 +285,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return isoSpeed.ToString() ?? string.Empty;
     }
 
@@ -250,6 +296,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return saturation switch
         {
             0 => TranslationManager.GetTranslation("Normal"),
@@ -266,6 +313,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return contrast switch
         {
             0 => TranslationManager.GetTranslation("Normal"),
@@ -282,6 +330,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return sharpness switch
         {
             0 => TranslationManager.GetTranslation("Normal"),
@@ -298,6 +347,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return whiteBalance switch
         {
             0 => TranslationManager.GetTranslation("Auto"),
@@ -313,6 +363,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return resolutionUnit switch
         {
             1 => TranslationManager.GetTranslation("None"),
@@ -345,52 +396,74 @@ public static class EXIFHelper
                 return TranslationManager.GetTranslation("FlashFired");
 
             case 5:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("StrobeReturnLightDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightDetected");
 
             case 7:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
 
             case 15:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("StrobeReturnLightDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightDetected");
 
             case 16:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
 
             case 29:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("StrobeReturnLightDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightDetected");
 
             case 31:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
 
             case 65:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("RedEyeReduction");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction");
 
             case 69:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("RedEyeReduction") + ", " + TranslationManager.GetTranslation("StrobeReturnLightDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightDetected");
 
             case 71:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("RedEyeReduction") + ", " + TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
 
             case 73:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("RedEyeReduction");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction");
 
             case 77:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("RedEyeReduction") + ", " + TranslationManager.GetTranslation("StrobeReturnLightDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightDetected");
 
             case 79:
-                return TranslationManager.GetTranslation("Unknown") + ", " + TranslationManager.GetTranslation("RedEyeReduction") + ", " + TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
+                return TranslationManager.GetTranslation("Unknown") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
 
             case 89:
-                return TranslationManager.GetTranslation("FlashDidNotFire") + ", " + TranslationManager.GetTranslation("RedEyeReduction");
+                return TranslationManager.GetTranslation("FlashDidNotFire") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction");
 
             case 93:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("RedEyeReduction");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction");
 
             case 95:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("RedEyeReduction") + ", " + TranslationManager.GetTranslation("StrobeReturnLightDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightDetected");
 
             case 97:
-                return TranslationManager.GetTranslation("FlashFired") + ", " + TranslationManager.GetTranslation("RedEyeReduction") + ", " + TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
+                return TranslationManager.GetTranslation("FlashFired") + ", " +
+                       TranslationManager.GetTranslation("RedEyeReduction") + ", " +
+                       TranslationManager.GetTranslation("StrobeReturnLightNotDetected");
 
             default: return string.Empty;
         }
@@ -403,6 +476,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return lightSource switch
         {
             0 => TranslationManager.GetTranslation("Unknown"),
@@ -437,6 +511,7 @@ public static class EXIFHelper
         {
             return string.Empty;
         }
+
         return photometricInterpretation switch
         {
             0 => "WhiteIsZero",
@@ -473,6 +548,7 @@ public static class EXIFHelper
         {
             return title;
         }
+
         var titleTag = profile?.GetValue(ExifTag.ImageDescription)?.Value;
         return titleTag ?? string.Empty;
     }
@@ -485,10 +561,11 @@ public static class EXIFHelper
         {
             return subject;
         }
+
         var subjectTag = profile?.GetValue(ExifTag.XPSubject)?.Value;
         return subjectTag?.GetValue(0)?.ToString() ?? string.Empty;
     }
-    
+
     public static string GetUserComment(IExifProfile? profile)
     {
         var commentBytes = profile?.GetValue(ExifTag.UserComment)?.Value;
@@ -498,6 +575,7 @@ public static class EXIFHelper
             return string.Empty;
         }
 
-        return decodedComment.StartsWith("UNICODE") ? decodedComment.Replace("UNICODE", "") : decodedComment;;
+        return decodedComment.StartsWith("UNICODE") ? decodedComment.Replace("UNICODE", "") : decodedComment;
+        ;
     }
 }

+ 3 - 2
src/PicView.Core/Localization/LanguageModel.cs

@@ -70,7 +70,7 @@ public class LanguageModel
     public string? ColorPickerToolTooltip { get; set; }
     public string? ColorRepresentation { get; set; }
     public string? ColorTone { get; set; }
-    public string? Comment {get; set; }
+    public string? Comment { get; set; }
     public string? CompressedBitsPixel { get; set; }
     public string? Compression { get; set; }
     public string? ConstrainBackgroundToImage { get; set; }
@@ -282,6 +282,7 @@ public class LanguageModel
     public string? RecentFiles { get; set; }
     public string? RedEyeReduction { get; set; }
     public string? Reload { get; set; }
+    public string? RemoveImageData { get; set; }
     public string? RemoveStarRating { get; set; }
     public string? RenameFile { get; set; }
     public string? Reset { get; set; }
@@ -398,7 +399,7 @@ public class LanguageModel
     public string? WidthAndHeight { get; set; }
     public string? Window { get; set; }
     public string? WindowManagement { get; set; }
-    public string? WindowMargin{ get; set; }
+    public string? WindowMargin { get; set; }
     public string? WindowScaling { get; set; }
     public string? Zoom { get; set; }
     public string? ZoomIn { get; set; }

+ 104 - 97
src/PicView.Core/ViewModels/ExifViewModel.cs

@@ -16,116 +16,29 @@ public class ExifViewModel : IDisposable
         SetExifRating2Command = new ReactiveCommand<string>(Set2Star);
         SetExifRating3Command = new ReactiveCommand<string>(Set3Star);
         SetExifRating4Command = new ReactiveCommand<string>(Set4Star);
-        SetExifRating5Command = new ReactiveCommand<string>(Set5Star);            
-    }
-    
-    private void Set0Star(string value)
-    {
-        EXIFHelper.SetEXIFRating(value, 0);
-        ExifRating.Value = 0;
-    }
-
-    private void Set1Star(string value)
-    {
-        EXIFHelper.SetEXIFRating(value, 1);
-        ExifRating.Value = 1;
-    }
-
-    private void Set2Star(string value)
-    {
-        EXIFHelper.SetEXIFRating(value, 2);
-        ExifRating.Value = 2;
+        SetExifRating5Command = new ReactiveCommand<string>(Set5Star);
     }
 
-    private void Set3Star(string value)
+    public ReactiveCommand<FileInfo> RemoveImageDataCommand { get; } = new(async (value, _) =>
     {
-        EXIFHelper.SetEXIFRating(value, 3);
-        ExifRating.Value = 3;
-    }
+        await EXIFHelper.RemoveExifProfile(value);
+    });
 
-    private void Set4Star(string value)
-    {
-        EXIFHelper.SetEXIFRating(value, 4);
-        ExifRating.Value = 4;
-    }
-
-    private void Set5Star(string value)
-    {
-        EXIFHelper.SetEXIFRating(value, 5);
-        ExifRating.Value = 5;
-    }
-
-    public void Dispose()
-    {
-        Disposable.Dispose(
-            DpiX,
-            DpiY,
-            PrintSizeCm,
-            PrintSizeCm,
-            SizeMp,
-            ResolutionUnit,
-            BitDepth,
-            AspectRatio,
-            Latitude,
-            Longitude,
-            Altitude,
-            GoogleLink,
-            BingLink,
-            Authors,
-            DateTaken,
-            Copyright,
-            Title,
-            Subject,
-            Software,
-            ResolutionUnit,
-            ColorRepresentation,
-            Compression,
-            Comment,
-            CompressedBitsPixel,
-            CameraMaker,
-            CameraModel,
-            ExposureProgram,
-            ExposureTime,
-            ExposureBias,
-            FNumber,
-            MaxAperture,
-            DigitalZoom,
-            FocalLength35Mm,
-            FocalLength,
-            ISOSpeed,
-            MeteringMode,
-            Contrast,
-            Saturation,
-            Brightness,
-            Sharpness,
-            WhiteBalance,
-            FlashMode,
-            FlashEnergy,
-            LightSource,
-            PhotometricInterpretation,
-            Orientation,
-            ExifVersion,
-            LensMaker,
-            LensModel);
-    }
     public ReactiveCommand? OpenGoogleLinkCommand { get; }
     public ReactiveCommand? OpenBingLinkCommand { get; }
-    
+
     public ReactiveCommand<string>? SetExifRating0Command { get; set; }
     public ReactiveCommand<string>? SetExifRating1Command { get; set; }
     public ReactiveCommand<string>? SetExifRating2Command { get; set; }
     public ReactiveCommand<string>? SetExifRating3Command { get; set; }
     public ReactiveCommand<string>? SetExifRating4Command { get; set; }
     public ReactiveCommand<string>? SetExifRating5Command { get; set; }
-    
-    public void OpenGoogleMaps(Unit unit) => ProcessHelper.OpenLink(GoogleLink.CurrentValue);
-    public void OpenBingMaps(Unit unit) => ProcessHelper.OpenLink(BingLink.CurrentValue);
-    
+
     public BindableReactiveProperty<uint> ExifRating { get; } = new();
     public BindableReactiveProperty<double> DpiX { get; } = new();
 
     public BindableReactiveProperty<double> DpiY { get; } = new();
-    
+
     public BindableReactiveProperty<string?> PrintSizeInch { get; } = new();
 
     public BindableReactiveProperty<string?> PrintSizeCm { get; } = new();
@@ -165,7 +78,7 @@ public class ExifViewModel : IDisposable
     public BindableReactiveProperty<string?> ColorRepresentation { get; } = new();
 
     public BindableReactiveProperty<string?> Compression { get; } = new();
-    
+
     public BindableReactiveProperty<string?> Comment { get; } = new();
 
     public BindableReactiveProperty<string?> CompressedBitsPixel { get; } = new();
@@ -219,5 +132,99 @@ public class ExifViewModel : IDisposable
 
     public BindableReactiveProperty<string?> LensModel { get; } = new();
 
-    public BindableReactiveProperty<string?> LensMaker { get; } = new();    
-}
+    public BindableReactiveProperty<string?> LensMaker { get; } = new();
+
+    public void Dispose()
+    {
+        Disposable.Dispose(
+            DpiX,
+            DpiY,
+            PrintSizeCm,
+            PrintSizeCm,
+            SizeMp,
+            ResolutionUnit,
+            BitDepth,
+            AspectRatio,
+            Latitude,
+            Longitude,
+            Altitude,
+            GoogleLink,
+            BingLink,
+            Authors,
+            DateTaken,
+            Copyright,
+            Title,
+            Subject,
+            Software,
+            ResolutionUnit,
+            RemoveImageDataCommand,
+            ColorRepresentation,
+            Compression,
+            Comment,
+            CompressedBitsPixel,
+            CameraMaker,
+            CameraModel,
+            ExposureProgram,
+            ExposureTime,
+            ExposureBias,
+            FNumber,
+            MaxAperture,
+            DigitalZoom,
+            FocalLength35Mm,
+            FocalLength,
+            ISOSpeed,
+            MeteringMode,
+            Contrast,
+            Saturation,
+            Brightness,
+            Sharpness,
+            WhiteBalance,
+            FlashMode,
+            FlashEnergy,
+            LightSource,
+            PhotometricInterpretation,
+            Orientation,
+            ExifVersion,
+            LensMaker,
+            LensModel);
+    }
+
+    private void Set0Star(string value)
+    {
+        EXIFHelper.SetEXIFRating(value, 0);
+        ExifRating.Value = 0;
+    }
+
+    private void Set1Star(string value)
+    {
+        EXIFHelper.SetEXIFRating(value, 1);
+        ExifRating.Value = 1;
+    }
+
+    private void Set2Star(string value)
+    {
+        EXIFHelper.SetEXIFRating(value, 2);
+        ExifRating.Value = 2;
+    }
+
+    private void Set3Star(string value)
+    {
+        EXIFHelper.SetEXIFRating(value, 3);
+        ExifRating.Value = 3;
+    }
+
+    private void Set4Star(string value)
+    {
+        EXIFHelper.SetEXIFRating(value, 4);
+        ExifRating.Value = 4;
+    }
+
+    private void Set5Star(string value)
+    {
+        EXIFHelper.SetEXIFRating(value, 5);
+        ExifRating.Value = 5;
+    }
+
+    public void OpenGoogleMaps(Unit unit) => ProcessHelper.OpenLink(GoogleLink.CurrentValue);
+    public void OpenBingMaps(Unit unit) => ProcessHelper.OpenLink(BingLink.CurrentValue);
+}

+ 290 - 289
src/PicView.Core/ViewModels/TranslationViewModel.cs

@@ -1,5 +1,4 @@
-using PicView.Core.Extensions;
-using PicView.Core.Localization;
+using PicView.Core.Localization;
 using R3;
 
 namespace PicView.Core.ViewModels;
@@ -10,293 +9,294 @@ public class TranslationViewModel : IDisposable
     {
         Disposable.Dispose(File, SelectFile, OpenLastFile);
     }
-    
+
     public void UpdateLanguage()
     {
         var t = TranslationManager.Translation;
 
         File.Value = string.Concat(t.File[0].ToString().ToUpper(), t.File.AsSpan(1));
-        SelectFile .Value = t.OpenFileDialog;
-        OpenLastFile .Value = t.OpenLastFile;
-        Paste .Value = t.FilePaste;
-        Copy .Value = t.Copy;
-        Reload .Value = t.Reload;
-        Print .Value = t.Print;
-        DeleteFile .Value = t.DeleteFile;
-        PermanentlyDelete .Value = t.PermanentlyDelete;
-        Save .Value = t.Save;
-        CopyFile .Value = t.CopyFile;
-        NewWindow .Value = t.NewWindow;
-        Close .Value = t.Close;
-        CloseGallery .Value = t.CloseGallery;
-        Open .Value = t.Open;
-        OpenFileDialog .Value = t.OpenFileDialog;
-        ShowInFolder .Value = t.ShowInFolder;
-        OpenWith .Value = t.OpenWith;
-        RenameFile .Value = t.RenameFile;
-        DuplicateFile .Value = t.DuplicateFile;
-        RotateLeft .Value = t.RotateLeft;
-        RotateRight .Value = t.RotateRight;
-        Flip .Value = t.Flip;
-        UnFlip .Value = t.Unflip;
-        ShowBottomGallery .Value = t.ShowBottomGallery;
-        HideBottomGallery .Value = t.HideBottomGallery;
-        AutoFitWindow .Value = t.AutoFitWindow;
-        Stretch .Value = t.Stretch;
-        Crop .Value = t.Crop;
-        ResizeImage .Value = t.ResizeImage;
-        GoToImageAtSpecifiedIndex .Value = t.GoToImageAtSpecifiedIndex;
-        ToggleScroll .Value = t.ToggleScroll;
-        ScrollEnabled .Value = t.ScrollingEnabled;
-        ScrollDisabled .Value = t.ScrollingDisabled;
-        ScrollDirection .Value = t.ScrollDirection;
-        Reverse .Value = t.Reverse;
-        Forward .Value = t.Forward;
-        Slideshow .Value = t.Slideshow;
-        Settings .Value = t.Settings;
-        AboutWindow .Value = t.InfoWindow;
-        ImageInfo .Value = t.ImageInfo;
-        About .Value = t.About;
-        ShowAllSettingsWindow .Value = t.ShowAllSettingsWindow;
-        StayTopMost .Value = t.StayTopMost;
-        SearchSubdirectory .Value = t.SearchSubdirectory;
-        ToggleLooping .Value = t.ToggleLooping;
-        ApplicationShortcuts .Value = t.ApplicationShortcuts;
-        BatchResize .Value = t.BatchResize;
-        Effects .Value = t.Effects;
-        EffectsTooltip .Value = t.EffectsTooltip;
-        FileProperties .Value = t.FileProperties;
-        OptimizeImage .Value = t.OptimizeImage;
-        ImageInfo .Value = t.ImageInfo;
-        FileName .Value = t.FileName;
-        FileSize .Value = t.FileSize;
-        Folder .Value = t.Folder;
-        FullPath .Value = t.FullPath;
-        Created .Value = t.Created;
-        Modified .Value = t.Modified;
-        LastAccessTime .Value = t.LastAccessTime;
-        ConvertTo .Value = t.ConvertTo;
-        NoConversion .Value = t.NoConversion;
-        Resize .Value = t.Resize;
-        NoResize .Value = t.NoResize;
-        Apply .Value = t.Apply;
-        Cancel .Value = t.Cancel;
-        BitDepth .Value = t.BitDepth;
-        ReadAbleAspectRatio .Value = t.AspectRatio;
-        Width .Value = t.Width;
-        Height .Value = t.Height;
-        SizeMp .Value = t.SizeMp;
-        Resolution .Value = t.Resolution;
-        PrintSizeIn .Value = t.PrintSizeIn;
-        PrintSizeCm .Value = t.PrintSizeCm;
-        Centimeters .Value = t.Centimeters;
-        Inches .Value = t.Inches;
-        SizeTooltip .Value = t.SizeTooltip;
-        Latitude .Value = t.Latitude;
-        Longitude .Value = t.Longitude;
-        Altitude .Value = t.Altitude;
-        Authors .Value = t.Authors;
-        DateTaken .Value = t.DateTaken;
-        Copyright .Value = t.Copyright;
-        ResolutionUnit .Value = t.ResolutionUnit;
-        ColorRepresentation .Value = t.ColorRepresentation;
-        CompressedBitsPixel .Value = t.CompressedBitsPixel;
-        Compression .Value = t.Compression;
-        ExposureTime .Value = t.ExposureTime;
-        Title .Value = t.Title;
-        Subject .Value = t.Subject;
-        Software .Value = t.Software;
-        CameraMaker .Value = t.CameraMaker;
-        CameraModel .Value = t.CameraModel;
-        FocalLength .Value = t.FocalLength;
-        Fnumber .Value = t.FNumber;
-        Fstop .Value = t.Fstop;
-        MaxAperture .Value = t.MaxAperture;
-        ExposureBias .Value = t.ExposureBias;
-        ExposureProgram .Value = t.ExposureProgram;
-        DigitalZoom .Value = t.DigitalZoom;
-        ISOSpeed .Value = t.ISOSpeed;
-        FocalLength35mm .Value = t.FocalLength35mm;
-        MeteringMode .Value = t.MeteringMode;
-        Contrast .Value = t.Contrast;
-        Saturation .Value = t.Saturation;
-        Sharpness .Value = t.Sharpness;
-        WhiteBalance .Value = t.WhiteBalance;
-        FlashEnergy .Value = t.FlashEnergy;
-        FlashMode .Value = t.FlashMode;
-        LightSource .Value = t.LightSource;
-        Brightness .Value = t.Brightness;
-        PhotometricInterpretation .Value = t.PhotometricInterpretation;
-        Orientation .Value = t.Orientation;
-        ExifVersion .Value = t.ExifVersion;
-        LensMaker .Value = t.LensMaker;
-        LensModel .Value = t.LensModel;
-        SortFilesBy .Value = t.SortFilesBy;
-        FileExtension .Value = t.FileExtension;
-        CreationTime .Value = t.CreationTime;
-        Random .Value = t.Random;
-        Ascending .Value = t.Ascending;
-        Descending .Value = t.Descending;
-        RecentFiles .Value = t.RecentFiles;
-        SetAsWallpaper .Value = t.SetAsWallpaper;
-        SetAsLockScreenImage .Value = t.SetAsLockScreenImage;
-        Image .Value = t.Image;
-        CopyImage .Value = t.CopyImage;
-        FileCopyPath .Value = t.FileCopyPath;
-        FileCut .Value = t.Cut;
-        CtrlToZoom .Value = t.CtrlToZoom;
-        ScrollToZoom .Value = t.ScrollToZoom;
-        GeneralSettings .Value = t.GeneralSettings;
-        Appearance .Value = t.Appearance;
-        Language .Value = t.Language;
-        MouseWheel .Value = t.MouseWheel;
-        MiscSettings .Value = t.MiscSettings;
-        StayCentered .Value = t.StayCentered;
-        ShowFileSavingDialog .Value = t.ShowFileSavingDialog;
-        OpenInSameWindow .Value = t.OpenInSameWindow;
-        ApplicationStartup .Value = t.ApplicationStartup;
-        None .Value = t.None;
-        AdjustTimingForSlideshow .Value = t.AdjustTimingForSlideshow;
-        AdjustTimingForZoom .Value = t.AdjustTimingForZoom;
-        AdjustNavSpeed .Value = t.AdjustNavSpeed;
-        SecAbbreviation .Value = t.SecAbbreviation;
-        ResetButtonText .Value = t.ResetButtonText;
-        ShowBottomToolbar .Value = t.ShowBottomToolbar;
-        ShowBottomGalleryWhenUiIsHidden .Value = t.ShowBottomGalleryWhenUiIsHidden;
-        ChangeKeybindingTooltip .Value = t.ChangeKeybindingTooltip;
-        ToggleTaskbarProgress .Value = t.ToggleTaskbarProgress;
-        ChangeKeybindingText .Value = t.ChangeKeybindingText;
-        Navigation .Value = t.Navigation;
-        NextImage .Value = t.NextImage;
-        PrevImage .Value = t.PrevImage;
-        LastImage .Value = t.LastImage;
-        FirstImage .Value = t.FirstImage;
-        NextFolder .Value = t.NextFolder;
-        PrevFolder .Value = t.PrevFolder;
-        SelectGalleryThumb .Value = t.SelectGalleryThumb;
-        ScrollAndRotate .Value = t.ScrollAndRotate;
-        ScrollUp .Value = t.ScrollUp;
-        ScrollDown .Value = t.ScrollDown;
-        ScrollToTop .Value = t.ScrollToTop;
-        ScrollToBottom .Value = t.ScrollToBottom;
-        Zoom .Value = t.Zoom;
-        ZoomIn .Value = t.ZoomIn;
-        ZoomOut .Value = t.ZoomOut;
-        Pan .Value = t.Pan;
-        ResetZoom .Value = t.ResetZoom;
-        ImageControl .Value = t.ImageControl;
-        ChangeBackground .Value = t.ChangeBackground;
-        InterfaceConfiguration .Value = t.InterfaceConfiguration;
-        FileManagement .Value = t.FileManagement;
-        ToggleFullscreen .Value = t.ToggleFullscreen;
-        Fullscreen .Value = t.Fullscreen;
-        ShowImageGallery .Value = t.ShowImageGallery;
-        WindowManagement .Value = t.WindowManagement;
-        CenterWindow .Value = t.CenterWindow;
-        WindowScaling .Value = t.WindowScaling;
-        NormalWindow .Value = t.NormalWindow;
-        SetStarRating .Value = t.SetStarRating;
-        _1Star .Value = t._1Star;
-        _2Star .Value = t._2Star;
-        _3Star .Value = t._3Star;
-        _4Star .Value = t._4Star;
-        _5Star .Value = t._5Star;
-        RemoveStarRating .Value = t.RemoveStarRating;
-        Theme .Value = t.Theme;
-        DarkTheme .Value = t.DarkTheme;
-        LightTheme .Value = t.LightTheme;
-        MouseDrag .Value = t.MouseDrag;
-        DoubleClick .Value = t.DoubleClick;
-        MoveWindow .Value = t.MoveWindow;
-        GithubRepo .Value = t.GithubRepo;
-        Version .Value = t.Version;
-        ViewLicenseFile .Value = t.ViewLicenseFile;
-        CheckForUpdates .Value = t.CheckForUpdates;
-        Credits .Value = t.Credits;
-        ColorPickerTool .Value = t.ColorPickerTool;
-        ColorPickerToolTooltip .Value = t.ColorPickerToolTooltip;
-        ExpandedGalleryItemSize .Value = t.ExpandedGalleryItemSize;
-        BottomGalleryItemSize .Value = t.BottomGalleryItemSize;
-        Square .Value = t.Square;
-        Uniform .Value = t.Uniform;
-        UniformToFill .Value = t.UniformToFill;
-        FillSquare .Value = t.FillSquare;
-        Fill .Value = t.Fill;
-        GallerySettings .Value = t.GallerySettings;
-        GalleryThumbnailStretch .Value = t.GalleryThumbnailStretch;
-        BottomGalleryThumbnailStretch .Value = t.BottomGalleryThumbnailStretch;
-        RestoreDown .Value = t.RestoreDown;
-        SideBySide .Value = t.SideBySide;
-        SideBySideTooltip .Value = t.SideBySideTooltip;
-        HighlightColor .Value = t.HighlightColor;
-        AllowZoomOut .Value = t.AllowZoomOut;
-        GlassTheme .Value = t.GlassTheme;
-        ChangingThemeRequiresRestart .Value = t.ChangingThemeRequiresRestart;
-        ShowUI .Value = t.ShowUI;
-        HideUI .Value = t.HideUI;
-        HideBottomToolbar .Value = t.HideBottomToolbar;
-        Center .Value = t.Center;
-        Tile .Value = t.Tile;
-        Fit .Value = t.Fit;
-        Pixels .Value = t.Pixels;
-        Percentage .Value = t.Percentage;
-        Quality .Value = t.Quality;
-        SaveAs .Value = t.SaveAs;
-        Reset .Value = t.Reset;
-        AdvanceBy10Images .Value = t.AdvanceBy10Images;
-        AdvanceBy100Images .Value = t.AdvanceBy100Images;
-        GoBackBy10Images .Value = t.GoBackBy10Images;
-        GoBackBy100Images .Value = t.GoBackBy100Images;
-        ShowFadeInButtonsOnHover .Value = t.ShowFadeInButtonsOnHover;
-        DisableFadeInButtonsOnHover .Value = t.DisableFadeInButtonsOnHover;
-        UsingTouchpad .Value = t.UsingTouchpad;
-        UsingMouse .Value = t.UsingMouse;
-        SourceFolder .Value = t.SourceFolder;
-        OutputFolder .Value = t.OutputFolder;
-        GenerateThumbnails .Value = t.GenerateThumbnails;
-        Lossless .Value = t.Lossless;
-        Lossy .Value = t.Lossy;
-        Start .Value = t.Start;
-        Thumbnail .Value = t.Thumbnail;
-        WidthAndHeight .Value = t.WidthAndHeight;
-        CloseWindowPrompt .Value = t.CloseWindowPrompt;
-        ShowConfirmationOnEsc .Value = t.ShowConfirmationOnEsc;
-        ImageAliasing .Value = t.ImageAliasing;
-        HighQuality .Value = t.HighQuality;
-        Lighting .Value = t.Lighting;
-        BlackAndWhite .Value = t.BlackAndWhite;
-        NegativeColors .Value = t.NegativeColors;
-        Blur .Value = t.Blur;
-        PencilSketch .Value = t.PencilSketch;
-        OldMovie .Value = t.OldMovie;
-        Posterize .Value = t.Posterize;
-        ClearEffects .Value = t.ClearEffects;
-        Solarize .Value = t.Solarize;
-        Maximize .Value = t.Maximize;
-        SelectAll .Value = t.SelectAll;
-        Normal .Value = t.Normal;
-        FileAssociations .Value = t.FileAssociations;
-        SelectFileTypesToAssociate .Value = t.SelectFileTypesToAssociate;
-        Filter .Value = t.Filter;
-        UnselectAll .Value = t.UnselectAll;
-        Unassociate .Value = t.Unassociate;
-        ShowConfirmationDialogWhenMovingFileToRecycleBin .Value = t.ShowConfirmationDialogWhenMovingFileToRecycleBin;
-        MoveToRecycleBin .Value = t.MoveToRecycleBin;
-        ShowConfirmationDialogWhenPermanentlyDeletingFile .Value = t.ShowConfirmationDialogWhenPermanentlyDeletingFile;
-        Downloading .Value = t.Downloading;
-        Pinned .Value = t.Pinned;
-        Unpin .Value = t.Unpin;
-        Pin .Value = t.Pin;
-        Clear .Value = t.Clear;
-        OpenFileHistory .Value = t.OpenFileHistory;
-        ConstrainBackgroundToImage .Value = t.ConstrainBackgroundToImage;
-        Window .Value = t.Window;
-        WindowMargin .Value = t.WindowMargin;
-        Mouse .Value = t.Mouse;
-        MouseSideButtons .Value = t.MouseSideButtons;
-        NavigateFileHistory .Value = t.NavigateFileHistory;
-        NavigateBetweenDirectories .Value = t.NavigateBetweenDirectories;
-        Comment .Value = t.Comment;
+        SelectFile.Value = t.OpenFileDialog;
+        OpenLastFile.Value = t.OpenLastFile;
+        Paste.Value = t.FilePaste;
+        Copy.Value = t.Copy;
+        Reload.Value = t.Reload;
+        Print.Value = t.Print;
+        DeleteFile.Value = t.DeleteFile;
+        PermanentlyDelete.Value = t.PermanentlyDelete;
+        Save.Value = t.Save;
+        CopyFile.Value = t.CopyFile;
+        NewWindow.Value = t.NewWindow;
+        Close.Value = t.Close;
+        CloseGallery.Value = t.CloseGallery;
+        Open.Value = t.Open;
+        OpenFileDialog.Value = t.OpenFileDialog;
+        ShowInFolder.Value = t.ShowInFolder;
+        OpenWith.Value = t.OpenWith;
+        RenameFile.Value = t.RenameFile;
+        DuplicateFile.Value = t.DuplicateFile;
+        RotateLeft.Value = t.RotateLeft;
+        RotateRight.Value = t.RotateRight;
+        Flip.Value = t.Flip;
+        UnFlip.Value = t.Unflip;
+        ShowBottomGallery.Value = t.ShowBottomGallery;
+        HideBottomGallery.Value = t.HideBottomGallery;
+        AutoFitWindow.Value = t.AutoFitWindow;
+        Stretch.Value = t.Stretch;
+        Crop.Value = t.Crop;
+        ResizeImage.Value = t.ResizeImage;
+        GoToImageAtSpecifiedIndex.Value = t.GoToImageAtSpecifiedIndex;
+        ToggleScroll.Value = t.ToggleScroll;
+        ScrollEnabled.Value = t.ScrollingEnabled;
+        ScrollDisabled.Value = t.ScrollingDisabled;
+        ScrollDirection.Value = t.ScrollDirection;
+        Reverse.Value = t.Reverse;
+        Forward.Value = t.Forward;
+        Slideshow.Value = t.Slideshow;
+        Settings.Value = t.Settings;
+        AboutWindow.Value = t.InfoWindow;
+        ImageInfo.Value = t.ImageInfo;
+        About.Value = t.About;
+        ShowAllSettingsWindow.Value = t.ShowAllSettingsWindow;
+        StayTopMost.Value = t.StayTopMost;
+        SearchSubdirectory.Value = t.SearchSubdirectory;
+        ToggleLooping.Value = t.ToggleLooping;
+        ApplicationShortcuts.Value = t.ApplicationShortcuts;
+        BatchResize.Value = t.BatchResize;
+        Effects.Value = t.Effects;
+        EffectsTooltip.Value = t.EffectsTooltip;
+        FileProperties.Value = t.FileProperties;
+        OptimizeImage.Value = t.OptimizeImage;
+        ImageInfo.Value = t.ImageInfo;
+        FileName.Value = t.FileName;
+        FileSize.Value = t.FileSize;
+        Folder.Value = t.Folder;
+        FullPath.Value = t.FullPath;
+        Created.Value = t.Created;
+        Modified.Value = t.Modified;
+        LastAccessTime.Value = t.LastAccessTime;
+        ConvertTo.Value = t.ConvertTo;
+        NoConversion.Value = t.NoConversion;
+        Resize.Value = t.Resize;
+        NoResize.Value = t.NoResize;
+        Apply.Value = t.Apply;
+        Cancel.Value = t.Cancel;
+        BitDepth.Value = t.BitDepth;
+        ReadAbleAspectRatio.Value = t.AspectRatio;
+        Width.Value = t.Width;
+        Height.Value = t.Height;
+        SizeMp.Value = t.SizeMp;
+        Resolution.Value = t.Resolution;
+        PrintSizeIn.Value = t.PrintSizeIn;
+        PrintSizeCm.Value = t.PrintSizeCm;
+        Centimeters.Value = t.Centimeters;
+        Inches.Value = t.Inches;
+        SizeTooltip.Value = t.SizeTooltip;
+        Latitude.Value = t.Latitude;
+        Longitude.Value = t.Longitude;
+        Altitude.Value = t.Altitude;
+        Authors.Value = t.Authors;
+        DateTaken.Value = t.DateTaken;
+        Copyright.Value = t.Copyright;
+        ResolutionUnit.Value = t.ResolutionUnit;
+        ColorRepresentation.Value = t.ColorRepresentation;
+        CompressedBitsPixel.Value = t.CompressedBitsPixel;
+        Compression.Value = t.Compression;
+        ExposureTime.Value = t.ExposureTime;
+        Title.Value = t.Title;
+        Subject.Value = t.Subject;
+        Software.Value = t.Software;
+        CameraMaker.Value = t.CameraMaker;
+        CameraModel.Value = t.CameraModel;
+        FocalLength.Value = t.FocalLength;
+        Fnumber.Value = t.FNumber;
+        Fstop.Value = t.Fstop;
+        MaxAperture.Value = t.MaxAperture;
+        ExposureBias.Value = t.ExposureBias;
+        ExposureProgram.Value = t.ExposureProgram;
+        DigitalZoom.Value = t.DigitalZoom;
+        ISOSpeed.Value = t.ISOSpeed;
+        FocalLength35mm.Value = t.FocalLength35mm;
+        MeteringMode.Value = t.MeteringMode;
+        Contrast.Value = t.Contrast;
+        Saturation.Value = t.Saturation;
+        Sharpness.Value = t.Sharpness;
+        WhiteBalance.Value = t.WhiteBalance;
+        FlashEnergy.Value = t.FlashEnergy;
+        FlashMode.Value = t.FlashMode;
+        LightSource.Value = t.LightSource;
+        Brightness.Value = t.Brightness;
+        PhotometricInterpretation.Value = t.PhotometricInterpretation;
+        Orientation.Value = t.Orientation;
+        ExifVersion.Value = t.ExifVersion;
+        LensMaker.Value = t.LensMaker;
+        LensModel.Value = t.LensModel;
+        SortFilesBy.Value = t.SortFilesBy;
+        FileExtension.Value = t.FileExtension;
+        CreationTime.Value = t.CreationTime;
+        Random.Value = t.Random;
+        Ascending.Value = t.Ascending;
+        Descending.Value = t.Descending;
+        RecentFiles.Value = t.RecentFiles;
+        SetAsWallpaper.Value = t.SetAsWallpaper;
+        SetAsLockScreenImage.Value = t.SetAsLockScreenImage;
+        Image.Value = t.Image;
+        CopyImage.Value = t.CopyImage;
+        FileCopyPath.Value = t.FileCopyPath;
+        FileCut.Value = t.Cut;
+        CtrlToZoom.Value = t.CtrlToZoom;
+        ScrollToZoom.Value = t.ScrollToZoom;
+        GeneralSettings.Value = t.GeneralSettings;
+        Appearance.Value = t.Appearance;
+        Language.Value = t.Language;
+        MouseWheel.Value = t.MouseWheel;
+        MiscSettings.Value = t.MiscSettings;
+        StayCentered.Value = t.StayCentered;
+        ShowFileSavingDialog.Value = t.ShowFileSavingDialog;
+        OpenInSameWindow.Value = t.OpenInSameWindow;
+        ApplicationStartup.Value = t.ApplicationStartup;
+        None.Value = t.None;
+        AdjustTimingForSlideshow.Value = t.AdjustTimingForSlideshow;
+        AdjustTimingForZoom.Value = t.AdjustTimingForZoom;
+        AdjustNavSpeed.Value = t.AdjustNavSpeed;
+        SecAbbreviation.Value = t.SecAbbreviation;
+        ResetButtonText.Value = t.ResetButtonText;
+        ShowBottomToolbar.Value = t.ShowBottomToolbar;
+        ShowBottomGalleryWhenUiIsHidden.Value = t.ShowBottomGalleryWhenUiIsHidden;
+        ChangeKeybindingTooltip.Value = t.ChangeKeybindingTooltip;
+        ToggleTaskbarProgress.Value = t.ToggleTaskbarProgress;
+        ChangeKeybindingText.Value = t.ChangeKeybindingText;
+        Navigation.Value = t.Navigation;
+        NextImage.Value = t.NextImage;
+        PrevImage.Value = t.PrevImage;
+        LastImage.Value = t.LastImage;
+        FirstImage.Value = t.FirstImage;
+        NextFolder.Value = t.NextFolder;
+        PrevFolder.Value = t.PrevFolder;
+        SelectGalleryThumb.Value = t.SelectGalleryThumb;
+        ScrollAndRotate.Value = t.ScrollAndRotate;
+        ScrollUp.Value = t.ScrollUp;
+        ScrollDown.Value = t.ScrollDown;
+        ScrollToTop.Value = t.ScrollToTop;
+        ScrollToBottom.Value = t.ScrollToBottom;
+        Zoom.Value = t.Zoom;
+        ZoomIn.Value = t.ZoomIn;
+        ZoomOut.Value = t.ZoomOut;
+        Pan.Value = t.Pan;
+        ResetZoom.Value = t.ResetZoom;
+        ImageControl.Value = t.ImageControl;
+        ChangeBackground.Value = t.ChangeBackground;
+        InterfaceConfiguration.Value = t.InterfaceConfiguration;
+        FileManagement.Value = t.FileManagement;
+        ToggleFullscreen.Value = t.ToggleFullscreen;
+        Fullscreen.Value = t.Fullscreen;
+        ShowImageGallery.Value = t.ShowImageGallery;
+        WindowManagement.Value = t.WindowManagement;
+        CenterWindow.Value = t.CenterWindow;
+        WindowScaling.Value = t.WindowScaling;
+        NormalWindow.Value = t.NormalWindow;
+        SetStarRating.Value = t.SetStarRating;
+        _1Star.Value = t._1Star;
+        _2Star.Value = t._2Star;
+        _3Star.Value = t._3Star;
+        _4Star.Value = t._4Star;
+        _5Star.Value = t._5Star;
+        RemoveImageData.Value = t.RemoveImageData;
+        RemoveStarRating.Value = t.RemoveStarRating;
+        Theme.Value = t.Theme;
+        DarkTheme.Value = t.DarkTheme;
+        LightTheme.Value = t.LightTheme;
+        MouseDrag.Value = t.MouseDrag;
+        DoubleClick.Value = t.DoubleClick;
+        MoveWindow.Value = t.MoveWindow;
+        GithubRepo.Value = t.GithubRepo;
+        Version.Value = t.Version;
+        ViewLicenseFile.Value = t.ViewLicenseFile;
+        CheckForUpdates.Value = t.CheckForUpdates;
+        Credits.Value = t.Credits;
+        ColorPickerTool.Value = t.ColorPickerTool;
+        ColorPickerToolTooltip.Value = t.ColorPickerToolTooltip;
+        ExpandedGalleryItemSize.Value = t.ExpandedGalleryItemSize;
+        BottomGalleryItemSize.Value = t.BottomGalleryItemSize;
+        Square.Value = t.Square;
+        Uniform.Value = t.Uniform;
+        UniformToFill.Value = t.UniformToFill;
+        FillSquare.Value = t.FillSquare;
+        Fill.Value = t.Fill;
+        GallerySettings.Value = t.GallerySettings;
+        GalleryThumbnailStretch.Value = t.GalleryThumbnailStretch;
+        BottomGalleryThumbnailStretch.Value = t.BottomGalleryThumbnailStretch;
+        RestoreDown.Value = t.RestoreDown;
+        SideBySide.Value = t.SideBySide;
+        SideBySideTooltip.Value = t.SideBySideTooltip;
+        HighlightColor.Value = t.HighlightColor;
+        AllowZoomOut.Value = t.AllowZoomOut;
+        GlassTheme.Value = t.GlassTheme;
+        ChangingThemeRequiresRestart.Value = t.ChangingThemeRequiresRestart;
+        ShowUI.Value = t.ShowUI;
+        HideUI.Value = t.HideUI;
+        HideBottomToolbar.Value = t.HideBottomToolbar;
+        Center.Value = t.Center;
+        Tile.Value = t.Tile;
+        Fit.Value = t.Fit;
+        Pixels.Value = t.Pixels;
+        Percentage.Value = t.Percentage;
+        Quality.Value = t.Quality;
+        SaveAs.Value = t.SaveAs;
+        Reset.Value = t.Reset;
+        AdvanceBy10Images.Value = t.AdvanceBy10Images;
+        AdvanceBy100Images.Value = t.AdvanceBy100Images;
+        GoBackBy10Images.Value = t.GoBackBy10Images;
+        GoBackBy100Images.Value = t.GoBackBy100Images;
+        ShowFadeInButtonsOnHover.Value = t.ShowFadeInButtonsOnHover;
+        DisableFadeInButtonsOnHover.Value = t.DisableFadeInButtonsOnHover;
+        UsingTouchpad.Value = t.UsingTouchpad;
+        UsingMouse.Value = t.UsingMouse;
+        SourceFolder.Value = t.SourceFolder;
+        OutputFolder.Value = t.OutputFolder;
+        GenerateThumbnails.Value = t.GenerateThumbnails;
+        Lossless.Value = t.Lossless;
+        Lossy.Value = t.Lossy;
+        Start.Value = t.Start;
+        Thumbnail.Value = t.Thumbnail;
+        WidthAndHeight.Value = t.WidthAndHeight;
+        CloseWindowPrompt.Value = t.CloseWindowPrompt;
+        ShowConfirmationOnEsc.Value = t.ShowConfirmationOnEsc;
+        ImageAliasing.Value = t.ImageAliasing;
+        HighQuality.Value = t.HighQuality;
+        Lighting.Value = t.Lighting;
+        BlackAndWhite.Value = t.BlackAndWhite;
+        NegativeColors.Value = t.NegativeColors;
+        Blur.Value = t.Blur;
+        PencilSketch.Value = t.PencilSketch;
+        OldMovie.Value = t.OldMovie;
+        Posterize.Value = t.Posterize;
+        ClearEffects.Value = t.ClearEffects;
+        Solarize.Value = t.Solarize;
+        Maximize.Value = t.Maximize;
+        SelectAll.Value = t.SelectAll;
+        Normal.Value = t.Normal;
+        FileAssociations.Value = t.FileAssociations;
+        SelectFileTypesToAssociate.Value = t.SelectFileTypesToAssociate;
+        Filter.Value = t.Filter;
+        UnselectAll.Value = t.UnselectAll;
+        Unassociate.Value = t.Unassociate;
+        ShowConfirmationDialogWhenMovingFileToRecycleBin.Value = t.ShowConfirmationDialogWhenMovingFileToRecycleBin;
+        MoveToRecycleBin.Value = t.MoveToRecycleBin;
+        ShowConfirmationDialogWhenPermanentlyDeletingFile.Value = t.ShowConfirmationDialogWhenPermanentlyDeletingFile;
+        Downloading.Value = t.Downloading;
+        Pinned.Value = t.Pinned;
+        Unpin.Value = t.Unpin;
+        Pin.Value = t.Pin;
+        Clear.Value = t.Clear;
+        OpenFileHistory.Value = t.OpenFileHistory;
+        ConstrainBackgroundToImage.Value = t.ConstrainBackgroundToImage;
+        Window.Value = t.Window;
+        WindowMargin.Value = t.WindowMargin;
+        Mouse.Value = t.Mouse;
+        MouseSideButtons.Value = t.MouseSideButtons;
+        NavigateFileHistory.Value = t.NavigateFileHistory;
+        NavigateBetweenDirectories.Value = t.NavigateBetweenDirectories;
+        Comment.Value = t.Comment;
     }
 
     #region Static Translation Strings
@@ -586,11 +586,11 @@ public class TranslationViewModel : IDisposable
     public BindableReactiveProperty<string?> MiscSettings { get; } = new();
 
     public BindableReactiveProperty<string?> Modified { get; } = new();
-    
+
     public BindableReactiveProperty<string?> Mouse { get; } = new();
 
     public BindableReactiveProperty<string?> MouseDrag { get; } = new();
-    
+
     public BindableReactiveProperty<string?> MouseSideButtons { get; } = new();
 
     public BindableReactiveProperty<string?> MouseWheel { get; } = new();
@@ -683,6 +683,7 @@ public class TranslationViewModel : IDisposable
 
     public BindableReactiveProperty<string?> Reload { get; } = new();
 
+    public BindableReactiveProperty<string?> RemoveImageData { get; } = new();
     public BindableReactiveProperty<string?> RemoveStarRating { get; } = new();
 
     public BindableReactiveProperty<string?> RenameFile { get; } = new();
@@ -853,7 +854,7 @@ public class TranslationViewModel : IDisposable
 
     public BindableReactiveProperty<string?> Window { get; } = new();
     public BindableReactiveProperty<string?> WindowManagement { get; } = new();
-    
+
     public BindableReactiveProperty<string?> WindowMargin { get; } = new();
 
     public BindableReactiveProperty<string?> WindowScaling { get; } = new();
@@ -862,7 +863,7 @@ public class TranslationViewModel : IDisposable
     public BindableReactiveProperty<string?> ZoomIn { get; } = new();
 
     public BindableReactiveProperty<string?> ZoomOut { get; } = new();
-    
+
     #endregion strings
 
     #region Dynamic Translation strings
@@ -883,6 +884,6 @@ public class TranslationViewModel : IDisposable
 
     public BindableReactiveProperty<string?> IsShowingUI { get; } = new();
     public BindableReactiveProperty<string?> IsUsingTouchpad { get; } = new();
-    
+
     #endregion
 }