context: #region License
  
  // Copyright (c) 2013, ClearCanvas Inc.
  // All rights reserved.
  // http://www.clearcanvas.ca
  //
  // This file is part of the ClearCanvas RIS/PACS open source project.
  //
  // The ClearCanvas RIS/PACS open source project is free software: you can
  // redistribute it and/or modify it under the terms of the GNU General Public
  // License as published by the Free Software Foundation, either version 3 of the
  // License, or (at your option) any later version.
  //
  // The ClearCanvas RIS/PACS open source project is distributed in the hope that it
  // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
  // Public License for more details.
  //
  // You should have received a copy of the GNU General Public License along with
  // the ClearCanvas RIS/PACS open source project.  If not, see
  // <http://www.gnu.org/licenses/>.
  
  #endregion
  
  using System;
  using System.Collections.Generic;
  using ClearCanvas.Common.Utilities;
  using ClearCanvas.ImageViewer.Common;
  using ClearCanvas.ImageViewer.Imaging;
  
  namespace ClearCanvas.ImageViewer.AdvancedImaging.Fusion
  {
  	public static class AlphaColorMapFactory
  	{
  	    // TODO (CR Apr 2013): I'm not sure this is necessary, and it causes basically a permanent memory leak.
  		private static readonly Dictionary<ICachedColorMapKey, CacheItem> _cache = new Dictionary<ICachedColorMapKey, CacheItem>();
  		private static readonly object _syncLock = new object();
  
  		public static IColorMap GetColorMap(string colorMapName, byte alpha, bool thresholding)
  		{
  			return new CachedColorMapProxy(new AlphaColorMapKey(colorMapName, alpha, thresholding));
  		}
  
  		public static IColorMap GetColorMap(IColorMap colorMap, byte alpha, bool thresholding)
  		{
  			return new CachedColorMapProxy(new CustomAlphaColorMapKey(colorMap, alpha, thresholding));
  		}
  
  		private static CacheItem GetColorMapCacheItem(ICachedColorMapKey key)
  		{
  			lock (_syncLock)
  			{
  				if (_cache.ContainsKey(key))
  					return _cache[key];
  				CacheItem item = new CacheItem(key);
  				_cache[key] = item;
  				return item;
  			}
  		}
  
  		#region ICachedColorMapKey Interface
  
  		private interface ICachedColorMapKey
  		{
  			IColorMap CreateColorMap();
  		}
  
  		#endregion
  
  		#region AlphaColorMapKey Class
  
  		[Cloneable(true)]
  		private class AlphaColorMapKey : ICachedColorMapKey, IEquatable<AlphaColorMapKey>
  		{
  			private readonly string _colorMapName;
  			private readonly byte _alpha;
  			private readonly bool _thresholding;
  
  			/// <summary>
  			/// Cloning constructor.
  			/// </summary>
  			private AlphaColorMapKey() {}
  
  			public AlphaColorMapKey(string colorMapName, byte alpha, bool thresholding)
  				: this()
  			{
  				_colorMapName = colorMapName;
  				_alpha = alpha;
  				_thresholding = thresholding;
  			}
  
  			public IColorMap CreateColorMap()
  			{
  				IColorMap baseColorMap;
  				if (_colorMapName == HotIronColorMapFactory.ColorMapName)
  				{
  					baseColorMap = new HotIronColorMapFactory().Create();
  				}
  				else
  				{
  					using (LutFactory lutFactory = LutFactory.Create())
  					{
  						baseColorMap = lutFactory.GetColorMap(_colorMapName);
  					}
  				}
  
  				return new AlphaColorMap(baseColorMap, _alpha, _thresholding);
  			}
  
  			public override int GetHashCode()
  			{
  				return 0x15BDF4E1 ^ _colorMapName.GetHashCode() ^ _alpha.GetHashCode() ^ _thresholding.GetHashCode();
  			}
  
  			public bool Equals(AlphaColorMapKey other)
  			{
  				return _colorMapName.Equals(other._colorMapName) && _alpha.Equals(other._alpha) && _thresholding.Equals(other._thresholding);
  			}
  
  			public override bool Equals(object obj)
  			{
  				if (obj is AlphaColorMapKey)
  					return Equals((AlphaColorMapKey) obj);
  				return false;
  			}
  
  			public override string ToString()
  			{
  				return String.Format("{0}[alpha={1},thresholding={2}]", _colorMapName, _alpha, _thresholding ? 1 : 0);
  			}
  		}
  
  		#endregion
  
  		#region CustomAlphaColorMapKey Class
  
  		[Cloneable(true)]
  		private class CustomAlphaColorMapKey : ICachedColorMapKey, IEquatable<CustomAlphaColorMapKey>
  		{
  			private readonly IColorMap _colorMap;
  			private readonly byte _alpha;
  			private readonly bool _thresholding;
  
  			/// <summary>
  			/// Cloning constructor.
  			/// </summary>
  			private CustomAlphaColorMapKey() {}
  
  			public CustomAlphaColorMapKey(IColorMap colorMap, byte alpha, bool thresholding)
  				: this()
  			{
  				_colorMap = colorMap;
  				_alpha = alpha;
  				_thresholding = thresholding;
  			}
  
  			public IColorMap CreateColorMap()
  			{
  				return new AlphaColorMap(_colorMap, _alpha, _thresholding);
  			}
  
  			public override int GetHashCode()
  			{
  				return 0x15BDF4E1 ^ _colorMap.GetHashCode() ^ _alpha.GetHashCode() ^ _thresholding.GetHashCode();
  			}
  
  			public bool Equals(CustomAlphaColorMapKey other)
  			{
  				return _colorMap.Equals(other._colorMap) && _alpha.Equals(other._alpha) && _thresholding.Equals(other._thresholding);
  			}
  
  			public override bool Equals(object obj)
  			{
  				if (obj is CustomAlphaColorMapKey)
  					return Equals((CustomAlphaColorMapKey) obj);
  				return false;
  			}
  
  			public override string ToString()
  			{
  				return String.Format("Custom[real={0},alpha={1},thresholding={2}]", _colorMap, _alpha, _thresholding ? 1 : 0);
  			}
  		}
  
  		#endregion
  
  		#region CachedColorMapProxy Class
  
  		[Cloneable(true)]
  		private class CachedColorMapProxy : ColorMapBase
  		{
  			private readonly ICachedColorMapKey _colorMapKey;
  			private int _minInputValue;
  			private int _maxInputValue;
  
  			[CloneIgnore]
  			private CacheItem _cacheItem;
  
  			/// <summary>
  			/// Cloning constructor.
  			/// </summary>
  			private CachedColorMapProxy() {}
  
  			public CachedColorMapProxy(ICachedColorMapKey colorMapKey)
  				: this()
  			{
  				_colorMapKey = colorMapKey;
  			}
  
  			private IColorMap RealColorMap
  			{
  				get
  				{
  					if (_cacheItem == null)
  						_cacheItem = GetColorMapCacheItem(new FullColorMapKey(_colorMapKey, _minInputValue, _maxInputValue));
  					return _cacheItem.RealColorMap;
  				}
  			}
  
  			public override int MinInputValue
  			{
  				get { return _minInputValue; }
  				set
  				{
  					if (value == _minInputValue)
  						return;
  
  					_cacheItem = null;
  					_minInputValue = value;
  					OnLutChanged();
  				}
  			}
  
  			public override int MaxInputValue
  			{
  				get { return _maxInputValue; }
  				set
  				{
  
gt: 					if (value == _maxInputValue)