/// <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; }