Example #1
0
        private static void PaintColorSchemeToBitmapT <T>(this IRaster raster, T noData, Func <int, int, T> getValue, IRasterSymbolizer rasterSymbolizer, Bitmap bitmap, IProgressHandler progressHandler)
            where T : struct, IEquatable <T>, IComparable <T>
        {
            if (raster == null)
            {
                throw new ArgumentNullException(nameof(raster));
            }
            if (rasterSymbolizer == null)
            {
                throw new ArgumentNullException(nameof(rasterSymbolizer));
            }
            if (bitmap == null)
            {
                throw new ArgumentNullException(nameof(bitmap));
            }

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

            BitmapData bmpData;
            var        numRows    = raster.NumRows;
            var        numColumns = raster.NumColumns;
            var        rect       = new Rectangle(0, 0, numColumns, numRows);

            try
            {
                bmpData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            }
            catch
            {
                var ms = new MemoryStream();
                bitmap.Save(ms, ImageFormat.MemoryBmp);
                ms.Position = 0;
                bmpData     = bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            }

            // Prepare progress meter
            var pm = new ProgressMeter(progressHandler, SymbologyMessageStrings.DesktopRasterExt_PaintingColorScheme, numRows);

            if (numRows * numColumns < 100000)
            {
                pm.StepPercent = 50;
            }
            if (numRows * numColumns < 500000)
            {
                pm.StepPercent = 10;
            }
            if (numRows * numColumns < 1000000)
            {
                pm.StepPercent = 5;
            }

            var sets        = GetColorSets <T>(rasterSymbolizer.Scheme.Categories);
            var noDataColor = Argb.FromColor(rasterSymbolizer.NoDataColor);
            var alpha       = Argb.ByteRange(Convert.ToInt32(rasterSymbolizer.Opacity * 255));
            var ptr         = bmpData.Scan0;

            for (var row = 0; row < numRows; row++)
            {
                for (var col = 0; col < numColumns; col++)
                {
                    var  val = getValue(row, col);
                    Argb argb;
                    if (val.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 (val.Equals(getValue(row, col - 1)))
                            {
                                srcOffset = Offset(row, col - 1, bmpData.Stride);
                            }
                        }

                        if (srcOffset == null && row > 0)
                        {
                            if (val.Equals(getValue(row - 1, col)))
                            {
                                srcOffset = Offset(row - 1, col, bmpData.Stride);
                            }
                        }

                        if (srcOffset != null)
                        {
                            argb = new Argb(Marshal.ReadByte(ptr, (int)srcOffset + 3), Marshal.ReadByte(ptr, (int)srcOffset + 2), Marshal.ReadByte(ptr, (int)srcOffset + 1), Marshal.ReadByte(ptr, (int)srcOffset));
                        }
                        else
                        {
                            var color = GetColor(sets, val);
                            argb = new Argb(alpha, color.R, color.G, color.B);
                        }
                    }

                    var offset = Offset(row, col, bmpData.Stride);
                    Marshal.WriteByte(ptr, offset, argb.B);
                    Marshal.WriteByte(ptr, offset + 1, argb.G);
                    Marshal.WriteByte(ptr, offset + 2, argb.R);
                    Marshal.WriteByte(ptr, offset + 3, argb.A);
                }

                pm.CurrentValue = row;
            }

            pm.Reset();
            if (rasterSymbolizer.IsSmoothed)
            {
                var mySmoother = new Smoother(bmpData.Stride, bmpData.Width, bmpData.Height, bmpData.Scan0, progressHandler);
                mySmoother.Smooth();
            }

            bitmap.UnlockBits(bmpData);
            rasterSymbolizer.ColorSchemeHasUpdated = true;
        }
