ImageLoader.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. //
  5. // Purpose: ImageLoader utility class loads specified image and
  6. // caches it in the memory for the future use.
  7. //
  8. using System;
  9. using System.Collections;
  10. using System.ComponentModel;
  11. using System.ComponentModel.Design;
  12. using System.Drawing;
  13. using System.IO;
  14. using System.Net;
  15. using System.Reflection;
  16. using System.Resources;
  17. using System.Security;
  18. namespace FastReport.DataVisualization.Charting.Utilities
  19. {
  20. using Size = System.Drawing.Size;
  21. /// <summary>
  22. /// ImageLoader utility class loads and returns specified image
  23. /// form the File, URI, Web Request or Chart Resources.
  24. /// Loaded images are stored in the internal hashtable which
  25. /// allows to improve performance if image need to be used
  26. /// several times.
  27. /// </summary>
  28. internal class ImageLoader : IDisposable, IServiceProvider
  29. {
  30. #region Fields
  31. // Image storage
  32. private Hashtable _imageData = null;
  33. // Reference to the service container
  34. private IServiceContainer _serviceContainer = null;
  35. #endregion
  36. #region Constructors and Initialization
  37. /// <summary>
  38. /// Default constructor is not accessible.
  39. /// </summary>
  40. private ImageLoader()
  41. {
  42. }
  43. /// <summary>
  44. /// Default public constructor.
  45. /// </summary>
  46. /// <param name="container">Service container.</param>
  47. public ImageLoader(IServiceContainer container)
  48. {
  49. if(container == null)
  50. {
  51. throw(new ArgumentNullException(SR.ExceptionImageLoaderInvalidServiceContainer));
  52. }
  53. _serviceContainer = container;
  54. }
  55. /// <summary>
  56. /// Returns Image Loader service object
  57. /// </summary>
  58. /// <param name="serviceType">Requested service type.</param>
  59. /// <returns>Image Loader service object.</returns>
  60. [EditorBrowsableAttribute(EditorBrowsableState.Never)]
  61. object IServiceProvider.GetService(Type serviceType)
  62. {
  63. if(serviceType == typeof(ImageLoader))
  64. {
  65. return this;
  66. }
  67. throw (new ArgumentException( SR.ExceptionImageLoaderUnsupportedType( serviceType.ToString())));
  68. }
  69. /// <summary>
  70. /// Dispose images in the hashtable
  71. /// </summary>
  72. public void Dispose()
  73. {
  74. if (_imageData != null)
  75. {
  76. foreach (DictionaryEntry entry in _imageData)
  77. {
  78. if (entry.Value is IDisposable)
  79. {
  80. ((IDisposable)entry.Value).Dispose();
  81. }
  82. }
  83. _imageData = null;
  84. GC.SuppressFinalize(this);
  85. }
  86. }
  87. #endregion
  88. #region Methods
  89. /// <summary>
  90. /// Loads image from URL. Checks if image already loaded (cached).
  91. /// </summary>
  92. /// <param name="imageURL">Image name (FileName, URL, Resource).</param>
  93. /// <returns>Image object.</returns>
  94. public System.Drawing.Image LoadImage(string imageURL)
  95. {
  96. return LoadImage(imageURL, true);
  97. }
  98. /// <summary>
  99. /// Loads image from URL. Checks if image already loaded (cached).
  100. /// </summary>
  101. /// <param name="imageURL">Image name (FileName, URL, Resource).</param>
  102. /// <param name="saveImage">True if loaded image should be saved in cache.</param>
  103. /// <returns>Image object</returns>
  104. public System.Drawing.Image LoadImage(string imageURL, bool saveImage)
  105. {
  106. System.Drawing.Image image = null;
  107. // Check if image is defined in the chart image collection
  108. if (_serviceContainer != null)
  109. {
  110. Chart chart = (Chart)_serviceContainer.GetService(typeof(Chart));
  111. if(chart != null)
  112. {
  113. foreach(NamedImage namedImage in chart.Images)
  114. {
  115. if(namedImage.Name == imageURL)
  116. {
  117. return namedImage.Image;
  118. }
  119. }
  120. }
  121. }
  122. // Create new hashtable
  123. if (_imageData == null)
  124. {
  125. _imageData = new Hashtable(StringComparer.OrdinalIgnoreCase);
  126. }
  127. // First check if image with this name already loaded
  128. if (_imageData.Contains(imageURL))
  129. {
  130. image = (System.Drawing.Image)_imageData[imageURL];
  131. }
  132. // Try to load image from resource
  133. if(image == null)
  134. {
  135. try
  136. {
  137. // Check if resource class type was specified
  138. int columnIndex = imageURL.IndexOf("::", StringComparison.Ordinal);
  139. if (columnIndex > 0)
  140. {
  141. string resourceRootName = imageURL.Substring(0, columnIndex);
  142. string resourceName = imageURL.Substring(columnIndex + 2);
  143. System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager(resourceRootName, Assembly.GetExecutingAssembly());
  144. image = (System.Drawing.Image)(resourceManager.GetObject(resourceName));
  145. }
  146. else if (Assembly.GetEntryAssembly() != null)
  147. {
  148. // Check if resource class type was specified
  149. columnIndex = imageURL.IndexOf(':');
  150. if (columnIndex > 0)
  151. {
  152. string resourceRootName = imageURL.Substring(0, columnIndex);
  153. string resourceName = imageURL.Substring(columnIndex + 1);
  154. System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager(resourceRootName, Assembly.GetEntryAssembly());
  155. image = (Image)(resourceManager.GetObject(resourceName));
  156. }
  157. else
  158. {
  159. // Try to load resource from every type defined in entry assembly
  160. Assembly entryAssembly = Assembly.GetEntryAssembly();
  161. if (entryAssembly != null)
  162. {
  163. foreach (Type type in entryAssembly.GetTypes())
  164. {
  165. System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager(type);
  166. try
  167. {
  168. image = (Image)(resourceManager.GetObject(imageURL));
  169. }
  170. catch (ArgumentNullException)
  171. {
  172. }
  173. catch (MissingManifestResourceException)
  174. {
  175. }
  176. // Check if image was loaded
  177. if (image != null)
  178. {
  179. break;
  180. }
  181. }
  182. }
  183. }
  184. }
  185. }
  186. catch (MissingManifestResourceException)
  187. {
  188. }
  189. }
  190. // Try to load image using the Web Request
  191. if(image == null)
  192. {
  193. Uri imageUri = null;
  194. try
  195. {
  196. // Try to create URI directly from image URL (will work in case of absolute URL)
  197. imageUri = new Uri(imageURL);
  198. }
  199. catch(UriFormatException)
  200. {}
  201. // Load image from file or web resource
  202. if(imageUri != null)
  203. {
  204. try
  205. {
  206. WebRequest request = WebRequest.Create(imageUri);
  207. image = System.Drawing.Image.FromStream(request.GetResponse().GetResponseStream());
  208. }
  209. catch (ArgumentException)
  210. {
  211. }
  212. catch (NotSupportedException)
  213. {
  214. }
  215. catch (SecurityException)
  216. {
  217. }
  218. }
  219. }
  220. // absolute uri(without Server.MapPath)in web is not allowed. Loading from replative uri Server[Page].MapPath is done above.
  221. // Try to load as file
  222. if(image == null)
  223. {
  224. image = LoadFromFile(imageURL);
  225. }
  226. // Error loading image
  227. if(image == null)
  228. {
  229. throw(new ArgumentException( SR.ExceptionImageLoaderIncorrectImageLocation( imageURL ) ) );
  230. }
  231. // Save new image in cache
  232. if(saveImage)
  233. {
  234. _imageData[imageURL] = image;
  235. }
  236. return image;
  237. }
  238. /// <summary>
  239. /// Helper function which loads image from file.
  240. /// </summary>
  241. /// <param name="fileName">File name.</param>
  242. /// <returns>Loaded image or null.</returns>
  243. private System.Drawing.Image LoadFromFile(string fileName)
  244. {
  245. // Try to load image from file
  246. try
  247. {
  248. return System.Drawing.Image.FromFile(fileName);
  249. }
  250. catch(FileNotFoundException)
  251. {
  252. return null;
  253. }
  254. }
  255. /// <summary>
  256. /// Returns the image size taking the image DPI into consideration.
  257. /// </summary>
  258. /// <param name="name">Image name (FileName, URL, Resource).</param>
  259. /// <param name="graphics">Graphics used to calculate the image size.</param>
  260. /// <param name="size">Calculated size.</param>
  261. /// <returns>false if it fails to calculate the size, otherwise true.</returns>
  262. internal bool GetAdjustedImageSize(string name, IGraphics graphics, ref SizeF size)
  263. {
  264. Image image = LoadImage(name);
  265. if (image == null)
  266. return false;
  267. GetAdjustedImageSize(image, graphics, ref size);
  268. return true;
  269. }
  270. /// <summary>
  271. /// Returns the image size taking the image DPI into consideration.
  272. /// </summary>
  273. /// <param name="image">Image for whcih to calculate the size.</param>
  274. /// <param name="graphics">Graphics used to calculate the image size.</param>
  275. /// <param name="size">Calculated size.</param>
  276. internal static void GetAdjustedImageSize(Image image, IGraphics graphics, ref SizeF size)
  277. {
  278. if (graphics != null)
  279. {
  280. //this will work in case the image DPI is specified, otherwise the image DPI will be assumed to be same as the screen DPI
  281. size.Width = image.Width * graphics.DpiX / image.HorizontalResolution;
  282. size.Height = image.Height * graphics.DpiY / image.VerticalResolution;
  283. }
  284. else
  285. {
  286. size.Width = image.Width;
  287. size.Height = image.Height;
  288. }
  289. }
  290. /// <summary>
  291. /// Checks if the image has the same DPI as the graphics object.
  292. /// </summary>
  293. /// <param name="image">Image to be checked.</param>
  294. /// <param name="graphics">Graphics object to be used.</param>
  295. /// <returns>true if they match, otherwise false.</returns>
  296. internal static bool DoDpisMatch(Image image, IGraphics graphics)
  297. {
  298. return graphics.DpiX == image.HorizontalResolution && graphics.DpiY == image.VerticalResolution;
  299. }
  300. internal static Image GetScaledImage(Image image, IGraphics graphics)
  301. {
  302. Bitmap scaledImage = new Bitmap(image, new Size((int)(image.Width * graphics.DpiX / image.HorizontalResolution),
  303. (int)(image.Height * graphics.DpiY / image.VerticalResolution)));
  304. return scaledImage;
  305. }
  306. #endregion
  307. }
  308. }