/// <summary>
        /// Will convolve the 2-D filter with the source image, producing the output image.
        /// This overload assumes that you are working with files.
        /// </summary>
        /// <param name="SourceFile">A string representing the image file to open.</param>
        /// <param name="DestFile">A string representing the image file to save to.</param>
        /// <param name="filter">A 2D array of floats, row major.  Filter must be smaller than image.</param>
        /// <param name="ShowProgressDialog">Boolean, true to have the function automatically show a dialog.</param>
        /// <param name="ICallBack">A MapWinGIS.ICallback for handling errors and progress messages</param>
        /// <returns>Boolean, false if the process was canceled.</returns>
        public static bool ApplyFilter(string SourceFile, string DestFile, float[,] filter, bool ShowProgressDialog, MapWinGIS.ICallback ICallBack)
        {
            MapWinUtility.Logger.Dbg("ApplyFilter(SourceFile: " + SourceFile + ",\n" +
                                     "            DestFile: " + DestFile + ",\n" +
                                     "            filter: [" + filter.GetUpperBound(0) + ", " + filter.GetUpperBound(1) + "],\n" +
                                     "            ShowProgressDialog: " + ShowProgressDialog.ToString() + ",\n" +
                                     "            ICallback)");
            bool res;

            // Argument checks
            if (SourceFile == null)
            {
                MapWinUtility.Logger.Dbg("Argument Exception: SourceFile cannot be null.");
                throw new ArgumentException("SourceFile cannot be null.");
            }
            if (System.IO.File.Exists(SourceFile) == false)
            {
                MapWinUtility.Logger.Dbg("Argument Exception: SourceFile not found.");
                throw new ArgumentException("SourceFile not found.");
            }
            if (DestFile == null)
            {
                MapWinUtility.Logger.Dbg("Argument Exception: DestFile cannot be null.");
                throw new ArgumentException("DestFile cannot be null.");
            }
            if (System.IO.File.Exists(SourceFile) == true)
            {
                System.IO.File.Delete(DestFile);
            }
            if (filter.GetUpperBound(0) == 0 || filter.GetUpperBound(1) == 0)
            {
                MapWinUtility.Logger.Dbg("Argument Exception: Filter must have values.");
                throw new ArgumentException("Filter must have values.");
            }

            // Check image object
            MapWinGIS.Image SourceImage = new MapWinGIS.Image();
            res = SourceImage.Open(SourceFile, MapWinGIS.ImageType.USE_FILE_EXTENSION, true, null);
            if (res == false)
            {
                MapWinUtility.Logger.Dbg("Application Exception: " + "Attempting to open " + SourceFile + " produced the following error:\n" + SourceImage.get_ErrorMsg(SourceImage.LastErrorCode));
                throw new ApplicationException("Attempting to open " + SourceFile + " produced the following error:\n" + SourceImage.get_ErrorMsg(SourceImage.LastErrorCode));
            }
            // Try to create the output image
            MapWinGIS.Image DestImage = new MapWinGIS.Image();
            res = DestImage.CreateNew(SourceImage.Width, SourceImage.Height);
            if (res == false)
            {
                MapWinUtility.Logger.Dbg("Application Exception: " + "Attempting to create " + DestFile + " produced the following error:\n" + DestImage.get_ErrorMsg(DestImage.LastErrorCode));
                throw new ApplicationException("Attempting to create " + DestFile + " produced the following error:\n" + DestImage.get_ErrorMsg(DestImage.LastErrorCode));
            }
            DestImage.Save(DestFile, false, MapWinGIS.ImageType.USE_FILE_EXTENSION, ICallBack);
            res = Do_ApplyFilter(SourceImage, ref DestImage, filter, ShowProgressDialog, ICallBack);
            DestImage.Close();
            SourceImage.Close();
            MapWinUtility.Logger.Dbg("Finished ApplyFilter");
            return(res);
        }
        /// <summary>
        /// Reprojects an image using the currently defined projective transform.
        /// Be sure to call Derive_Coefficients first.  This loops through point by point
        /// so won't be very fast.
        /// </summary>
        /// <param name="SourceImage">A MapWinGIS.Image object to be transformed</param>
        /// <param name="resultImage">A string representing the destination filename</param>
        /// <param name="ICallBack">A MapWinGIS.ICallback interface for progress messages</param>
        /// <remarks>ArgumentExceptions should be trapped for user error, but other types should be reported as bugs</remarks>
        public void ProjectImage(MapWinGIS.Image SourceImage, string resultImage, MapWinGIS.ICallback ICallBack)
        {
            bool res;

            if (SourceImage == null)
            {
                throw new ArgumentException("Source Image cannot be null.");
            }
            if (resultImage == null)
            {
                resultImage = System.IO.Path.ChangeExtension(SourceImage.Filename, "_Projected" + System.IO.Path.GetExtension(SourceImage.Filename));
            }
            if (Defined == false)
            {
                throw new ApplicationException("You first have to define the coefficients by calling Derive_Coefficients.");
            }
            MapWinGIS.Image DestImage = new MapWinGIS.Image();
            try
            {
                res = DestImage.CreateNew(m_OutputWidth, m_OutputHeight);
            }
            catch
            {
                throw new ApplicationException("The current Image object crashes with images too large to fit in memory.");
            }
            if (res == false)
            {
                throw new ApplicationException("Application Exception when Creating New: " + DestImage.get_ErrorMsg(DestImage.LastErrorCode));
            }
            if (res == false)
            {
                throw new ApplicationException("Image object is having trouble creating a new image.");
            }
            for (int Yprj = 0; Yprj < m_OutputHeight; Yprj++)
            {
                for (int Xprj = 0; Xprj < m_OutputWidth; Xprj++)
                {
                    double X, Y;
                    double X1, Y1;
                    int    Xorig = 0;
                    int    Yorig = 0;

                    X1 = (double)Xprj;
                    Y1 = (double)Yprj;
                    X  = -(b * Y1 - Y1 * h * c + e * c - X1 * e + f * X1 * h - f * b) / (X1 * h * d + b * Y1 * g - b * d - X1 * g * e + a * e - a * Y1 * h);
                    Y  = -(c * Y1 * g + X1 * d - a * Y1 - X1 * g * f - c * d + a * f) / (X1 * h * d + b * Y1 * g - b * d - X1 * g * e + a * e - a * Y1 * h);

                    if (X < 0 || Y < 0 || X > m_InputWidth || Y > m_InputHeight)
                    {
                        continue;
                    }
                    // using nearest neighbors
                    Xorig = rnd(X);
                    Yorig = rnd(Y);

                    int Rowo = (m_InputHeight - 1) - Yorig;
                    int pVal = SourceImage.get_Value(Rowo, Xorig);

                    int row = (m_OutputHeight - 1) - Yprj;
                    DestImage.set_Value(row, Xprj, pVal);
                }
                if (ICallBack != null)
                {
                    ICallBack.Progress("Status", (Yprj * 100) / m_OutputHeight, "Row: " + Yprj.ToString());
                }
            }

            DestImage.dX        = m_OutputCellWidth;
            DestImage.dY        = m_OutputCellHeight;
            DestImage.XllCenter = m_XllCenter;
            DestImage.YllCenter = m_YllCenter;
            string dir = System.IO.Path.GetDirectoryName(resultImage);

            if (!System.IO.Directory.Exists(dir))
            {
                System.IO.Directory.CreateDirectory(dir);
            }
            if (System.IO.Path.GetExtension(resultImage) == ".jpg")
            {
                resultImage = System.IO.Path.ChangeExtension(resultImage, ".bmp");
            }
            res = DestImage.Save(resultImage, true, MapWinGIS.ImageType.USE_FILE_EXTENSION, ICallBack);
            if (res == false)
            {
                throw new ApplicationException(DestImage.get_ErrorMsg(DestImage.LastErrorCode));
            }
            DestImage.SetProjection(SourceImage.GetProjection());
            DestImage.Close();
            if (ICallBack != null)
            {
                ICallBack.Progress("Status", 0, "Saved output as " + DestImage.Filename);
            }
        }