/// <summary>
        /// Creates a bitmap from this raster using the specified rasterSymbolizer
        /// </summary>
        /// <param name="raster">The raster to draw to a bitmap</param>
        /// <param name="rasterSymbolizer">The raster symbolizer to use for assigning colors</param>
        /// <param name="bitmap">This must be an Format32bbpArgb bitmap that has already been saved to a file so that it exists.</param>
        /// <param name="progressHandler">The progress handler to use.</param>
        /// <returns>A System.Drawing.Bitmap if the operation was successful or null.</returns>
        /// <exception cref="MapWindow.Main.NullLogException">rasterSymbolizer cannot be null</exception>
        public static void DrawToBitmap(this IRaster raster, IRasterSymbolizer rasterSymbolizer, Bitmap bitmap, IProgressHandler progressHandler)
        {
         
            System.Drawing.Imaging.BitmapData bmpData;
            
            if (rasterSymbolizer == null)
            {
                throw new NullLogException("rasterSymbolizer");
            }

            if (rasterSymbolizer.Scheme.Categories == null || rasterSymbolizer.Scheme.Categories.Count == 0) return;

            Rectangle rect = new Rectangle(0, 0, raster.NumColumns, raster.NumRows);
            try
            {
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            catch(Exception ex)
            {
                string originalError = ex.ToString();
                // if they have not saved the bitmap yet, it can cause an exception
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                ms.Position = 0;
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                // any further exceptions should simply throw exceptions to allow easy debugging
            }

            int numBytes = bmpData.Stride * bmpData.Height;
            byte[] rgbData = new byte[numBytes];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbData, 0, numBytes);

            bool useHillShade = false;
            float[][] hillshade = rasterSymbolizer.HillShade;
            if (rasterSymbolizer.ShadedRelief.IsUsed)
            {
                hillshade = rasterSymbolizer.HillShade;
                useHillShade = true;
            }
            Color pixelColor;
            ProgressMeter pm = new ProgressMeter(progressHandler, "Recreating Bitmap", raster.NumRows);

            try
            {
                for (int row = 0; row < raster.NumRows; row++)
                {
                    for (int col = 0; col < raster.NumColumns; col++)
                    {
                        // use the colorbreaks to calculate the colors
                        pixelColor = rasterSymbolizer.GetColor(raster.Value[row, col]);

                        // control transparency here
                        float alpha = rasterSymbolizer.Opacity * 255f;
                        if (alpha > 255f) alpha = 255f;
                        if (alpha < 0f) alpha = 0f;
                        byte a = Convert.ToByte(alpha);
                        byte g;
                        byte r;
                        byte b;
                        if (useHillShade && hillshade != null)
                        {
                            if (hillshade[row][col] == -1 || float.IsNaN(hillshade[row][col]))
                            {
                                pixelColor = rasterSymbolizer.NoDataColor;
                                r = pixelColor.R;
                                g = pixelColor.G;
                                b = pixelColor.B;
                            }
                            else
                            {
                                float red = pixelColor.R * hillshade[row][col];
                                float green = pixelColor.G * hillshade[row][col];
                                float blue = pixelColor.B * hillshade[row][col];
                                if (red > 255f) red = 255f;
                                if (green > 255f) green = 255f;
                                if (blue > 255f) blue = 255f;
                                if (red < 0f) red = 0f;
                                if (green < 0f) green = 0f;
                                if (blue < 0f) blue = 0f;
                                b = Convert.ToByte(blue);
                                r = Convert.ToByte(red);
                                g = Convert.ToByte(green);

                            }
                        }
                        else
                        {
                            r = pixelColor.R;
                            g = pixelColor.G;
                            b = pixelColor.B;
                        }

                        int offset = row * bmpData.Stride + col * 4;
                        rgbData[offset] = b;
                        rgbData[offset + 1] = g;
                        rgbData[offset + 2] = r;
                        rgbData[offset + 3] = a;
                    }
                    pm.CurrentValue = row;
                }
            }
            catch
            {
                System.Diagnostics.Debug.WriteLine(" Unable to write data to raster.");
            }
            pm.Reset();
            if (rasterSymbolizer.IsSmoothed)
            {
                Smoother mySmoother = new Smoother(bmpData, rgbData, progressHandler);
                rgbData = mySmoother.Smooth();
            }


            // Copy the values back into the bitmap
            System.Runtime.InteropServices.Marshal.Copy(rgbData, 0, bmpData.Scan0, numBytes);
            bitmap.UnlockBits(bmpData);
            rasterSymbolizer.ColorSchemeHasUpdated = true;
            return;
        }
        /// <summary>
        /// Creates a bitmap using only the colorscheme, even if a hillshade was specified
        /// </summary>
        /// <param name="raster">The Raster containing values that need to be drawn to the bitmap as a color scheme.</param>
        /// <param name="bitmap">The bitmap to edit.  Ensure that this has been created and saved at least once</param>
        /// <param name="progressHandler">An IProgressHandler</param>
        /// <param name="rasterSymbolizer">The raster symbolizer to use</param>
        /// <exception cref="MapWindow.Main.NullLogException">rasterSymbolizer cannot be null</exception>
        public static void PaintColorSchemeToBitmap(this IRaster raster, IRasterSymbolizer rasterSymbolizer, Bitmap bitmap, IProgressHandler progressHandler)
        {
         
            System.Drawing.Imaging.BitmapData bmpData;
            int numRows = raster.NumRows;
            int numColumns = raster.NumColumns;
            if (rasterSymbolizer == null)
            {
                throw new NullLogException("rasterSymbolizer");
            }

            if (rasterSymbolizer.Scheme.Categories == null || rasterSymbolizer.Scheme.Categories.Count == 0) return;

            // Create a new Bitmap and use LockBits combined with Marshal.Copy to get an array of bytes to work with.

            Rectangle rect = new Rectangle(0, 0, numColumns, numRows);
            try
            {
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            catch
            {
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                ms.Position = 0;
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            int numBytes = bmpData.Stride * bmpData.Height;
            byte[] rgbData = new byte[numBytes];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbData, 0, numBytes);

            Color pixelColor;
            ProgressMeter pm = new ProgressMeter(progressHandler, MessageStrings.PaintingColorScheme, raster.NumRows);
            if (numRows * numColumns < 100000) pm.StepPercent = 50;
            if (numRows * numColumns < 500000) pm.StepPercent = 10;
            if (numRows * numColumns < 1000000) pm.StepPercent = 5;
            for (int row = 0; row < numRows; row++)
            {
                for (int col = 0; col < numColumns; col++)
                {
                    // use the colorbreaks to calculate the colors
                    pixelColor = rasterSymbolizer.GetColor(raster.Value[row, col]);

                    // control transparency here
                    int alpha = Convert.ToInt32(rasterSymbolizer.Opacity * 255);
                    if (alpha > 255) alpha = 255;
                    if (alpha < 0) alpha = 0;
                    byte a = (byte)alpha;


                    byte r = pixelColor.R;
                    byte g = pixelColor.G;
                    byte b = pixelColor.B;

                    int offset = row * bmpData.Stride + col * 4;
                    rgbData[offset] = b;
                    rgbData[offset + 1] = g;
                    rgbData[offset + 2] = r;
                    rgbData[offset + 3] = a;
                }
                pm.CurrentValue = row;
            }
            pm.Reset();
            if (rasterSymbolizer.IsSmoothed)
            {
                Smoother mySmoother = new Smoother(bmpData, rgbData, progressHandler);
                rgbData = mySmoother.Smooth();
            }


            // Copy the values back into the bitmap
            System.Runtime.InteropServices.Marshal.Copy(rgbData, 0, bmpData.Scan0, numBytes);
            bitmap.UnlockBits(bmpData);
            rasterSymbolizer.ColorSchemeHasUpdated = true;
            return;
        }
        /// <summary>
        /// Creates a bitmap based on the specified RasterSymbolizer
        /// </summary>
        /// <returns></returns>
        /// <exception cref="MapWindow.Main.NullLogException">rasterSymbolizer cannot be null</exception>
        public virtual void DrawToBitmap(IRasterSymbolizer rasterSymbolizer, Bitmap bitmap,
                                         IProgressHandler progressHandler)
        {
            Debug.WriteLine("IntRaster Calculated Bitmap");
            BitmapData bmpData;
            if (Data == null) return;

            if (rasterSymbolizer == null)
                throw new NullLogException("rasterSymbolizer");

            if (rasterSymbolizer.Scheme == null || rasterSymbolizer.Scheme.Categories == null || rasterSymbolizer.Scheme.Categories.Count == 0) return;

            // Create a new Bitmap and use LockBits combined with Marshal.Copy to get an array of bytes to work with.

            Rectangle rect = new Rectangle(0, 0, NumColumns, NumRows);
            try
            {
                bmpData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            }
            catch (ArgumentException ex)
            {
                if (ex.ParamName == "format")
                    throw new BitmapFormatException();
                LogManager.DefaultLogManager.Exception(ex);
                throw;
            }
            int numBytes = bmpData.Stride*bmpData.Height;
            byte[] rgbData = new byte[numBytes];
            Marshal.Copy(bmpData.Scan0, rgbData, 0, numBytes);

            bool useHillShade = false;
            float[][] hillshade = rasterSymbolizer.HillShade;
            if (rasterSymbolizer.ShadedRelief.IsUsed)
            {
                hillshade = rasterSymbolizer.HillShade;
                useHillShade = true;
            }
            Color pixelColor;
            ProgressMeter pm = new ProgressMeter(progressHandler, MessageStrings.CreatingTexture, NumRows);
            if (NumRows*NumColumns < 100000) pm.StepPercent = 50;
            if (NumRows*NumColumns < 500000) pm.StepPercent = 10;
            if (NumRows*NumColumns < 1000000) pm.StepPercent = 5;
            for (int row = 0; row < NumRows; row++)
            {
                for (int col = 0; col < NumColumns; col++)
                {
                    // use the colorbreaks to calculate the colors
                    pixelColor = rasterSymbolizer.GetColor(Data[row][col]);

                    // control transparency here
                    int alpha = Convert.ToInt32(rasterSymbolizer.Opacity*255);
                    if (alpha > 255) alpha = 255;
                    if (alpha < 0) alpha = 0;
                    byte a = (byte) alpha;


                    byte r, g, b;
                    if (useHillShade && hillshade != null)
                    {
                        if (hillshade[row][col] == -1)
                        {
                            pixelColor = rasterSymbolizer.NoDataColor;
                            r = pixelColor.R;
                            g = pixelColor.G;
                            b = pixelColor.B;
                        }
                        else
                        {
                            int red = Convert.ToInt32(pixelColor.R*hillshade[row][col]);
                            int green = Convert.ToInt32(pixelColor.G*hillshade[row][col]);
                            int blue = Convert.ToInt32(pixelColor.B*hillshade[row][col]);
                            if (red > 255) red = 255;
                            if (green > 255) green = 255;
                            if (blue > 255) blue = 255;
                            if (red < 0) red = 0;
                            if (green < 0) green = 0;
                            if (blue < 0) blue = 0;
                            b = (byte) blue;
                            r = (byte) red;
                            g = (byte) green;
                        }
                    }
                    else
                    {
                        r = pixelColor.R;
                        g = pixelColor.G;
                        b = pixelColor.B;
                    }

                    int offset = row*bmpData.Stride + col*4;
                    rgbData[offset] = b;
                    rgbData[offset + 1] = g;
                    rgbData[offset + 2] = r;
                    rgbData[offset + 3] = a;
                }
                pm.CurrentValue = row;
            }
            pm.Reset();

            if (rasterSymbolizer.IsSmoothed)
            {
                Smoother sm = new Smoother(bmpData, rgbData, progressHandler);
                rgbData = sm.Smooth();
            }
            // Copy the values back into the bitmap
            Marshal.Copy(rgbData, 0, bmpData.Scan0, numBytes);
            bitmap.UnlockBits(bmpData);

            rasterSymbolizer.ColorSchemeHasUpdated = true;
            return;
        }