Example #2
0
        private static Argb GetColor <T>(IEnumerable <ColorSet <T> > sets, T value)
            where T : struct, IComparable <T>
        {
            foreach (var set in sets)
            {
                if (set.Contains(value))
                {
                    if (!set.Gradient)
                    {
                        return(set.Color);
                    }
                    if (set.Min == null || set.Max == null)
                    {
                        return(set.Color);
                    }

                    double lowVal = Convert.ToDouble(set.Min.Value);
                    double range  = Math.Abs(Convert.ToDouble(set.Max.Value) - lowVal);
                    double p      = 0; // the portion of the range, where 0 is LowValue & 1 is HighValue
                    double ht;
                    double dVal = Convert.ToDouble(value);
                    switch (set.GradientModel)
                    {
                    case GradientModel.Linear:
                        p = (dVal - lowVal) / range;
                        break;

                    case GradientModel.Exponential:
                        ht = dVal;
                        if (ht < 1)
                        {
                            ht = 1.0;
                        }
                        if (range > 1)
                        {
                            p = Math.Pow(ht - lowVal, 2) / Math.Pow(range, 2);
                        }
                        else
                        {
                            return(set.Color);
                        }

                        break;

                    case GradientModel.Logarithmic:
                        ht = dVal;
                        if (ht < 1)
                        {
                            ht = 1.0;
                        }
                        if (range > 1.0 && ht - lowVal > 1.0)
                        {
                            p = Math.Log(ht - lowVal) / Math.Log(range);
                        }
                        else
                        {
                            return(set.Color);
                        }

                        break;
                    }

                    return(new Argb(set.MinA + (int)(set.RangeA * p), set.MinR + (int)(set.RangeR * p), set.MinG + (int)(set.RangeG * p), set.MinB + (int)(set.RangeB * p)));
                }
            }

            return(Argb.FromColor(Color.Transparent));
        }
Example #3
0
        private static List <ColorSet <T> > GetColorSets <T>(IEnumerable <IColorCategory> categories)
            where T : struct, IComparable <T>
        {
            var result = new List <ColorSet <T> >();

            foreach (var c in categories)
            {
                var   cs   = new ColorSet <T>();
                Color high = c.HighColor;
                Color low  = c.LowColor;
                cs.Color = Argb.FromColor(low);
                if (high != low)
                {
                    cs.GradientModel = c.GradientModel;
                    cs.Gradient      = true;
                    cs.MinA          = low.A;
                    cs.MinR          = low.R;
                    cs.MinG          = low.G;
                    cs.MinB          = low.B;
                    cs.RangeA        = high.A - cs.MinA;
                    cs.RangeR        = high.R - cs.MinR;
                    cs.RangeG        = high.G - cs.MinG;
                    cs.RangeB        = high.B - cs.MinB;
                }

                cs.Max = Global.MaximumValue <T>();
                var testMax = Convert.ToDouble(cs.Max);
                cs.Min = Global.MinimumValue <T>();
                var testMin = Convert.ToDouble(cs.Min);

                if (c.Range.Maximum != null && c.Range.Maximum < testMax)
                {
                    if (c.Range.Maximum < testMin)
                    {
                        cs.Max = cs.Min;
                    }
                    else
                    {
                        cs.Max = (T)Convert.ChangeType(c.Range.Maximum.Value, typeof(T));
                    }
                }

                if (c.Range.Minimum != null && c.Range.Minimum > testMin)
                {
                    if (c.Range.Minimum > testMax)
                    {
                        cs.Min = Global.MaximumValue <T>();
                    }
                    else
                    {
                        cs.Min = (T)Convert.ChangeType(c.Range.Minimum.Value, typeof(T));
                    }
                }

                cs.MinInclusive = c.Range.MinIsInclusive;
                cs.MaxInclusive = c.Range.MaxIsInclusive;
                result.Add(cs);
            }

            // The normal order uses "overwrite" behavior, so that each color is drawn
            // if it qualifies until all the ranges are tested, overwriting previous.
            // This can be mimicked by going through the sets in reverse and choosing
            // the first that qualifies. For lots of color ranges, opting out of
            // a large portion of the range testing should be faster.
            result.Reverse();
            return(result);
        }
Example #4
0
        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();
            }
        }