private static void DrawToBitmapT <T>(IRaster raster, T noData, Func <int, int, T> getValue, Func <int, byte> getByte, Action <int, byte> setByte, IRasterSymbolizer rasterSymbolizer, int stride, ProgressMeter pm) where T : struct, IEquatable <T>, IComparable <T> { if (raster == null) { throw new ArgumentNullException(nameof(raster)); } if (rasterSymbolizer == null) { throw new ArgumentNullException(nameof(rasterSymbolizer)); } if (rasterSymbolizer.Scheme.Categories == null || rasterSymbolizer.Scheme.Categories.Count == 0) { return; } float[][] hillshade = null; if (rasterSymbolizer.ShadedRelief.IsUsed) { pm.BaseMessage = "Calculating Shaded Relief"; hillshade = rasterSymbolizer.HillShade ?? raster.CreateHillShadeT(getValue, rasterSymbolizer.ShadedRelief, pm); } pm.BaseMessage = "Calculating Colors"; var sets = GetColorSets <T>(rasterSymbolizer.Scheme.Categories); var noDataColor = Argb.FromColor(rasterSymbolizer.NoDataColor); for (int row = 0; row < raster.NumRows; row++) { for (int col = 0; col < raster.NumColumns; col++) { var value = getValue(row, col); Argb argb; if (value.Equals(noData)) { argb = noDataColor; } else { // Usually values are not random, so check neighboring previous cells for same color int?srcOffset = null; if (col > 0) { if (value.Equals(getValue(row, col - 1))) { srcOffset = Offset(row, col - 1, stride); } } if (srcOffset == null && row > 0) { if (value.Equals(getValue(row - 1, col))) { srcOffset = Offset(row - 1, col, stride); } } if (srcOffset != null) { argb = new Argb(getByte((int)srcOffset + 3), getByte((int)srcOffset + 2), getByte((int)srcOffset + 1), getByte((int)srcOffset)); } else { argb = GetColor(sets, value); } } if (hillshade != null) { if (hillshade[row][col] == -1 || float.IsNaN(hillshade[row][col])) { argb = new Argb(argb.A, noDataColor.R, noDataColor.G, noDataColor.B); } else { var red = (int)(argb.R * hillshade[row][col]); var green = (int)(argb.G * hillshade[row][col]); var blue = (int)(argb.B * hillshade[row][col]); argb = new Argb(argb.A, red, green, blue); } } var offset = Offset(row, col, stride); setByte(offset, argb.B); setByte(offset + 1, argb.G); setByte(offset + 2, argb.R); setByte(offset + 3, argb.A); } pm.Next(); } }