PlaylistImageEnhancer.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using MediaBrowser.Common.IO;
  2. using MediaBrowser.Controller.Entities;
  3. using MediaBrowser.Controller.Entities.Audio;
  4. using MediaBrowser.Controller.Entities.TV;
  5. using MediaBrowser.Controller.Playlists;
  6. using MediaBrowser.Controller.Providers;
  7. using MediaBrowser.Model.Drawing;
  8. using MediaBrowser.Model.Entities;
  9. using MoreLinq;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Drawing;
  13. using System.Drawing.Drawing2D;
  14. using System.Drawing.Imaging;
  15. using System.IO;
  16. using System.Linq;
  17. using System.Threading.Tasks;
  18. namespace MediaBrowser.Server.Implementations.Playlists
  19. {
  20. public class PlaylistImageEnhancer : IImageEnhancer
  21. {
  22. private readonly IFileSystem _fileSystem;
  23. public PlaylistImageEnhancer(IFileSystem fileSystem)
  24. {
  25. _fileSystem = fileSystem;
  26. }
  27. public bool Supports(IHasImages item, ImageType imageType)
  28. {
  29. return imageType == ImageType.Primary && item is Playlist;
  30. }
  31. public MetadataProviderPriority Priority
  32. {
  33. get { return MetadataProviderPriority.First; }
  34. }
  35. private List<BaseItem> GetItemsWithImages(IHasImages item)
  36. {
  37. var playlist = (Playlist)item;
  38. var items = playlist.GetManageableItems()
  39. .Select(i =>
  40. {
  41. var subItem = i.Item2;
  42. var episode = subItem as Episode;
  43. if (episode != null)
  44. {
  45. var series = episode.Series;
  46. if (series != null && series.HasImage(ImageType.Primary))
  47. {
  48. return series;
  49. }
  50. }
  51. if (subItem.HasImage(ImageType.Primary))
  52. {
  53. return subItem;
  54. }
  55. var parent = subItem.Parent;
  56. if (parent != null && parent.HasImage(ImageType.Primary))
  57. {
  58. if (parent is MusicAlbum)
  59. {
  60. return parent;
  61. }
  62. }
  63. return null;
  64. })
  65. .Where(i => i != null)
  66. .DistinctBy(i => i.Id)
  67. .ToList();
  68. // Rotate the images no more than once per day
  69. var random = new Random(DateTime.Now.DayOfYear).Next();
  70. return items
  71. .OrderBy(i => random - items.IndexOf(i))
  72. .Take(4)
  73. .OrderBy(i => i.Name)
  74. .ToList();
  75. }
  76. private const string Version = "3";
  77. public string GetConfigurationCacheKey(List<BaseItem> items)
  78. {
  79. return Version + "_" + string.Join(",", items.Select(i => i.Id.ToString("N")).ToArray());
  80. }
  81. public string GetConfigurationCacheKey(IHasImages item, ImageType imageType)
  82. {
  83. var items = GetItemsWithImages(item);
  84. return GetConfigurationCacheKey(items);
  85. }
  86. private const int ImageSize = 800;
  87. public ImageSize GetEnhancedImageSize(IHasImages item, ImageType imageType, int imageIndex, ImageSize originalImageSize)
  88. {
  89. var items = GetItemsWithImages(item);
  90. if (items.Count == 0)
  91. {
  92. return originalImageSize;
  93. }
  94. return new ImageSize
  95. {
  96. Height = ImageSize,
  97. Width = ImageSize
  98. };
  99. }
  100. public async Task<Image> EnhanceImageAsync(IHasImages item, Image originalImage, ImageType imageType, int imageIndex)
  101. {
  102. var items = GetItemsWithImages(item);
  103. if (items.Count == 0)
  104. {
  105. return originalImage;
  106. }
  107. var img = await GetCollage(items).ConfigureAwait(false);
  108. using (originalImage)
  109. {
  110. return img;
  111. }
  112. }
  113. private Task<Image> GetCollage(List<BaseItem> items)
  114. {
  115. return GetCollage(items.Select(i => i.GetImagePath(ImageType.Primary)).ToList());
  116. }
  117. private async Task<Image> GetCollage(List<string> files)
  118. {
  119. if (files.Count < 4)
  120. {
  121. return await GetSingleImage(files).ConfigureAwait(false);
  122. }
  123. const int rows = 2;
  124. const int cols = 2;
  125. const int singleSize = ImageSize / 2;
  126. var index = 0;
  127. var img = new Bitmap(ImageSize, ImageSize, PixelFormat.Format32bppPArgb);
  128. using (var graphics = Graphics.FromImage(img))
  129. {
  130. graphics.CompositingQuality = CompositingQuality.HighQuality;
  131. graphics.SmoothingMode = SmoothingMode.HighQuality;
  132. graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
  133. graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
  134. graphics.CompositingMode = CompositingMode.SourceCopy;
  135. for (var row = 0; row < rows; row++)
  136. {
  137. for (var col = 0; col < cols; col++)
  138. {
  139. var x = col * singleSize;
  140. var y = row * singleSize;
  141. using (var fileStream = _fileSystem.GetFileStream(files[index], FileMode.Open, FileAccess.Read, FileShare.Read, true))
  142. {
  143. using (var memoryStream = new MemoryStream())
  144. {
  145. await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
  146. memoryStream.Position = 0;
  147. using (var imgtemp = Image.FromStream(memoryStream, true, false))
  148. {
  149. graphics.DrawImage(imgtemp, x, y, singleSize, singleSize);
  150. }
  151. }
  152. }
  153. index++;
  154. }
  155. }
  156. }
  157. return img;
  158. }
  159. private Task<Image> GetSingleImage(List<string> files)
  160. {
  161. return GetImage(files[0]);
  162. }
  163. private async Task<Image> GetImage(string file)
  164. {
  165. using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, true))
  166. {
  167. var memoryStream = new MemoryStream();
  168. await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
  169. memoryStream.Position = 0;
  170. return Image.FromStream(memoryStream, true, false);
  171. }
  172. }
  173. }
  174. }