Index: ImageViewer/ColorPresentationImage.cs =================================================================== --- ImageViewer/ColorPresentationImage.cs (revision 9089) +++ ImageViewer/ColorPresentationImage.cs (working copy) @@ -39,7 +39,8 @@ /// A colour . /// [Cloneable] - public class ColorPresentationImage : BasicPresentationImage + public class ColorPresentationImage : BasicPresentationImage, + IVoiLutProvider, IModalityLutProvider { #region Private fields @@ -151,7 +152,37 @@ /// public new ColorImageGraphic ImageGraphic { - get { return (ColorImageGraphic)base.ImageGraphic; } - } - } + get { return (ColorImageGraphic)base.ImageGraphic; } + } + + #region IVoiLutProvider and IModalityLutProvider Members + + /// + /// Gets this image's . + /// + public IVoiLutManager VoiLutManager + { + get + { + return this.ImageGraphic.VoiLutManager; + } + } + + + /// + /// Gets this image's modality lut. + /// + public IComposableLut ModalityLut + { + get + { + return this.ImageGraphic.ModalityLut; + } + } + + #endregion + + + } + } Index: ImageViewer/DicomColorPresentationImage.cs =================================================================== --- ImageViewer/DicomColorPresentationImage.cs (revision 9089) +++ ImageViewer/DicomColorPresentationImage.cs (working copy) @@ -32,11 +32,17 @@ using System; using ClearCanvas.Common; using ClearCanvas.Common.Utilities; +using ClearCanvas.Dicom; +using ClearCanvas.Dicom.Iod; using ClearCanvas.ImageViewer.Annotations; using ClearCanvas.ImageViewer.Annotations.Dicom; +using ClearCanvas.ImageViewer.Imaging; using ClearCanvas.ImageViewer.PresentationStates; using ClearCanvas.ImageViewer.StudyManagement; + + + namespace ClearCanvas.ImageViewer { /// @@ -44,7 +50,8 @@ /// [Cloneable] public class DicomColorPresentationImage - : ColorPresentationImage, IImageSopProvider, IDicomSoftcopyPresentationStateProvider + : ColorPresentationImage, IImageSopProvider, + IDicomSoftcopyPresentationStateProvider, IDicomVoiLutsProvider { [CloneIgnore] private IFrameReference _frameReference; @@ -74,6 +81,7 @@ frameReference.Frame.GetNormalizedPixelData) { _frameReference = frameReference; + _dicomVoiLuts = new DicomVoiLuts(this); } /// @@ -84,6 +92,7 @@ { Frame frame = source.Frame; _frameReference = frame.CreateTransientReference(); + _dicomVoiLuts = new DicomVoiLuts(this); } /// @@ -141,6 +150,20 @@ #endregion + + #region IDicomVoiLutsProvider Members + + [CloneIgnore] + private readonly DicomVoiLuts _dicomVoiLuts; + + public IDicomVoiLuts DicomVoiLuts + { + get { return _dicomVoiLuts; } + } + + #endregion + + /// /// Dispose method. Inheritors should override this method to do any additional cleanup. /// Index: ImageViewer/Graphics/ColorImageGraphic.cs =================================================================== --- ImageViewer/Graphics/ColorImageGraphic.cs (revision 9089) +++ ImageViewer/Graphics/ColorImageGraphic.cs (working copy) @@ -31,7 +31,10 @@ using ClearCanvas.Common.Utilities; using ClearCanvas.ImageViewer.Imaging; +using ClearCanvas.Common; +using ClearCanvas.Dicom.Validation; + namespace ClearCanvas.ImageViewer.Graphics { /// @@ -44,8 +47,38 @@ /// opacity (i.e. alpha) of each pixel. /// [Cloneable] - public class ColorImageGraphic : ImageGraphic + public class ColorImageGraphic : ImageGraphic, + IModalityLutProvider, + IVoiLutProvider + { + + private enum Luts + { + Modality = 1, + Voi = 2, + } + + + #region Private fields + + private int _bitsStored; + private int _highBit; + private bool _isSigned; + + private double _rescaleSlope; + private double _rescaleIntercept; + private bool _invert; + + private LutComposer _lutComposer; + private LutFactory _lutFactory; + private IVoiLutManager _voiLutManager; + + private IDataLut _colorMap; + + #endregion + + /// /// Initializes a new instance of /// with the specified image parameters. @@ -60,8 +93,10 @@ public ColorImageGraphic(int rows, int columns) : base(rows, columns, 32) { + Initialize(8, 7, false, 1, 0, false); } + /// /// Initializes a new instance of /// with the specified image parameters. @@ -75,6 +110,7 @@ public ColorImageGraphic(int rows, int columns, byte[] pixelData) : base(rows, columns, 32, pixelData) { + Initialize(8, 7, false, 1, 0, false); } /// @@ -85,7 +121,7 @@ /// /// /// - /// Creates a grayscale image using existing pixel data but does so + /// Creates a color image using existing pixel data but does so /// without ever storing a reference to the pixel data. This is necessary /// to ensure that pixel data can be properly garbage collected in /// any future memory management schemes. @@ -93,6 +129,7 @@ public ColorImageGraphic(int rows, int columns, PixelDataGetter pixelDataGetter) : base(rows, columns, 32, pixelDataGetter) { + Initialize(8, 7, false, 1, 0, false); } /// @@ -125,6 +162,279 @@ return new ColorPixelData(this.Rows, this.Columns, this.PixelDataRaw); else return new ColorPixelData(this.Rows, this.Columns, this.PixelDataGetter); - } - } + } + + #region Public properties + + /// + /// Gets the number of bits stored in the image. + /// + /// + /// The number of bits stored does not necessarily equal the number of bits + /// allocated. Value 8 is typical for RGB Images + /// + public int BitsStored + { + get { return _bitsStored; } + } + + /// + /// Gets the high bit. + /// + /// + /// Theoretically, the high bit does not necessarily have to equal + /// Bits Stored - 1. But in almost all cases this assumption is true; + /// we too make this assumption. + /// + public int HighBit + { + get { return _highBit; } + } + + /// + /// Get a value indicating whether the image's pixel data is signed. + /// + public bool IsSigned + { + get { return _isSigned; } + } + + /// + /// Gets or sets a value indicating whether the image should be inverted. + /// + + public bool Invert + { + get { return _invert; } + set { _invert = value; } + } + + #endregion + + #region IVoiLutProvider and Modality Members + + /// + /// Retrieves the VoiLutManager . + /// + public IVoiLutManager VoiLutManager + { + get + { + if (_voiLutManager == null) + _voiLutManager = new VoiLutManager(this); + + return _voiLutManager; + } + } + + /// + /// Retrieves this image's modality lut. + /// + public IComposableLut ModalityLut + { + get + { + InitializeNecessaryLuts(Luts.Modality); + return this.LutComposer.LutCollection[0]; + } + } + + /// + /// Retrieves this image's Voi Lut. + /// + public IComposableLut VoiLut + { + get + { + InitializeNecessaryLuts(Luts.Voi); + return this.LutComposer.LutCollection[1]; + } + } + + + /// + /// The output lut composed of both the Modality and Voi Luts. + /// + public IComposedLut OutputLut + { + get + { + InitializeNecessaryLuts(Luts.Voi); + return this.LutComposer; + } + } + + + /// + /// Retrieves this image's color map. + /// + public IDataLut ColorMap + { + get + { + if (_colorMap == null) + InstallColorMap(this.LutFactory.GetGrayscaleColorMap()); + + return _colorMap; + } + } + + #endregion + + + #region Private properties + + /// + /// Retrieves LutComposer. + /// + private LutComposer LutComposer + { + get + { + if (_lutComposer == null) + _lutComposer = new LutComposer(); + + return _lutComposer; + } + } + + /// + /// Retrieves LutFactory + /// + private LutFactory LutFactory + { + get + { + if (_lutFactory == null) + _lutFactory = LutFactory.NewInstance; + + return _lutFactory; + } + } + + #endregion + + #region Disposal + + /// + /// Implementation of the pattern + /// + /// True if this object is being disposed, false if it is being finalized + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_lutFactory != null) + _lutFactory.Dispose(); + + if (_lutComposer != null) + _lutComposer.Dispose(); + } + } + + #endregion + + + #region Private methods + + /// + /// Install IComposableLut + /// + /// + + internal void InstallVoiLut(IComposableLut voiLut) + { + Platform.CheckForNullReference(voiLut, "voiLut"); + + InitializeNecessaryLuts(Luts.Modality); + + if (this.LutComposer.LutCollection.Count == 1) + { + this.LutComposer.LutCollection.Add(voiLut); + } + else + { + this.LutComposer.LutCollection[1] = voiLut; + } + } + + /// + /// Initialization of private Variables + /// + /// + /// + /// + /// + /// + /// + private void Initialize( + int bitsStored, + int highBit, + bool isSigned, + double rescaleSlope, + double rescaleIntercept, + bool invert) + { + + _bitsStored = bitsStored; + _highBit = highBit; + _isSigned = isSigned; + _rescaleSlope = rescaleSlope <= double.Epsilon ? 1 : rescaleSlope; + _rescaleIntercept = rescaleIntercept; + _invert = invert; + } + + /// + /// Initialization of Lut if is need. + /// + /// + private void InitializeNecessaryLuts(Luts luts) + { + if (luts >= Luts.Modality && LutComposer.LutCollection.Count == 0) + { + IComposableLut modalityLut = + this.LutFactory.GetModalityLutLinear(this.BitsStored, this.IsSigned, _rescaleSlope, _rescaleIntercept); + + this.LutComposer.LutCollection.Add(modalityLut); + } + + if (luts >= Luts.Voi && LutComposer.LutCollection.Count == 1) + { + IComposableLut lut = InitialVoiLutProvider.Instance.GetLut(this.ParentPresentationImage); + + if (lut == null) + lut = new MinMaxPixelCalculatedLinearLut(this.PixelData, this.ModalityLut); + + InstallVoiLut(lut); + } + } + + /// + /// Install ColorMap by Name + /// + /// + internal void InstallColorMap(string name) + { + InstallColorMap(this.LutFactory.GetColorMap(name)); + } + + + /// + /// Install ColorMap by Interface + /// + /// + internal void InstallColorMap(IDataLut colorMap) + { + if (_colorMap == colorMap) + return; + + _colorMap = colorMap; + } + + #endregion + + + + } + } Index: ImageViewer/Imaging/AlgorithmCalculatedVoiLutLinear.cs =================================================================== --- ImageViewer/Imaging/AlgorithmCalculatedVoiLutLinear.cs (revision 9089) +++ ImageViewer/Imaging/AlgorithmCalculatedVoiLutLinear.cs (working copy) @@ -52,8 +52,11 @@ #region Private Fields [CloneCopyReference] - private readonly GrayscalePixelData _pixelData; - + + private readonly GrayscalePixelData _pixelData = null; + + private readonly ColorPixelData _pixelDatacolor = null; + //allow this to be cloned, since it will just clone the LutFactory's proxy object, anyway. private readonly IComposableLut _modalityLut; @@ -80,7 +83,7 @@ _windowCenter = double.NaN; } - /// + /// /// Constructor. /// /// The pixel data the algorithm will be run on. @@ -89,6 +92,32 @@ { } + /// + /// Constructor for ColorPixelData + /// + /// The pixel data the algorithm will be run on. + /// The modality lut to use for calculating and , if applicable. + protected AlgorithmCalculatedVoiLutLinear(ColorPixelData pixelDatacolor, IComposableLut modalityLut) + { + Platform.CheckForNullReference(pixelDatacolor, "pixelData"); + + _pixelDatacolor = pixelDatacolor; + _modalityLut = modalityLut; + + _windowWidth = 256.0; + _windowCenter = 128.0; + } + + /// + /// Additional Constructor for ColorPixelData + /// + /// The pixel data the algorithm will be run on. + protected AlgorithmCalculatedVoiLutLinear(ColorPixelData pixelDatacolor) + : this(pixelDatacolor, null) + { + } + + /// /// Cloning constructor. /// Index: ImageViewer/Imaging/MinMaxPixelCalculatedLinearLut.cs =================================================================== --- ImageViewer/Imaging/MinMaxPixelCalculatedLinearLut.cs (revision 9089) +++ ImageViewer/Imaging/MinMaxPixelCalculatedLinearLut.cs (working copy) @@ -42,10 +42,10 @@ [Cloneable] public sealed class MinMaxPixelCalculatedLinearLut : AlgorithmCalculatedVoiLutLinear { - #region Public Constructors + #region Constructors /// - /// Constructor. + /// Constructor for GrayscalePixelData /// /// /// The input object can be null. @@ -59,7 +59,7 @@ } /// - /// Constructor. + /// Constructor for GrayscalePixelData /// /// The pixel data the algorithm will be run on. public MinMaxPixelCalculatedLinearLut(GrayscalePixelData pixelData) @@ -67,13 +67,44 @@ { } + /// + /// Constructor for ColorPixelData + /// + /// + /// The input object can be null. + /// + /// The pixel data the algorithm will be run on. + public MinMaxPixelCalculatedLinearLut(ColorPixelData colorpixelData) + : base(colorpixelData) + { + } + + /// + /// Constructor for ColorPixelData + /// + /// + /// The input object can be null. + /// + /// The pixel data the algorithm will be run on. + /// The modality lut to use for calculating + /// and , if applicable. + public MinMaxPixelCalculatedLinearLut(ColorPixelData pixelData, IComposableLut modalityLut) + : base(pixelData, modalityLut) + { + } + + /// + /// Cloning constructor. + /// + /// + /// private MinMaxPixelCalculatedLinearLut(MinMaxPixelCalculatedLinearLut source, ICloningContext context) : base(source, context) { context.CloneFields(source, this); } - #endregion + #endregion #region Overrides Index: ImageViewer/Imaging/VoiLutManager.cs =================================================================== --- ImageViewer/Imaging/VoiLutManager.cs (revision 9089) +++ ImageViewer/Imaging/VoiLutManager.cs (working copy) @@ -37,68 +37,149 @@ internal sealed class VoiLutManager : IVoiLutManager { #region Private Fields - - private GrayscaleImageGraphic _grayscaleImageGraphic; - + + private GrayscaleImageGraphic _grayscaleImageGraphic = null; + + // _colorImageGraphic also IVoiLutManager Provider + private ColorImageGraphic _colorImageGraphic = null; + #endregion + + #region Public Constructors + + /// + /// Constructor for GrayscaleImageGraphic + /// + /// public VoiLutManager(GrayscaleImageGraphic grayscaleImageGraphic) { Platform.CheckForNullReference(grayscaleImageGraphic, "grayscaleImageGraphic"); _grayscaleImageGraphic = grayscaleImageGraphic; - } + } - #region IVoiLutManager Members + /// + /// Constructor for ColorImageGraphic + /// + /// + public VoiLutManager(ColorImageGraphic colorImageGraphic) + { + Platform.CheckForNullReference(colorImageGraphic, "colorImageGraphic"); + _colorImageGraphic = colorImageGraphic; + } + + #endregion + - public IComposableLut GetLut() - { - return _grayscaleImageGraphic.VoiLut; - } + #region IVoiLutManager Members - public void InstallLut(IComposableLut lut) + + public IComposableLut GetLut() { - IComposableLut existingLut = GetLut(); - if (existingLut is IGeneratedDataLut) - { - //Clear the data in the data lut so it's not hanging around using up memory. - ((IGeneratedDataLut)existingLut).Clear(); - } - - _grayscaleImageGraphic.InstallVoiLut(lut); - } + if (_grayscaleImageGraphic != null) + return _grayscaleImageGraphic.VoiLut; + else // ColorImageGraphic was instantiated + return _colorImageGraphic.VoiLut; + } - public bool Invert - { - get { return _grayscaleImageGraphic.Invert; } - set { _grayscaleImageGraphic.Invert = value; } - } + public void InstallLut(IComposableLut lut) + { + IComposableLut existingLut = GetLut(); + if (existingLut is IGeneratedDataLut) + { + //Clear the data in the data lut so it's not hanging around using up memory. + ((IGeneratedDataLut)existingLut).Clear(); + } - public void ToggleInvert() - { - _grayscaleImageGraphic.Invert = !_grayscaleImageGraphic.Invert; - } + if (_grayscaleImageGraphic != null) + _grayscaleImageGraphic.InstallVoiLut(lut); + else // ColorImageGraphic was instantiated + _colorImageGraphic.InstallVoiLut(lut); + } + + public bool Invert + { + get + { + + if (_grayscaleImageGraphic != null) + return _grayscaleImageGraphic.Invert; + else // ColorImageGraphic was instantiated + return _colorImageGraphic.Invert; + + } + set + { + if (_grayscaleImageGraphic != null) + { + _grayscaleImageGraphic.Invert = value; + } + else // ColorImageGraphic was instantiated + { + _colorImageGraphic.Invert = value; + } + } + } + + public void ToggleInvert() + { + if (_grayscaleImageGraphic != null) + { + _grayscaleImageGraphic.Invert = !_grayscaleImageGraphic.Invert; + } + else // ColorImageGraphic was instantiated + { + _colorImageGraphic.Invert = !_colorImageGraphic.Invert; + + } + } + #endregion #region IMemorable Members + + public object CreateMemento() + { + if (_grayscaleImageGraphic != null) + { + return new VoiLutMemento(_grayscaleImageGraphic.VoiLut, _grayscaleImageGraphic.Invert); + } + else // ColorImageGraphic was instantiated + { + return new VoiLutMemento(_colorImageGraphic.VoiLut, _colorImageGraphic.Invert); + } - public object CreateMemento() - { - return new VoiLutMemento(_grayscaleImageGraphic.VoiLut, _grayscaleImageGraphic.Invert); - } + } public void SetMemento(object memento) { - VoiLutMemento lutMemento = memento as VoiLutMemento; - Platform.CheckForInvalidCast(lutMemento, "memento", typeof(VoiLutMemento).Name); + VoiLutMemento lutMemento = memento as VoiLutMemento; + Platform.CheckForInvalidCast(lutMemento, "memento", typeof(VoiLutMemento).Name); - if (_grayscaleImageGraphic.VoiLut != lutMemento.ComposableLutMemento.OriginatingLut) - this.InstallLut(lutMemento.ComposableLutMemento.OriginatingLut); + if (_grayscaleImageGraphic != null) + { - if (lutMemento.ComposableLutMemento.InnerMemento != null) - _grayscaleImageGraphic.VoiLut.SetMemento(lutMemento.ComposableLutMemento.InnerMemento); + if (_grayscaleImageGraphic.VoiLut != lutMemento.ComposableLutMemento.OriginatingLut) + this.InstallLut(lutMemento.ComposableLutMemento.OriginatingLut); - _grayscaleImageGraphic.Invert = lutMemento.Invert; + if (lutMemento.ComposableLutMemento.InnerMemento != null) + _grayscaleImageGraphic.VoiLut.SetMemento(lutMemento.ComposableLutMemento.InnerMemento); + + _grayscaleImageGraphic.Invert = lutMemento.Invert; + } + else // ColorImageGraphic was instantiated + { + if (_colorImageGraphic.VoiLut != lutMemento.ComposableLutMemento.OriginatingLut) + this.InstallLut(lutMemento.ComposableLutMemento.OriginatingLut); + + if (lutMemento.ComposableLutMemento.InnerMemento != null) + _colorImageGraphic.VoiLut.SetMemento(lutMemento.ComposableLutMemento.InnerMemento); + + _colorImageGraphic.Invert = lutMemento.Invert; + + + } } #endregion Index: ImageViewer/Rendering/BilinearInterpolation/BilinearInterpolation.cpp =================================================================== --- ImageViewer/Rendering/BilinearInterpolation/BilinearInterpolation.cpp (revision 9089) +++ ImageViewer/Rendering/BilinearInterpolation/BilinearInterpolation.cpp (working copy) @@ -606,6 +606,7 @@ } } + void InterpolateBilinearRGB( BYTE* pDstPixelData, @@ -627,6 +628,8 @@ float xRatio, float yRatio, + LUTDATA* pLutData, + std::auto_ptr& spxSrcPixels, std::auto_ptr& spdxFixedAtSrcPixelCoordinates) { @@ -666,8 +669,10 @@ int yInterpolated2 = (*pSrcPixel01 << FIXEDPRECISION) + ((dyFixed * ((*pSrcPixel11 - *pSrcPixel01) << FIXEDPRECISION)) >> FIXEDPRECISION); int IFinal = (yInterpolated1 + (((*pdxFixed) * (yInterpolated2 - yInterpolated1)) >> FIXEDPRECISION)) >> FIXEDPRECISION; - pRowDstPixelData[i] = (BYTE)(IFinal); //R(i=0), G(1), B(2), A(3) + // pRowDstPixelData[i] = (BYTE)(IFinal); + pRowDstPixelData[i] = (BYTE)(*(pLutData->LutData + (BYTE)(IFinal) - pLutData->FirstMappedPixelValue)); + pSrcPixel00 += srcNextChannelOffset; } @@ -682,6 +687,10 @@ } + + + + BOOL InterpolateBilinear ( BYTE* pSrcPixelData, @@ -825,8 +834,10 @@ srcNextChannelOffset, xRatio, yRatio, + pLutData, spxSrcPixels, spdxFixedAtSrcPixelCoordinates); + } else { Index: ImageViewer/Rendering/ImageRenderer.cs =================================================================== --- ImageViewer/Rendering/ImageRenderer.cs (revision 9089) +++ ImageViewer/Rendering/ImageRenderer.cs (working copy) @@ -135,7 +135,15 @@ } } } - + /// + /// Render ColorImageGraphic with lutData + /// + /// + /// + /// + /// + /// + /// private static void RenderColor( ColorImageGraphic image, RectangleF srcViewableRectangle, @@ -144,30 +152,49 @@ int dstWidth, int dstBytesPerPixel) { - fixed (byte* pSrcPixelData = image.PixelData.Raw) - { - if (image.InterpolationMode == InterpolationMode.Bilinear) - { - int srcBytesPerPixel = 4; + - ImageInterpolatorBilinear.Interpolate( - srcViewableRectangle, - pSrcPixelData, - image.Columns, - image.Rows, - srcBytesPerPixel, - 32, - dstViewableRectangle, - (byte*)pDstPixelData, - dstWidth, - dstBytesPerPixel, - IsRotated(image), - null, - true, - false, - false); - } - } + fixed (byte* pSrcPixelData = image.PixelData.Raw) + { + if (image.InterpolationMode == InterpolationMode.Bilinear) + { + // int[] finalLutBuffer = ConstructFinalLut(image.OutputLut, image.ColorMap, image.Invert); + + // + // Invert of Color Image is disabled + // + int[] finalLutBuffer = ConstructFinalLut(image.OutputLut, image.ColorMap, false); + + fixed (int* pFinalLutData = finalLutBuffer) + { + ImageInterpolatorBilinear.LutData lutData; + lutData.Data = pFinalLutData; + lutData.FirstMappedPixelData = image.OutputLut.MinInputValue; + lutData.Length = finalLutBuffer.Length; + + int srcBytesPerPixel = 4; + + ImageInterpolatorBilinear.Interpolate( + srcViewableRectangle, + pSrcPixelData, + image.Columns, + image.Rows, + srcBytesPerPixel, + 8, + dstViewableRectangle, + (byte*)pDstPixelData, + dstWidth, + dstBytesPerPixel, + IsRotated(image), + &lutData, //ok because it's a local variable in an unsafe method, therefore it's already fixed. + true, + false, + false); + } + } + } + + } private static bool IsRotated(ImageGraphic imageGraphic) Index: ImageViewer/Tools/Standard/PresetVoiLuts/Luts/AutoVoiLutLinear.cs =================================================================== --- ImageViewer/Tools/Standard/PresetVoiLuts/Luts/AutoVoiLutLinear.cs (revision 9089) +++ ImageViewer/Tools/Standard/PresetVoiLuts/Luts/AutoVoiLutLinear.cs (working copy) @@ -184,9 +184,22 @@ get { return _name; } } + + /// + /// + /// + /// + /// public static bool CanCreateFrom(IDicomVoiLutsProvider provider) { - return provider != null && provider.DicomVoiLuts.ImageVoiLinearLuts.Count > 0; + // + // In the case when Image doesn't have Width and Center + // "DicomVoiLuts.ImageVoiLinearLuts.Count" is zero and function return false + // This case is frequently for RGB images + // The condition "provider.DicomVoiLuts.ImageVoiLinearLuts.Count >= 0" + // is temporary workaround about this problem + // + return provider != null && provider.DicomVoiLuts.ImageVoiLinearLuts.Count >= 0; } public static AutoImageVoiLutLinear CreateFrom(IDicomVoiLutsProvider provider) Index: ImageViewer/Tools/Standard/PresetVoiLuts/Operations/AutoPresetVoiLutOperationComponent.cs =================================================================== --- ImageViewer/Tools/Standard/PresetVoiLuts/Operations/AutoPresetVoiLutOperationComponent.cs (revision 9089) +++ ImageViewer/Tools/Standard/PresetVoiLuts/Operations/AutoPresetVoiLutOperationComponent.cs (working copy) @@ -64,7 +64,15 @@ { get { return (GrayscalePixelData) ((IImageGraphicProvider) _image).ImageGraphic.PixelData; } } + /// + /// Property PixelDataColor for ColorPixelData + /// + private ColorPixelData PixelDataColor + { + get { return (ColorPixelData)((IImageGraphicProvider)_image).ImageGraphic.PixelData; } + } + private IVoiLutManager VoiLutManager { get { return ((IVoiLutProvider) _image).VoiLutManager; } @@ -77,10 +85,28 @@ private MinMaxPixelCalculatedLinearLut GetDefaultMinMaxLut() { - if (IsModalityLutProvider(_image)) - return new MinMaxPixelCalculatedLinearLut(this.PixelData, ((IModalityLutProvider) _image).ModalityLut); - else - return new MinMaxPixelCalculatedLinearLut(this.PixelData); + // + // We have two different cases for DicomGrayscalePresentationImage + // and DicomColorPresentationImage + // + if ((IImageGraphicProvider)_image is DicomGrayscalePresentationImage) + { + + if (IsModalityLutProvider(_image)) + return new MinMaxPixelCalculatedLinearLut(this.PixelData, ((IModalityLutProvider)_image).ModalityLut); + else + return new MinMaxPixelCalculatedLinearLut(this.PixelData); + } + else // _image is DicomColorPresentationImage + { + + if (IsModalityLutProvider(_image)) + return new MinMaxPixelCalculatedLinearLut(this.PixelDataColor, ((IModalityLutProvider)_image).ModalityLut); + else + return new MinMaxPixelCalculatedLinearLut(this.PixelDataColor); + } + + } public IComposableLut GetInitialLut() @@ -223,7 +249,13 @@ public static bool CanCreateFrom(IPresentationImage presentationImage) { - if (IsVoiLutProvider(presentationImage) && IsGrayScaleImage(presentationImage) && IsImageSopProvider(presentationImage)) + // + // RGB Images is also IVoiLutProvider and IDIcomVoiLutProvider. + // Because this the check "IsGrayScaleImage(presentationImage)" is canceled + // + + if ( IsVoiLutProvider(presentationImage) // && IsGrayScaleImage(presentationImage) + && IsImageSopProvider(presentationImage)) { IDicomVoiLutsProvider voiLutsProvider = presentationImage as IDicomVoiLutsProvider; return (AutoImageVoiLutLinear.CanCreateFrom(voiLutsProvider) Index: ImageViewer/Tools/Standard/WindowLevelTool.cs =================================================================== --- ImageViewer/Tools/Standard/WindowLevelTool.cs (revision 9089) +++ ImageViewer/Tools/Standard/WindowLevelTool.cs (working copy) @@ -127,22 +127,22 @@ private void IncrementWindowWidth() { - IncrementWindowWithUndo(10, 0); + IncrementWindowWithUndo(5, 0); } private void DecrementWindowWidth() { - IncrementWindowWithUndo(-10, 0); + IncrementWindowWithUndo(-5, 0); } private void IncrementWindowCenter() { - IncrementWindowWithUndo(0, 10); + IncrementWindowWithUndo(0, 5); } private void DecrementWindowCenter() { - IncrementWindowWithUndo(0, -10); + IncrementWindowWithUndo(0, -5); } private void IncrementWindow(double windowIncrement, double levelIncrement) @@ -210,7 +210,7 @@ { base.Track(mouseInformation); - IncrementWindow(this.DeltaX * 10, this.DeltaY * 10); + IncrementWindow(this.DeltaX * 5, this.DeltaY * 5); return true; }