ExifHandling.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using Avalonia.Media.Imaging;
  2. using ImageMagick;
  3. using PicView.Avalonia.Resizing;
  4. using PicView.Avalonia.ViewModels;
  5. using PicView.Core.DebugTools;
  6. using PicView.Core.ImageDecoding;
  7. using PicView.Core.Localization;
  8. using PicView.Core.Titles;
  9. namespace PicView.Avalonia.Navigation;
  10. public static class ExifHandling
  11. {
  12. public static void UpdateExifValues(MainViewModel vm)
  13. {
  14. if (vm.PicViewer?.FileInfo is null || vm.PicViewer is { PixelWidth: <= 0, PixelHeight: <= 0 })
  15. {
  16. return;
  17. }
  18. using var magick = new MagickImage();
  19. try
  20. {
  21. if (!vm.PicViewer.FileInfo.Exists)
  22. {
  23. return;
  24. }
  25. magick.Ping(vm.PicViewer.FileInfo);
  26. var profile = magick.GetExifProfile();
  27. if (profile != null)
  28. {
  29. vm.Exif.DpiY = profile?.GetValue(ExifTag.YResolution)?.Value.ToDouble() ?? 0;
  30. vm.Exif.DpiX = profile?.GetValue(ExifTag.XResolution)?.Value.ToDouble() ?? 0;
  31. var depth = profile?.GetValue(ExifTag.BitsPerSample)?.Value;
  32. if (depth is not null)
  33. {
  34. var x = depth.Aggregate(0, (current, value) => current + value);
  35. vm.Exif.BitDepth = x.ToString();
  36. }
  37. else
  38. {
  39. vm.Exif.BitDepth = (magick.Depth * 3).ToString();
  40. }
  41. }
  42. if (vm.Exif.DpiX is 0 && vm.PicViewer.ImageType is ImageType.Bitmap or ImageType.AnimatedGif or ImageType.AnimatedWebp)
  43. {
  44. if (vm.PicViewer.ImageSource is Bitmap bmp)
  45. {
  46. vm.Exif.DpiX = bmp?.Dpi.X ?? 0;
  47. vm.Exif.DpiY = bmp?.Dpi.Y ?? 0;
  48. }
  49. }
  50. vm.Exif.Orientation = vm.PicViewer.ExifOrientation switch
  51. {
  52. EXIFHelper.EXIFOrientation.Horizontal => TranslationManager.Translation.Normal,
  53. EXIFHelper.EXIFOrientation.MirrorHorizontal => TranslationManager.Translation.Flipped,
  54. EXIFHelper.EXIFOrientation.Rotate180 => $"{TranslationManager.Translation.Rotated} 180\u00b0",
  55. EXIFHelper.EXIFOrientation.MirrorVertical =>
  56. $"{TranslationManager.Translation.Rotated} 180\u00b0, {TranslationManager.Translation.Flipped}",
  57. EXIFHelper.EXIFOrientation.MirrorHorizontalRotate270Cw =>
  58. $"{TranslationManager.Translation.Rotated} 270\u00b0, {TranslationManager.Translation.Flipped}",
  59. EXIFHelper.EXIFOrientation.Rotate90Cw => $"{TranslationManager.Translation.Rotated} 90\u00b0",
  60. EXIFHelper.EXIFOrientation.MirrorHorizontalRotate90Cw =>
  61. $"{TranslationManager.Translation.Rotated} 90\u00b0, {TranslationManager.Translation.Flipped}",
  62. EXIFHelper.EXIFOrientation.Rotated270Cw => $"{TranslationManager.Translation.Rotated} 270\u00b0",
  63. _ => string.Empty
  64. };
  65. var meter = TranslationManager.Translation.Meter;
  66. if (string.IsNullOrEmpty(vm.Exif.BitDepth))
  67. {
  68. vm.Exif.BitDepth = (magick.Depth * 3).ToString();
  69. }
  70. if (vm.Exif.DpiX == 0 || vm.Exif.DpiY == 0) // Check for zero before division
  71. {
  72. vm.Exif.PrintSizeCm = vm.Exif.PrintSizeInch = vm.Exif.SizeMp = vm.Exif.Resolution = string.Empty;
  73. }
  74. else
  75. {
  76. var printSizes = AspectRatioHelper.GetPrintSizes( vm.PicViewer.PixelWidth, vm.PicViewer.PixelHeight, vm.Exif.DpiX, vm.Exif.DpiY);
  77. vm.Exif.PrintSizeCm = printSizes.PrintSizeCm;
  78. vm.Exif.PrintSizeInch = printSizes.PrintSizeInch;
  79. vm.Exif.SizeMp = printSizes.SizeMp;
  80. vm.Exif.Resolution = $"{vm.Exif.DpiX} x {vm.Exif.DpiY} {TranslationManager.Translation.Dpi}";
  81. }
  82. var gcd = ImageTitleFormatter.GCD(vm.PicViewer.PixelWidth, vm.PicViewer.PixelHeight);
  83. if (gcd != 0) // Check for zero before division
  84. {
  85. vm.Exif.AspectRatio = AspectRatioHelper.GetFormattedAspectRatio(gcd, vm.PicViewer.PixelWidth, vm.PicViewer.PixelHeight);
  86. }
  87. else
  88. {
  89. vm.Exif.AspectRatio = string.Empty; // Handle cases where gcd is 0
  90. }
  91. vm.EXIFRating = profile?.GetValue(ExifTag.Rating)?.Value ?? 0;
  92. var gpsValues = EXIFHelper.GetGPSValues(profile);
  93. if (gpsValues is not null)
  94. {
  95. vm.Exif.Latitude = gpsValues[0];
  96. vm.Exif.Longitude = gpsValues[1];
  97. vm.Exif.GoogleLink = gpsValues[2];
  98. vm.Exif.BingLink = gpsValues[3];
  99. }
  100. else
  101. {
  102. vm.Exif.Latitude = vm.Exif.Longitude = vm.Exif.GoogleLink = vm.Exif.BingLink = string.Empty;
  103. }
  104. var altitude = profile?.GetValue(ExifTag.GPSAltitude)?.Value;
  105. vm.Exif.Altitude = altitude.HasValue
  106. ? $"{altitude.Value.ToDouble()} {meter}"
  107. : string.Empty;
  108. var getAuthors = profile?.GetValue(ExifTag.Artist)?.Value;
  109. vm.Exif.Authors = getAuthors ?? string.Empty;
  110. vm.Exif.DateTaken = EXIFHelper.GetDateTaken(profile);
  111. vm.Exif.Copyright = profile?.GetValue(ExifTag.Copyright)?.Value ?? string.Empty;
  112. vm.Exif.Title = EXIFHelper.GetTitle(profile);
  113. vm.Exif.Subject = EXIFHelper.GetSubject(profile);
  114. vm.Exif.Software = profile?.GetValue(ExifTag.Software)?.Value ?? string.Empty;
  115. vm.Exif.ResolutionUnit = EXIFHelper.GetResolutionUnit(profile);
  116. vm.Exif.ColorRepresentation = EXIFHelper.GetColorSpace(profile);
  117. vm.Exif.Compression = profile?.GetValue(ExifTag.Compression)?.Value.ToString() ?? string.Empty;
  118. vm.Exif.CompressedBitsPixel = profile?.GetValue(ExifTag.CompressedBitsPerPixel)?.Value.ToString() ?? string.Empty;
  119. vm.Exif.CameraMaker = profile?.GetValue(ExifTag.Make)?.Value ?? string.Empty;
  120. vm.Exif.CameraModel = profile?.GetValue(ExifTag.Model)?.Value ?? string.Empty;
  121. vm.Exif.ExposureProgram = EXIFHelper.GetExposureProgram(profile);
  122. vm.Exif.ExposureTime = profile?.GetValue(ExifTag.ExposureTime)?.Value.ToString() ?? string.Empty;
  123. vm.Exif.FNumber = profile?.GetValue(ExifTag.FNumber)?.Value.ToString() ?? string.Empty;
  124. vm.Exif.MaxAperture = profile?.GetValue(ExifTag.MaxApertureValue)?.Value.ToString() ?? string.Empty;
  125. vm.Exif.ExposureBias = profile?.GetValue(ExifTag.ExposureBiasValue)?.Value.ToString() ?? string.Empty;
  126. vm.Exif.DigitalZoom = profile?.GetValue(ExifTag.DigitalZoomRatio)?.Value.ToString() ?? string.Empty;
  127. vm.Exif.FocalLength35Mm = profile?.GetValue(ExifTag.FocalLengthIn35mmFilm)?.Value.ToString() ?? string.Empty;
  128. vm.Exif.FocalLength = profile?.GetValue(ExifTag.FocalLength)?.Value.ToString() ?? string.Empty;
  129. vm.Exif.ISOSpeed = EXIFHelper.GetISOSpeed(profile);
  130. vm.Exif.MeteringMode = profile?.GetValue(ExifTag.MeteringMode)?.Value.ToString() ?? string.Empty;
  131. vm.Exif.Contrast = EXIFHelper.GetContrast(profile);
  132. vm.Exif.Saturation = EXIFHelper.GetSaturation(profile);
  133. vm.Exif.Sharpness = EXIFHelper.GetSharpness(profile);
  134. vm.Exif.WhiteBalance = EXIFHelper.GetWhiteBalance(profile);
  135. vm.Exif.FlashMode = EXIFHelper.GetFlashMode(profile);
  136. vm.Exif.FlashEnergy = profile?.GetValue(ExifTag.FlashEnergy)?.Value.ToString() ?? string.Empty;
  137. vm.Exif.LightSource = EXIFHelper.GetLightSource(profile);
  138. vm.Exif.Brightness = profile?.GetValue(ExifTag.BrightnessValue)?.Value.ToString() ?? string.Empty;
  139. vm.Exif.PhotometricInterpretation = EXIFHelper.GetPhotometricInterpretation(profile);
  140. vm.Exif.ExifVersion = EXIFHelper.GetExifVersion(profile);
  141. vm.Exif.LensModel = profile?.GetValue(ExifTag.LensModel)?.Value ?? string.Empty;
  142. vm.Exif.LensMaker = profile?.GetValue(ExifTag.LensMake)?.Value ?? string.Empty;
  143. vm.Exif.Comment = EXIFHelper.GetUserComment(profile);
  144. }
  145. catch (Exception e)
  146. {
  147. DebugHelper.LogDebug(nameof(ExifHandling), nameof(UpdateExifValues), e);
  148. }
  149. }
  150. }