/// <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);
            }
        }
		private static void  standardizeMatrixLineThroughLut(DataBlkFloat inb, float[] out_Renamed, float dwInputMaxValue, LookUpTableFP lut)
		{
			int j = 0;
			float wTemp;
			float[] in_Renamed = (float[]) inb.Data; // input pixel reference
			float[] lutFP = lut.lut;
			
			for (int y = inb.uly; y < inb.uly + inb.h; ++y)
			{
				for (int x = inb.ulx; x < inb.ulx + inb.w; ++x)
				{
					int i = inb.offset + (y - inb.uly) * inb.scanw + (x - inb.ulx); // pixel index.
					if (in_Renamed[i] > dwInputMaxValue)
						wTemp = dwInputMaxValue;
					else if (in_Renamed[i] < 0)
						wTemp = 0;
					else
						wTemp = in_Renamed[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'"
					out_Renamed[j++] = lutFP[(int) wTemp];
				}
			}
		}
		private static void  standardizeMatrixLineThroughLut(DataBlkInt inb, float[] out_Renamed, int dwInputMaxValue, LookUpTableFP lut)
		{
			int wTemp, j = 0;
			int[] in_Renamed = (int[]) inb.Data; // input pixel reference
			float[] lutFP = lut.lut;
			for (int y = inb.uly; y < inb.uly + inb.h; ++y)
			{
				for (int x = inb.ulx; x < inb.ulx + inb.w; ++x)
				{
					int i = inb.offset + (y - inb.uly) * inb.scanw + (x - inb.ulx); // pixel index.
					if (in_Renamed[i] > dwInputMaxValue)
						wTemp = dwInputMaxValue;
					else if (in_Renamed[i] < 0)
						wTemp = 0;
					else
						wTemp = in_Renamed[i];
					out_Renamed[j++] = lutFP[wTemp];
				}
			}
		}
        private static void  standardizeMatrixLineThroughLut(DataBlkFloat inb, float[] out_Renamed, float dwInputMaxValue, LookUpTableFP lut)
        {
            int   j = 0;
            float wTemp;

            float[] in_Renamed = (float[])inb.Data;              // input pixel reference
            float[] lutFP      = lut.lut;

            for (int y = inb.uly; y < inb.uly + inb.h; ++y)
            {
                for (int x = inb.ulx; x < inb.ulx + inb.w; ++x)
                {
                    int i = inb.offset + (y - inb.uly) * inb.scanw + (x - inb.ulx);                     // pixel index.
                    if (in_Renamed[i] > dwInputMaxValue)
                    {
                        wTemp = dwInputMaxValue;
                    }
                    else if (in_Renamed[i] < 0)
                    {
                        wTemp = 0;
                    }
                    else
                    {
                        wTemp = in_Renamed[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'"
                    out_Renamed[j++] = lutFP[(int)wTemp];
                }
            }
        }
        private static void  standardizeMatrixLineThroughLut(DataBlkInt inb, float[] out_Renamed, int dwInputMaxValue, LookUpTableFP lut)
        {
            int wTemp, j = 0;

            int[]   in_Renamed = (int[])inb.Data;            // input pixel reference
            float[] lutFP      = lut.lut;
            for (int y = inb.uly; y < inb.uly + inb.h; ++y)
            {
                for (int x = inb.ulx; x < inb.ulx + inb.w; ++x)
                {
                    int i = inb.offset + (y - inb.uly) * inb.scanw + (x - inb.ulx);                     // pixel index.
                    if (in_Renamed[i] > dwInputMaxValue)
                    {
                        wTemp = dwInputMaxValue;
                    }
                    else if (in_Renamed[i] < 0)
                    {
                        wTemp = 0;
                    }
                    else
                    {
                        wTemp = in_Renamed[i];
                    }
                    out_Renamed[j++] = lutFP[wTemp];
                }
            }
        }
		/// <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);
			}
		}