示例#1
0
        /// <summary>
        /// Returns a gaussian weighted average of pixels centred on a point
        /// </summary>
        /// <param name="Source"></param>
        /// <param name="Coords"></param>
        /// <param name="Radius"></param>
        /// <returns></returns>
        public static Color GetGaussianPixel(Bitmap Source, ProportionPoint Coords, int Radius)
        {
            if ((Radius > MaxGausRadius) || (Radius < 0)) throw new ArgumentOutOfRangeException("Radius", "Radius must be >= 0 and < MaxGausRadius");

            int diameter = 1 + (2 * Radius);
            int centre = Radius + 1;

            double sigma = (double)Radius / 2d;
            Normal dist = new Normal(Radius, sigma);

            // create new bitmap with known PixelFormat
            Bitmap bm = new Bitmap(Source.Width, Source.Height, PixelFormat.Format24bppRgb);
            using (Graphics gr = Graphics.FromImage(bm))
            {
                gr.DrawImage(Source, new Rectangle(0, 0, bm.Width, bm.Height));
            }
            //Source.Dispose();

            // Now we know there are 24 bits per pixel. 24 / 8 (bits / byte) = 3 bytes
            const int BytesPerPixel = 3;

            Color colourPixel;

            int x, y;
            x = (int)Math.Round((double)(Coords.x * (float)bm.Width));
            if (x >= bm.Width) x = bm.Width - 1;
            y = (int)Math.Round((double)(Coords.y * (float)bm.Height));
            if (y >= bm.Height) y = bm.Height - 1;

            int stride;
            byte[] rgbValues = GetBytesFromImage(bm, out stride);
            bm.Dispose();

            int centrePixel = (Math.Abs(stride) * y) + (x * BytesPerPixel);

            if (Radius == 0)
            {
                // get the RGB data from the byte array
                colourPixel = Color.FromArgb(0, rgbValues[centrePixel], rgbValues[centrePixel + 1], rgbValues[centrePixel + 2]);
            }
            else
            {
                // work out where the origin of our sub-region will be
                int TLcorner = centrePixel - (BytesPerPixel * (Radius + (Radius * stride)));
                double weightCumulative = 0;
                double[] rgbCumulative = new double[3] { 0d, 0d, 0d };
                for (int row = 0; row < diameter; row++)
                {
                    for (int col = 0; col < diameter; col++)
                    {
                        // find the start of this pixel
                        int pixelStart = TLcorner + (BytesPerPixel * (col + (row * stride)));
                        int centrePixelStart = pixelStart - (col - Radius);
                        int line = (int)Math.Floor((double)centrePixelStart / (double)stride);

                        // check pixel lies within bound of image
                        if ((pixelStart >= 0) && (pixelStart < rgbValues.Length))
                        {
                            // check pixel hasn't wrapped to different line
                            int lineOfThisPixel = (int)Math.Floor((double)pixelStart / (double)stride);
                            if (line == lineOfThisPixel)
                            {

                                // work out the distance from the centre of the sub-region
                                int relX = Math.Abs((col + 1) - centre);
                                int relY = Math.Abs((row + 1) - centre);
                                double hyp = Math.Sqrt((double)(Math.Pow(relX, 2)) + (Math.Pow(relY, 2)));

                                // get a gaussian weight for this distance
                                double weight = dist.CumulativeDistribution(Radius - hyp);
                                weightCumulative += weight;

                                // add the weighted RGB values to the array
                                for (int p = 0; p < 3; p++)
                                {
                                    rgbCumulative[p] += rgbValues[pixelStart + p] * weight;
                                }
                            }
                        }
                    }
                }
                // compose the resulting color pixel
                byte[] rgbFinal = new byte[3];
                for (int p = 0; p < 3; p++)
                {
                    int final = (int)Math.Round(rgbCumulative[p] / weightCumulative);
                    if (final > 255) final = 255;
                    rgbFinal[p] = (byte)(final & 0xff);
                }
                return Color.FromArgb(0, rgbFinal[0], rgbFinal[1], rgbFinal[2]);
            }

            return colourPixel;
        }
示例#2
0
 public NewPositionEventArgs(ProportionPoint position)
 {
     Position = position;
 }
示例#3
0
 /// <summary>
 /// Returns a single pixel from an image.
 /// </summary>
 /// <param name="i">The image to read from</param>
 /// <param name="p">The proportional location within the image</param>
 /// <returns></returns>
 public static Color GetPixel(Bitmap i, ProportionPoint p)
 {
     return GetGaussianPixel(i, p, 0);
 }