/// <summary>
        /// Reference implementation of the image fusion operator.
        /// </summary>
        private static IPresentationImage Fuse(IPresentationImage baseImage, IPresentationImage overlayImage, IColorMap colorMap, float opacity, bool thresholding)
        {
            Platform.CheckTrue(baseImage is IImageSopProvider, "baseImage must be a IImageSopProvider.");
            Platform.CheckTrue(overlayImage is IImageSopProvider, "overlayImage must be a IImageSopProvider.");
            Platform.CheckTrue(baseImage is IImageGraphicProvider, "baseImage must be a IImageGraphicProvider.");
            Platform.CheckTrue(overlayImage is IImageGraphicProvider, "overlayImage must be a IImageGraphicProvider.");

            var baseImageSopProvider        = (IImageSopProvider)baseImage;
            var baseImageGraphicProvider    = (IImageGraphicProvider)baseImage;
            var overlayImageSopProvider     = (IImageSopProvider)overlayImage;
            var overlayImageGraphicProvider = (IImageGraphicProvider)overlayImage;
            var rows      = baseImageSopProvider.Frame.Rows;
            var cols      = baseImageSopProvider.Frame.Columns;
            var pixelData = new byte[3 * rows * cols];

            colorMap.MinInputValue = ushort.MinValue;
            colorMap.MaxInputValue = ushort.MaxValue;

            // this here is the magic
            baseImageGraphicProvider.ImageGraphic.PixelData.ForEachPixel(
                (n, x, y, i) =>
            {
                // and this is why the base and overlay slices must be unsigned precisely coincident
                var patientLocation   = baseImageSopProvider.Frame.ImagePlaneHelper.ConvertToPatient(new PointF(x, y));
                var overlayCoordinate = overlayImageSopProvider.Frame.ImagePlaneHelper.ConvertToImagePlane(patientLocation);
                var baseValue         = (ushort)baseImageGraphicProvider.ImageGraphic.PixelData.GetPixel(i);
                var overlayValue      = overlayImageGraphicProvider.ImageGraphic.PixelData.GetPixel((int)overlayCoordinate.X, (int)overlayCoordinate.Y);

                // the fusion operator: output = underlyingGrey*(1-alpha) + overlayingColour*(alpha) (see DICOM 2009 PS 3.4 N.2.4.3)
                var compositeColor   = ToRgbVectorFromGrey(baseValue) * (1 - opacity) + ToRgbVector(colorMap[overlayValue]) * opacity;
                pixelData[3 * n]     = (byte)compositeColor.X;
                pixelData[3 * n + 1] = (byte)compositeColor.Y;
                pixelData[3 * n + 2] = (byte)compositeColor.Z;
            });

            var dicomFile = new DicomFile();
            var dataset   = dicomFile.DataSet;

            dataset[DicomTags.PatientId].SetStringValue(baseImageSopProvider.ImageSop.PatientId);
            dataset[DicomTags.PatientsName].SetStringValue(baseImageSopProvider.ImageSop.PatientsName);
            dataset[DicomTags.StudyId].SetStringValue(baseImageSopProvider.ImageSop.StudyId);
            dataset[DicomTags.StudyInstanceUid].SetStringValue(baseImageSopProvider.ImageSop.StudyInstanceUid);
            dataset[DicomTags.SeriesDescription].SetStringValue(baseImageSopProvider.ImageSop.SeriesDescription);
            dataset[DicomTags.SeriesNumber].SetInt32(0, 9001);
            dataset[DicomTags.SeriesInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
            dataset[DicomTags.SopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
            dataset[DicomTags.SopClassUid].SetStringValue(ModalityConverter.ToSopClassUid(Modality.SC));
            dataset[DicomTags.Modality].SetStringValue("SC");
            dataset[DicomTags.FrameOfReferenceUid].SetStringValue(baseImageSopProvider.Frame.FrameOfReferenceUid);
            dataset[DicomTags.ImageOrientationPatient].SetStringValue(baseImageSopProvider.Frame.ImageOrientationPatient.ToString());
            dataset[DicomTags.ImagePositionPatient].SetStringValue(baseImageSopProvider.Frame.ImagePositionPatient.ToString());
            dataset[DicomTags.PixelSpacing].SetStringValue(baseImageSopProvider.Frame.PixelSpacing.ToString());
            dataset[DicomTags.PhotometricInterpretation].SetStringValue("RGB");
            dataset[DicomTags.SamplesPerPixel].SetInt32(0, 3);
            dataset[DicomTags.BitsStored].SetInt32(0, 8);
            dataset[DicomTags.BitsAllocated].SetInt32(0, 8);
            dataset[DicomTags.HighBit].SetInt32(0, 7);
            dataset[DicomTags.PixelRepresentation].SetInt32(0, 0);
            dataset[DicomTags.Rows].SetInt32(0, rows);
            dataset[DicomTags.Columns].SetInt32(0, cols);
            dataset[DicomTags.PixelData].Values  = pixelData;
            dicomFile.MediaStorageSopClassUid    = dataset[DicomTags.SopClassUid];
            dicomFile.MediaStorageSopInstanceUid = dataset[DicomTags.SopInstanceUid];

            using (var sopDataSource = new XSopDataSource(dicomFile))
            {
                return(PresentationImageFactory.Create(new ImageSop(sopDataSource))[0]);
            }
        }
		/// <summary>
		/// Reference implementation of the image fusion operator.
		/// </summary>
		private static IPresentationImage Fuse(IPresentationImage baseImage, IPresentationImage overlayImage, IColorMap colorMap, float opacity, bool thresholding)
		{
			Platform.CheckTrue(baseImage is IImageSopProvider, "baseImage must be a IImageSopProvider.");
			Platform.CheckTrue(overlayImage is IImageSopProvider, "overlayImage must be a IImageSopProvider.");
			Platform.CheckTrue(baseImage is IImageGraphicProvider, "baseImage must be a IImageGraphicProvider.");
			Platform.CheckTrue(overlayImage is IImageGraphicProvider, "overlayImage must be a IImageGraphicProvider.");

			var baseImageSopProvider = (IImageSopProvider) baseImage;
			var baseImageGraphicProvider = (IImageGraphicProvider) baseImage;
			var overlayImageSopProvider = (IImageSopProvider) overlayImage;
			var overlayImageGraphicProvider = (IImageGraphicProvider) overlayImage;
			var rows = baseImageSopProvider.Frame.Rows;
			var cols = baseImageSopProvider.Frame.Columns;
			var pixelData = new byte[3*rows*cols];

			colorMap.MinInputValue = ushort.MinValue;
			colorMap.MaxInputValue = ushort.MaxValue;

			// this here is the magic
			baseImageGraphicProvider.ImageGraphic.PixelData.ForEachPixel(
				(n, x, y, i) =>
					{
						// and this is why the base and overlay slices must be unsigned precisely coincident
						var patientLocation = baseImageSopProvider.Frame.ImagePlaneHelper.ConvertToPatient(new PointF(x, y));
						var overlayCoordinate = overlayImageSopProvider.Frame.ImagePlaneHelper.ConvertToImagePlane(patientLocation);
						var baseValue = (ushort) baseImageGraphicProvider.ImageGraphic.PixelData.GetPixel(i);
						var overlayValue = overlayImageGraphicProvider.ImageGraphic.PixelData.GetPixel((int) overlayCoordinate.X, (int) overlayCoordinate.Y);

						// the fusion operator: output = underlyingGrey*(1-alpha) + overlayingColour*(alpha) (see DICOM 2009 PS 3.4 N.2.4.3)
						var compositeColor = ToRgbVectorFromGrey(baseValue)*(1 - opacity) + ToRgbVector(colorMap[overlayValue])*opacity;
						pixelData[3*n] = (byte) compositeColor.X;
						pixelData[3*n + 1] = (byte) compositeColor.Y;
						pixelData[3*n + 2] = (byte) compositeColor.Z;
					});

			var dicomFile = new DicomFile();
			var dataset = dicomFile.DataSet;
			dataset[DicomTags.PatientId].SetStringValue(baseImageSopProvider.ImageSop.PatientId);
			dataset[DicomTags.PatientsName].SetStringValue(baseImageSopProvider.ImageSop.PatientsName);
			dataset[DicomTags.StudyId].SetStringValue(baseImageSopProvider.ImageSop.StudyId);
			dataset[DicomTags.StudyInstanceUid].SetStringValue(baseImageSopProvider.ImageSop.StudyInstanceUid);
			dataset[DicomTags.SeriesDescription].SetStringValue(baseImageSopProvider.ImageSop.SeriesDescription);
			dataset[DicomTags.SeriesNumber].SetInt32(0, 9001);
			dataset[DicomTags.SeriesInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
			dataset[DicomTags.SopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
			dataset[DicomTags.SopClassUid].SetStringValue(ModalityConverter.ToSopClassUid(Modality.SC));
			dataset[DicomTags.Modality].SetStringValue("SC");
			dataset[DicomTags.FrameOfReferenceUid].SetStringValue(baseImageSopProvider.Frame.FrameOfReferenceUid);
			dataset[DicomTags.ImageOrientationPatient].SetStringValue(baseImageSopProvider.Frame.ImageOrientationPatient.ToString());
			dataset[DicomTags.ImagePositionPatient].SetStringValue(baseImageSopProvider.Frame.ImagePositionPatient.ToString());
			dataset[DicomTags.PixelSpacing].SetStringValue(baseImageSopProvider.Frame.PixelSpacing.ToString());
			dataset[DicomTags.PhotometricInterpretation].SetStringValue("RGB");
			dataset[DicomTags.SamplesPerPixel].SetInt32(0, 3);
			dataset[DicomTags.BitsStored].SetInt32(0, 8);
			dataset[DicomTags.BitsAllocated].SetInt32(0, 8);
			dataset[DicomTags.HighBit].SetInt32(0, 7);
			dataset[DicomTags.PixelRepresentation].SetInt32(0, 0);
			dataset[DicomTags.Rows].SetInt32(0, rows);
			dataset[DicomTags.Columns].SetInt32(0, cols);
			dataset[DicomTags.PixelData].Values = pixelData;
			dicomFile.MediaStorageSopClassUid = dataset[DicomTags.SopClassUid];
			dicomFile.MediaStorageSopInstanceUid = dataset[DicomTags.SopInstanceUid];

			using (var sopDataSource = new XSopDataSource(dicomFile))
			{
				return PresentationImageFactory.Create(new ImageSop(sopDataSource))[0];
			}
		}