/// <summary> Construct the lut from the RestrictedICCProfile.
        ///
        /// </summary>
        /// <param name="ricc">input RestrictedICCProfile
        /// </param>
        /// <param name="dwInputMaxValue">size of the output lut.
        /// </param>
        /// <param name="dwInputShiftValue">value used to shift samples to positive
        /// </param>
        public MonochromeTransformTosRGB(RestrictedICCProfile ricc, int dwInputMaxValue, int dwInputShiftValue)
        {
            if (ricc.Type != RestrictedICCProfile.kMonochromeInput)
            {
                throw new System.ArgumentException("MonochromeTransformTosRGB: wrong type ICCProfile supplied");
            }

            this.dwInputMaxValue = dwInputMaxValue;
            lut  = new short[dwInputMaxValue + 1];
            fLut = LookUpTableFP.createInstance(ricc.trc[ICCProfile.GRAY], dwInputMaxValue + 1);

            // First calculate the value for the shadow region
            int i;

            for (i = 0; ((i <= dwInputMaxValue) && (fLut.lut[i] <= ksRGBShadowCutoff)); i++)
            {
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                lut[i] = (short)(System.Math.Floor(ksRGB8ShadowSlope * (double)fLut.lut[i] + 0.5) - dwInputShiftValue);
            }

            // Now calculate the rest
            for (; i <= dwInputMaxValue; i++)
            {
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                lut[i] = (short)(System.Math.Floor(ksRGB8ScaleAfterExp * System.Math.Pow((double)fLut.lut[i], ksRGBExponent) - ksRGB8ReduceAfterExp + 0.5) - dwInputShiftValue);
            }
        }
        private double[] createMatrix(RestrictedICCProfile ricc, int[] maxValues)
        {
            // Coefficients from the input linear to PCS matrix
            double dfPCS00 = ICCXYZType.XYZToDouble(ricc.colorant[RED].x);
            double dfPCS01 = ICCXYZType.XYZToDouble(ricc.colorant[GREEN].x);
            double dfPCS02 = ICCXYZType.XYZToDouble(ricc.colorant[BLUE].x);
            double dfPCS10 = ICCXYZType.XYZToDouble(ricc.colorant[RED].y);
            double dfPCS11 = ICCXYZType.XYZToDouble(ricc.colorant[GREEN].y);
            double dfPCS12 = ICCXYZType.XYZToDouble(ricc.colorant[BLUE].y);
            double dfPCS20 = ICCXYZType.XYZToDouble(ricc.colorant[RED].z);
            double dfPCS21 = ICCXYZType.XYZToDouble(ricc.colorant[GREEN].z);
            double dfPCS22 = ICCXYZType.XYZToDouble(ricc.colorant[BLUE].z);

            double[] matrix = new double[9];
            matrix[M00] = maxValues[0] * (SRGB00 * dfPCS00 + SRGB01 * dfPCS10 + SRGB02 * dfPCS20);
            matrix[M01] = maxValues[0] * (SRGB00 * dfPCS01 + SRGB01 * dfPCS11 + SRGB02 * dfPCS21);
            matrix[M02] = maxValues[0] * (SRGB00 * dfPCS02 + SRGB01 * dfPCS12 + SRGB02 * dfPCS22);
            matrix[M10] = maxValues[1] * (SRGB10 * dfPCS00 + SRGB11 * dfPCS10 + SRGB12 * dfPCS20);
            matrix[M11] = maxValues[1] * (SRGB10 * dfPCS01 + SRGB11 * dfPCS11 + SRGB12 * dfPCS21);
            matrix[M12] = maxValues[1] * (SRGB10 * dfPCS02 + SRGB11 * dfPCS12 + SRGB12 * dfPCS22);
            matrix[M20] = maxValues[2] * (SRGB20 * dfPCS00 + SRGB21 * dfPCS10 + SRGB22 * dfPCS20);
            matrix[M21] = maxValues[2] * (SRGB20 * dfPCS01 + SRGB21 * dfPCS11 + SRGB22 * dfPCS21);
            matrix[M22] = maxValues[2] * (SRGB20 * dfPCS02 + SRGB21 * dfPCS12 + SRGB22 * dfPCS22);

            return(matrix);
        }
        /// <summary> Construct a 3 component transform based on an input RestricedICCProfile
        /// This transform will pass the input throught a floating point lut (LookUpTableFP),
        /// apply a matrix to the output and finally pass the intermediate buffer through
        /// a 8-bit lut (LookUpTable8).  This operation will be designated (LFP*M*L8) * Data
        /// The operators (LFP*M*L8) are constructed here.  Although the data for
        /// only one component is returned, the transformation must be done for all
        /// components, because the matrix application involves a linear combination of
        /// component input to produce the output.
        /// </summary>
        /// <param name="ricc">input profile
        /// </param>
        /// <param name="dwMaxValue">clipping value for output.
        /// </param>
        /// <param name="dwMaxCols">number of columns to transform
        /// </param>
        /// <param name="dwMaxRows">number of rows to transform
        /// </param>
        public MatrixBasedTransformTosRGB(RestrictedICCProfile ricc, int[] dwMaxValue, int[] dwShiftValue)
        {
            // Assure the proper type profile for this xform.
            if (ricc.Type != RestrictedICCProfile.kThreeCompInput)
            {
                throw new System.ArgumentException("MatrixBasedTransformTosRGB: wrong type ICCProfile supplied");
            }

            int c;             // component index.

            this.dwMaxValue   = dwMaxValue;
            this.dwShiftValue = dwShiftValue;

            // Create the LUTFP from the input profile.
            for (c = 0; c < 3; ++c)
            {
                fLut[c] = LookUpTableFP.createInstance(ricc.trc[c], dwMaxValue[c] + 1);
            }

            // Create the Input linear to PCS matrix
            matrix = createMatrix(ricc, dwMaxValue);             // Create and matrix from the ICC profile.

            // Create the final LUT32
            lut = LookUpTable32LinearSRGBtoSRGB.createInstance(dwMaxValue[0], dwMaxValue[0], ksRGBShadowCutoff, ksRGBShadowSlope, ksRGBScaleAfterExp, ksRGBExponent, ksRGBReduceAfterExp);
        }
		private double[] createMatrix(RestrictedICCProfile ricc, int[] maxValues)
		{
			
			// Coefficients from the input linear to PCS matrix
			double dfPCS00 = ICCXYZType.XYZToDouble(ricc.colorant[RED].x);
			double dfPCS01 = ICCXYZType.XYZToDouble(ricc.colorant[GREEN].x);
			double dfPCS02 = ICCXYZType.XYZToDouble(ricc.colorant[BLUE].x);
			double dfPCS10 = ICCXYZType.XYZToDouble(ricc.colorant[RED].y);
			double dfPCS11 = ICCXYZType.XYZToDouble(ricc.colorant[GREEN].y);
			double dfPCS12 = ICCXYZType.XYZToDouble(ricc.colorant[BLUE].y);
			double dfPCS20 = ICCXYZType.XYZToDouble(ricc.colorant[RED].z);
			double dfPCS21 = ICCXYZType.XYZToDouble(ricc.colorant[GREEN].z);
			double dfPCS22 = ICCXYZType.XYZToDouble(ricc.colorant[BLUE].z);
			
			double[] matrix = new double[9];
			matrix[M00] = maxValues[0] * (SRGB00 * dfPCS00 + SRGB01 * dfPCS10 + SRGB02 * dfPCS20);
			matrix[M01] = maxValues[0] * (SRGB00 * dfPCS01 + SRGB01 * dfPCS11 + SRGB02 * dfPCS21);
			matrix[M02] = maxValues[0] * (SRGB00 * dfPCS02 + SRGB01 * dfPCS12 + SRGB02 * dfPCS22);
			matrix[M10] = maxValues[1] * (SRGB10 * dfPCS00 + SRGB11 * dfPCS10 + SRGB12 * dfPCS20);
			matrix[M11] = maxValues[1] * (SRGB10 * dfPCS01 + SRGB11 * dfPCS11 + SRGB12 * dfPCS21);
			matrix[M12] = maxValues[1] * (SRGB10 * dfPCS02 + SRGB11 * dfPCS12 + SRGB12 * dfPCS22);
			matrix[M20] = maxValues[2] * (SRGB20 * dfPCS00 + SRGB21 * dfPCS10 + SRGB22 * dfPCS20);
			matrix[M21] = maxValues[2] * (SRGB20 * dfPCS01 + SRGB21 * dfPCS11 + SRGB22 * dfPCS21);
			matrix[M22] = maxValues[2] * (SRGB20 * dfPCS02 + SRGB21 * dfPCS12 + SRGB22 * dfPCS22);
			
			return matrix;
		}
		/// <summary> Construct a 3 component transform based on an input RestricedICCProfile
		/// This transform will pass the input throught a floating point lut (LookUpTableFP),
		/// apply a matrix to the output and finally pass the intermediate buffer through
		/// a 8-bit lut (LookUpTable8).  This operation will be designated (LFP*M*L8) * Data
		/// The operators (LFP*M*L8) are constructed here.  Although the data for
		/// only one component is returned, the transformation must be done for all
		/// components, because the matrix application involves a linear combination of
		/// component input to produce the output.
		/// </summary>
		/// <param name="ricc">input profile
		/// </param>
		/// <param name="dwMaxValue">clipping value for output.
		/// </param>
		/// <param name="dwMaxCols">number of columns to transform
		/// </param>
		/// <param name="dwMaxRows">number of rows to transform
		/// </param>
		public MatrixBasedTransformTosRGB(RestrictedICCProfile ricc, int[] dwMaxValue, int[] dwShiftValue)
		{
			
			// Assure the proper type profile for this xform.
			if (ricc.Type != RestrictedICCProfile.kThreeCompInput)
				throw new System.ArgumentException("MatrixBasedTransformTosRGB: wrong type ICCProfile supplied");
			
			int c; // component index.
			this.dwMaxValue = dwMaxValue;
			this.dwShiftValue = dwShiftValue;
			
			// Create the LUTFP from the input profile.
			for (c = 0; c < 3; ++c)
			{
				fLut[c] = LookUpTableFP.createInstance(ricc.trc[c], dwMaxValue[c] + 1);
			}
			
			// Create the Input linear to PCS matrix
			matrix = createMatrix(ricc, dwMaxValue); // Create and matrix from the ICC profile.
			
			// Create the final LUT32
			lut = LookUpTable32LinearSRGBtoSRGB.createInstance(dwMaxValue[0], dwMaxValue[0], ksRGBShadowCutoff, ksRGBShadowSlope, ksRGBScaleAfterExp, ksRGBExponent, ksRGBReduceAfterExp);
		}
		/// <summary> Construct the lut from the RestrictedICCProfile.
		/// 
		/// </summary>
		/// <param name="ricc">input RestrictedICCProfile
		/// </param>
		/// <param name="dwInputMaxValue">size of the output lut.
		/// </param>
		/// <param name="dwInputShiftValue">value used to shift samples to positive
		/// </param>
		public MonochromeTransformTosRGB(RestrictedICCProfile ricc, int dwInputMaxValue, int dwInputShiftValue)
		{
			
			if (ricc.Type != RestrictedICCProfile.kMonochromeInput)
				throw new System.ArgumentException("MonochromeTransformTosRGB: wrong type ICCProfile supplied");
			
			this.dwInputMaxValue = dwInputMaxValue;
			lut = new short[dwInputMaxValue + 1];
			fLut = LookUpTableFP.createInstance(ricc.trc[ICCProfile.GRAY], dwInputMaxValue + 1);
			
			// First calculate the value for the shadow region
			int i;
			for (i = 0; ((i <= dwInputMaxValue) && (fLut.lut[i] <= ksRGBShadowCutoff)); i++)
			{
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				lut[i] = (short) (System.Math.Floor(ksRGB8ShadowSlope * (double) fLut.lut[i] + 0.5) - dwInputShiftValue);
			}
			
			// Now calculate the rest   
			for (; i <= dwInputMaxValue; i++)
			{
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				lut[i] = (short) (System.Math.Floor(ksRGB8ScaleAfterExp * System.Math.Pow((double) fLut.lut[i], ksRGBExponent) - ksRGB8ReduceAfterExp + 0.5) - dwInputShiftValue);
			}
		}