ExifHandling.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. using System.Globalization;
  2. using Avalonia.Media.Imaging;
  3. using ImageMagick;
  4. using PicView.Avalonia.ImageHandling;
  5. using PicView.Avalonia.UI;
  6. using PicView.Avalonia.ViewModels;
  7. using PicView.Core.ImageDecoding;
  8. using PicView.Core.Localization;
  9. using PicView.Core.Navigation;
  10. namespace PicView.Avalonia.Navigation;
  11. public static class ExifHandling
  12. {
  13. public static void SetImageModel(ImageModel imageModel, MainViewModel vm)
  14. {
  15. vm.FileInfo = imageModel?.FileInfo ?? null;
  16. if (imageModel?.EXIFOrientation.HasValue ?? false)
  17. {
  18. switch (imageModel.EXIFOrientation.Value)
  19. {
  20. default:
  21. vm.ScaleX = 1;
  22. vm.RotationAngle = 0;
  23. vm.GetOrientation = string.Empty;
  24. break;
  25. case EXIFHelper.EXIFOrientation.Normal:
  26. vm.ScaleX = 1;
  27. vm.RotationAngle = 0;
  28. vm.GetOrientation = TranslationHelper.Translation.Normal;
  29. break;
  30. case EXIFHelper.EXIFOrientation.Flipped:
  31. vm.ScaleX = -1;
  32. vm.RotationAngle = 0;
  33. vm.GetOrientation = TranslationHelper.Translation.Flipped;
  34. break;
  35. case EXIFHelper.EXIFOrientation.Rotated180:
  36. vm.RotationAngle = 180;
  37. vm.ScaleX = 1;
  38. vm.GetOrientation = $"{TranslationHelper.Translation.Rotated} 180\u00b0";
  39. break;
  40. case EXIFHelper.EXIFOrientation.Rotated180Flipped:
  41. vm.RotationAngle = 180;
  42. vm.ScaleX = -1;
  43. vm.GetOrientation =
  44. $"{TranslationHelper.Translation.Rotated} 180\u00b0, {TranslationHelper.Translation.Flipped}";
  45. break;
  46. case EXIFHelper.EXIFOrientation.Rotated270Flipped:
  47. vm.RotationAngle = 270;
  48. vm.ScaleX = -1;
  49. vm.GetOrientation =
  50. $"{TranslationHelper.Translation.Rotated} 270\u00b0, {TranslationHelper.Translation.Flipped}";
  51. break;
  52. case EXIFHelper.EXIFOrientation.Rotated90:
  53. vm.RotationAngle = 90;
  54. vm.ScaleX = 1;
  55. vm.GetOrientation = $"{TranslationHelper.Translation.Rotated} 90\u00b0";
  56. break;
  57. case EXIFHelper.EXIFOrientation.Rotated90Flipped:
  58. vm.RotationAngle = 90;
  59. vm.ScaleX = -1;
  60. vm.GetOrientation =
  61. $"{TranslationHelper.Translation.Rotated} 90\u00b0, {TranslationHelper.Translation.Flipped}";
  62. break;
  63. case EXIFHelper.EXIFOrientation.Rotated270:
  64. vm.RotationAngle = 270;
  65. vm.ScaleX = 1;
  66. vm.GetOrientation = $"{TranslationHelper.Translation.Rotated} 270\u00b0";
  67. break;
  68. }
  69. }
  70. else
  71. {
  72. vm.ScaleX = 1;
  73. vm.RotationAngle = 0;
  74. vm.GetOrientation = string.Empty;
  75. }
  76. vm.ZoomValue = 1;
  77. vm.PixelWidth = imageModel?.PixelWidth ?? 0;
  78. vm.PixelHeight = imageModel?.PixelHeight ?? 0;
  79. }
  80. public static void UpdateExifValues(ImageModel imageModel, MainViewModel vm)
  81. {
  82. if (vm.FileInfo is null || vm is { PixelWidth: <= 0, PixelHeight: <= 0 })
  83. {
  84. return;
  85. }
  86. using var magick = new MagickImage();
  87. try
  88. {
  89. magick.Ping(vm.FileInfo);
  90. var profile = magick.GetExifProfile();
  91. if (profile != null)
  92. {
  93. vm.DpiY = profile?.GetValue(ExifTag.YResolution)?.Value.ToDouble() ?? 0;
  94. vm.DpiX = profile?.GetValue(ExifTag.XResolution)?.Value.ToDouble() ?? 0;
  95. var depth = profile?.GetValue(ExifTag.BitsPerSample)?.Value;
  96. if (depth is not null)
  97. {
  98. var x = depth.Aggregate(0, (current, value) => current + value);
  99. vm.GetBitDepth = x.ToString();
  100. }
  101. else
  102. {
  103. vm.GetBitDepth = (magick.Depth * 3).ToString();
  104. }
  105. }
  106. if (vm.DpiX is 0 && imageModel.ImageType is ImageType.Bitmap or ImageType.AnimatedGif or ImageType.AnimatedWebp)
  107. {
  108. if (imageModel.Image is Bitmap bmp)
  109. {
  110. vm.DpiX = bmp?.Dpi.X ?? 0;
  111. vm.DpiY = bmp?.Dpi.Y ?? 0;
  112. }
  113. }
  114. var meter = TranslationHelper.Translation.Meter;
  115. var cm = TranslationHelper.Translation.Centimeters;
  116. var mp = TranslationHelper.Translation.MegaPixels;
  117. var inches = TranslationHelper.Translation.Inches;
  118. var square = TranslationHelper.Translation.Square;
  119. var landscape = TranslationHelper.Translation.Landscape;
  120. var portrait = TranslationHelper.Translation.Portrait;
  121. if (string.IsNullOrEmpty(vm.GetBitDepth))
  122. {
  123. vm.GetBitDepth = (magick.Depth * 3).ToString();
  124. }
  125. if (vm.DpiX == 0 || vm.DpiY == 0) // Check for zero before division
  126. {
  127. vm.GetPrintSizeCm = vm.GetPrintSizeInch = vm.GetSizeMp = vm.GetResolution = string.Empty;
  128. }
  129. else
  130. {
  131. var inchesWidth = vm.PixelWidth / vm.DpiX;
  132. var inchesHeight = vm.PixelHeight / vm.DpiY;
  133. vm.GetPrintSizeInch =
  134. $"{inchesWidth.ToString("0.##", CultureInfo.CurrentCulture)} x {inchesHeight.ToString("0.##", CultureInfo.CurrentCulture)} {inches}";
  135. var cmWidth = vm.PixelWidth / vm.DpiX * 2.54;
  136. var cmHeight = vm.PixelHeight / vm.DpiY * 2.54;
  137. vm.GetPrintSizeCm =
  138. $"{cmWidth.ToString("0.##", CultureInfo.CurrentCulture)} x {cmHeight.ToString("0.##", CultureInfo.CurrentCulture)} {cm}";
  139. vm.GetSizeMp =
  140. $"{((float)vm.PixelHeight * vm.PixelWidth / 1000000).ToString("0.##", CultureInfo.CurrentCulture)} {mp}";
  141. vm.GetResolution = $"{vm.DpiX} x {vm.DpiY} {TranslationHelper.Translation.Dpi}";
  142. }
  143. var gcd = TitleHelper.GCD(vm.PixelWidth, vm.PixelHeight);
  144. if (gcd != 0) // Check for zero before division
  145. {
  146. var firstRatio = vm.PixelWidth / gcd;
  147. var secondRatio = vm.PixelHeight / gcd;
  148. if (firstRatio == secondRatio)
  149. {
  150. vm.GetAspectRatio = $"{firstRatio}:{secondRatio} ({square})";
  151. }
  152. else if (firstRatio > secondRatio)
  153. {
  154. vm.GetAspectRatio =
  155. $"{firstRatio}:{secondRatio} ({landscape})";
  156. }
  157. else
  158. {
  159. vm.GetAspectRatio = $"{firstRatio}:{secondRatio} ({portrait})";
  160. }
  161. }
  162. else
  163. {
  164. vm.GetAspectRatio = string.Empty; // Handle cases where gcd is 0
  165. }
  166. vm.EXIFRating = profile?.GetValue(ExifTag.Rating)?.Value ?? 0;
  167. var gpsValues = EXIFHelper.GetGPSValues(profile);
  168. if (gpsValues is not null)
  169. {
  170. vm.GetLatitude = gpsValues[0];
  171. vm.GetLongitude = gpsValues[1];
  172. vm.GoogleLink = gpsValues[2];
  173. vm.BingLink = gpsValues[3];
  174. }
  175. else
  176. {
  177. vm.GetLatitude = vm.GetLongitude = vm.GoogleLink = vm.BingLink = string.Empty;
  178. }
  179. var altitude = profile?.GetValue(ExifTag.GPSAltitude)?.Value;
  180. vm.GetAltitude = altitude.HasValue
  181. ? $"{altitude.Value.ToDouble()} {meter}"
  182. : string.Empty;
  183. var getAuthors = profile?.GetValue(ExifTag.Artist)?.Value;
  184. vm.GetAuthors = getAuthors ?? string.Empty;
  185. vm.GetDateTaken = EXIFHelper.GetDateTaken(profile);
  186. vm.GetCopyright = profile?.GetValue(ExifTag.Copyright)?.Value ?? string.Empty;
  187. vm.GetTitle = EXIFHelper.GetTitle(profile);
  188. vm.GetSubject = profile?.GetValue(ExifTag.XPSubject)?.Value.ToString() ?? string.Empty;
  189. vm.GetSoftware = profile?.GetValue(ExifTag.Software)?.Value ?? string.Empty;
  190. vm.GetResolutionUnit = EXIFHelper.GetResolutionUnit(profile);
  191. vm.GetColorRepresentation = EXIFHelper.GetColorSpace(profile);
  192. vm.GetCompression = profile?.GetValue(ExifTag.Compression)?.Value.ToString() ?? string.Empty;
  193. vm.GetCompressedBitsPixel = profile?.GetValue(ExifTag.CompressedBitsPerPixel)?.Value.ToString() ??
  194. string.Empty;
  195. vm.GetCameraMaker = profile?.GetValue(ExifTag.Make)?.Value ?? string.Empty;
  196. vm.GetCameraModel = profile?.GetValue(ExifTag.Model)?.Value ?? string.Empty;
  197. vm.GetExposureProgram = EXIFHelper.GetExposureProgram(profile);
  198. vm.GetExposureTime = profile?.GetValue(ExifTag.ExposureTime)?.Value.ToString() ?? string.Empty;
  199. vm.GetFNumber = profile?.GetValue(ExifTag.FNumber)?.Value.ToString() ?? string.Empty;
  200. vm.GetMaxAperture = profile?.GetValue(ExifTag.MaxApertureValue)?.Value.ToString() ?? string.Empty;
  201. vm.GetExposureBias = profile?.GetValue(ExifTag.ExposureBiasValue)?.Value.ToString() ?? string.Empty;
  202. vm.GetDigitalZoom = profile?.GetValue(ExifTag.DigitalZoomRatio)?.Value.ToString() ?? string.Empty;
  203. vm.GetFocalLength35Mm = profile?.GetValue(ExifTag.FocalLengthIn35mmFilm)?.Value.ToString() ??
  204. string.Empty;
  205. vm.GetFocalLength = profile?.GetValue(ExifTag.FocalLength)?.Value.ToString() ?? string.Empty;
  206. vm.GetISOSpeed = EXIFHelper.GetISOSpeed(profile);
  207. vm.GetMeteringMode = profile?.GetValue(ExifTag.MeteringMode)?.Value.ToString() ?? string.Empty;
  208. vm.GetContrast = EXIFHelper.GetContrast(profile);
  209. vm.GetSaturation = EXIFHelper.GetSaturation(profile);
  210. vm.GetSharpness = EXIFHelper.GetSharpness(profile);
  211. vm.GetWhiteBalance = EXIFHelper.GetWhiteBalance(profile);
  212. vm.GetFlashMode = EXIFHelper.GetFlashMode(profile);
  213. vm.GetFlashEnergy = profile?.GetValue(ExifTag.FlashEnergy)?.Value.ToString() ?? string.Empty;
  214. vm.GetLightSource = EXIFHelper.GetLightSource(profile);
  215. vm.GetBrightness = profile?.GetValue(ExifTag.BrightnessValue)?.Value.ToString() ?? string.Empty;
  216. vm.GetPhotometricInterpretation = EXIFHelper.GetPhotometricInterpretation(profile);
  217. vm.GetExifVersion = EXIFHelper.GetExifVersion(profile);
  218. vm.GetLensModel = profile?.GetValue(ExifTag.LensModel)?.Value ?? string.Empty;
  219. vm.GetLensMaker = profile?.GetValue(ExifTag.LensMake)?.Value ?? string.Empty;
  220. }
  221. catch (Exception e)
  222. {
  223. #if DEBUG
  224. Console.WriteLine(e);
  225. TooltipHelper.ShowTooltipMessage(e);
  226. #endif
  227. }
  228. }
  229. }