Пример #1
0
        private void LineAdd_Click(object sender, RoutedEventArgs e)
        {
            if (bitmapArrayWithoutLines == null)
            {
                bitmapArrayWithoutLines = new FastBitmapArray(bitmapArray);
            }
            if (multisamplingForNewLines)
            {
                //bitmapArray.CopyArea(bitmapArrayWithoutLines);

                int scaling = 2;
                bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleUp(scaling);

                var l = new Line(scaling * (int)StartPointX, scaling * (int)StartPointY,
                                 scaling * (int)EndPointX, scaling * (int)EndPointY,
                                 lineColor.ScR, lineColor.ScG, lineColor.ScB, scaling * (int)lineThickness);

                bitmapArrayWithoutLines.DrawLine(l);
                bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleDown(scaling);

                SetBitmapArray(bitmapArrayWithoutLines);
            }
            else
            {
                var l = new Line((int)StartPointX, (int)StartPointY, (int)EndPointX, (int)EndPointY,
                                 lineColor.ScR, lineColor.ScG, lineColor.ScB, (int)lineThickness);

                Lines.Add(l);
                bitmapArray.DrawLine(l);
            }
        }
Пример #2
0
        /// <summary>
        /// Applies this filter in a given circular area of the given FastBitmapArray.
        /// </summary>
        /// <param name="array"></param>
        /// <param name="point"></param>
        /// <param name="diameter"></param>
        /// <param name="mask"></param>
        protected void PaintCircle(FastBitmapArray array, Point point,
                                   int diameter, bool[][] mask)
        {
            int    centerX  = (int)point.X;
            int    centerY  = (int)point.Y;
            double radius   = diameter / 2;
            int    x        = centerX - (int)radius;
            int    y        = centerY - (int)radius;
            int    xEnd     = x + diameter;
            int    yEnd     = y + diameter;
            bool   inBounds = false;

            array.SetBatchArea(x, y, xEnd - 1, yEnd - 1);
            for (int i = x; i < xEnd; i++)
            {
                for (int j = y; j < yEnd; j++)
                {
                    inBounds = i >= 0 && i < array.Width &&
                               j >= 0 && j < array.Height &&
                               (i - centerX) * (i - centerX)
                               + (j - centerY) * (j - centerY) <= radius * radius;

                    if (inBounds && mask[i][j])
                    {
                        FilterWithCorrection(array, i, j);

                        mask[i][j] = false;
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Applies this filter in a given rectangular area of the given FastBitmapArray.
        /// </summary>
        /// <param name="array"></param>
        /// <param name="point"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mask"></param>
        protected void PaintRect(FastBitmapArray array, Point point,
                                 int width, int height, bool[][] mask)
        {
            int  x        = (int)point.X;
            int  y        = (int)point.Y;
            int  xEnd     = x + width;
            int  yEnd     = y + height;
            bool inBounds = false;

            array.SetBatchArea(x, y, xEnd - 1, yEnd - 1);
            for (int i = x; i < xEnd; i++)
            {
                for (int j = y; j < yEnd; j++)
                {
                    inBounds = i >= 0 && i < array.Width &&
                               j >= 0 && j < array.Height;

                    if (inBounds && mask[i][j])
                    {
                        FilterWithCorrection(array, i, j);

                        mask[i][j] = false;
                    }
                }
            }
        }
Пример #4
0
        public void SetBitmapArray(FastBitmapArray array)
        {
            bitmapArray         = array;
            DrawingImage.Source = bitmapArray.GetBitmap(Mask.Disabled);
            DrawingImage.Width  = bitmapArray.Width;
            DrawingImage.Height = bitmapArray.Height;
            ReinitializeMask();

            SendPropertyChanged("MaxPointX");
            SendPropertyChanged("MaxPointY");
        }
Пример #5
0
        public ShapePlayerWnd()
        {
            bitmapArrayLock = new object();
            timersLock      = new object();

            random     = new Random();
            watch      = new Stopwatch();
            stopwatch  = new Stopwatch();
            stopwatch2 = new Stopwatch();

            InitializeComponent();

            bitmapArray = new FastBitmapArray(500, 500, 0.9, 0.9, 0.9);

            sun.Offset(200, 200);
            waves1.Offset(0, 250);
            waves2.Offset(40, 280);
            dolphin.Offset(70, 140);

            try
            {
                rect1 = new Polygon(new Point(20, 20), new Point(20, 80), new Point(80, 80), new Point(80, 20));
                rect2 = rect1.Copy();
                rect2.Offset(30, 30);
                rect3 = rect1.Clip(rect2);

                trig1 = new Polygon(new Point(220, 80), new Point(280, 20), new Point(280, 80));
                trig2 = trig1.Copy();
                trig2.Offset(15, 15);
                trig3 = trig1.Clip(trig2);
            }
            catch (Exception e)
            {
                Trace.WriteLine(e.ToString());
            }

            reinitializeDisplayedBitmap = true;

            timer = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 30), DispatcherPriority.Background,
                                        TimerTick, this.Dispatcher);
            timer.Start();

            timerReport = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 1970), DispatcherPriority.Background,
                                              TimerReportTick, this.Dispatcher);
            timerReport.Start();

            watch.Start();
        }
Пример #6
0
        /// <summary>
        /// Applies the filter at given point of a given FastBitmapArray, using given shape of given size.
        /// </summary>
        /// <param name="array">array on which the filter will be applied</param>
        /// <param name="shape">shape of the brush</param>
        /// <param name="point">central point of the brush</param>
        /// <param name="size"> diameter of the brush</param>
        /// <param name="mask">masking array</param>
        public void ApplyAt(FastBitmapArray array, BrushShapes shape, Point point, int size,
                            bool[][] mask)
        {
            switch (shape)
            {
            case BrushShapes.Fill:
                Fill(array, mask);
                break;

            case BrushShapes.Square:
                PaintRect(array, new Point(point.X - size / 2, point.Y - size / 2), size, size, mask);
                break;

            case BrushShapes.Circle:
                PaintCircle(array, point, size, mask);
                break;
            }
        }
Пример #7
0
        private void DrawingArea_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (sender == null || !(sender is Canvas))
            {
                throw new ArgumentException("expected only Canvas", "sender");
            }

            var canvas = (Canvas)sender;

            if (!canvas.CaptureMouse())
            {
                throw new InvalidOperationException("cannot draw if mouse cannot captured");
            }

            switch (tool)
            {
            case Tools.Filtering:
            {
                //Status = "painting";
                bitmapArrayWithoutLines = null;
                Lines.Clear();
            } break;

            case Tools.Line:
            {
                //Status = "adding line";

                currentLineStart = new Point(e.GetPosition(canvas).X, e.GetPosition(canvas).Y);

                if (bitmapArrayTemp == null)
                {
                    currentLineEnd  = currentLineStart;
                    bitmapArrayTemp = new FastBitmapArray(bitmapArray);
                }
            } break;

            default:
                return;
            }

            keyIsDown = true;

            DrawingArea_MouseDownOrMove(sender, e);
        }
Пример #8
0
        private void UpdateImageSize(int width, int height)
        {
            lock (bitmapArrayLock)
            {
                int oldWidth  = bitmapArray.Width;
                int oldHeight = bitmapArray.Height;

                var newBitmapArray = new FastBitmapArray(width, height);

                //bool smallerWidth = width < oldWidth;
                //bool smallerHeight = height < oldHeight;

                //int diffWidth = width - oldWidth;
                //int diffHeight = height - oldHeight;

                //if (!smallerWidth && !smallerHeight)
                //	bitmapArray.CopyAreaBatch(bitmapArray);

                bitmapArray = newBitmapArray;

                reinitializeDisplayedBitmap = true;
            }
        }
Пример #9
0
        private void FilterWithCorrection(FastBitmapArray /*bitmap*/ array, int x, int y)
        {
            double red   = array.GetRed(x, y);
            double green = array.GetGreen(x, y);
            double blue  = array.GetBlue(x, y);

            double redNew   = FilterRed(red, green, blue);
            double greenNew = FilterGreen(red, green, blue);
            double blueNew  = FilterBlue(red, green, blue);

            if (redNew < 0)
            {
                redNew = 0;
            }
            else if (redNew > 1)
            {
                redNew = 1;
            }
            if (greenNew < 0)
            {
                greenNew = 0;
            }
            else if (greenNew > 1)
            {
                greenNew = 1;
            }
            if (blueNew < 0)
            {
                blueNew = 0;
            }
            else if (blueNew > 1)
            {
                blueNew = 1;
            }

            array.SetPixelBatch(x, y, redNew, greenNew, blueNew);
        }
Пример #10
0
        public FastBitmapArray Process(FastBitmapArray array, ErrorDiffusionKernelName kernelName, int levelsCount)
        {
            if (levelsCount < 2)
            {
                throw new ArgumentException("at least 2 levels are needed");
            }

            var processed = new FastBitmapArray(array.Width, array.Height);

            int levelsCountLess = levelsCount - 1;

            double[] levels = new double[levelsCount];
            // upper bounds for all levels (except for the last level, cos this one is always 1.0)
            double[] levelsBounds = new double[levelsCountLess];
            for (int i = 0; i < levelsCount; ++i)
            {
                levels[i] = ((double)i) / levelsCountLess;
                if (i > 0)
                {
                    levelsBounds[i - 1] = (levels[i - 1] + levels[i]) / 2;
                }
            }

            var matrix        = Matrices[kernelName];
            var matrixSum     = MatricesSums[kernelName];
            var matrixWidth   = matrix[0].Length;
            var matrixHeight  = matrix.Length;
            var currentPixelX = (matrixWidth - 1) / 2;

            for (int y = 0; y < array.Height; ++y)
            {
                for (int x = 0; x < array.Width; ++x)
                {
                    // get color value
                    double red   = array.GetRed(x, y);
                    double green = array.GetGreen(x, y);
                    double blue  = array.GetBlue(x, y);

                    // add error accumulated from previous pixels
                    red   += processed.GetRed(x, y);
                    green += processed.GetGreen(x, y);
                    blue  += processed.GetBlue(x, y);

                    // approximate
                    double redApprox = levels[levelsCountLess];
                    for (int i = 0; i < levelsCountLess; ++i)
                    {
                        if (red < levelsBounds[i])
                        {
                            redApprox = levels[i];
                            break;
                        }
                    }
                    double greenApprox = levels[levelsCountLess];
                    for (int i = 0; i < levelsCountLess; ++i)
                    {
                        if (green < levelsBounds[i])
                        {
                            greenApprox = levels[i];
                            break;
                        }
                    }
                    double blueApprox = levels[levelsCountLess];
                    for (int i = 0; i < levelsCountLess; ++i)
                    {
                        if (blue < levelsBounds[i])
                        {
                            blueApprox = levels[i];
                            break;
                        }
                    }

                    // calculate error
                    double redError   = red - redApprox;
                    double greenError = green - greenApprox;
                    double blueError  = blue - blueApprox;

                    // set current pixel value
                    processed.SetRedBatch(x, y, redApprox);
                    processed.SetGreenBatch(x, y, greenApprox);
                    processed.SetBlueBatch(x, y, blueApprox);

                    // diffuse the arror accross other pixels
                    for (int xx = 0; xx < matrixWidth; ++xx)
                    {
                        for (int yy = 0; yy < matrixHeight; ++yy)
                        {
                            if (yy == 0 && xx <= currentPixelX)
                            {
                                continue;
                            }

                            int xxx = x + xx - currentPixelX;
                            int yyy = y + yy;

                            if (xxx < 0 || xxx >= array.Width || yyy >= array.Height)
                            {
                                continue;
                            }

                            double level = ((double)matrix[yy][xx]) / matrixSum;
                            processed.SetRedBatch(xxx, yyy,
                                                  processed.GetRed(xxx, yyy) + redError * level);
                            processed.SetGreenBatch(xxx, yyy,
                                                    processed.GetGreen(xxx, yyy) + greenError * level);
                            processed.SetBlueBatch(xxx, yyy,
                                                   processed.GetBlue(xxx, yyy) + blueError * level);
                        }
                    }
                }
            }

            processed.SetBatchArea();

            return(processed);
        }
        /// <summary>
        /// Processes the input array.
        /// </summary>
        /// <param name="array"></param>
        /// <param name="matrixSize"></param>
        /// <returns></returns>
        public FastBitmapArray Process(FastBitmapArray array, int matrixSize, int levelsCount)
        {
            #region old approach
            //var processed = new FastBitmapArray(array.Width * matrixSize, array.Height * matrixSize);

            //int procXmin = 0;
            //int procXmax = 0;
            //int procYmin = 0;
            //int procYmax = 0;

            //var matrix = Matrices[matrixSize];
            //var matrixCoef = matrixSize * matrixSize + 1;

            //for (int x = 0; x < array.Width; ++x)
            //{
            //	procXmin = x * matrixSize;
            //	procXmax = procXmin + matrixSize;
            //	for (int y = 0; y < array.Height; ++y)
            //	{
            //		double red = array.GetRed(x, y);
            //		double green = array.GetGreen(x, y);
            //		double blue = array.GetBlue(x, y);

            //		procYmin = y * matrixSize;
            //		procYmax = procYmin + matrixSize;
            //		for (int xx = procXmin, xxx = 0; xx < procXmax; ++xx, ++xxx)
            //			for (int yy = procYmin, yyy = 0; yy < procYmax; ++yy, ++yyy)
            //			{
            //				double matrixValue = ((double)matrix[xxx][yyy]) / matrixCoef;
            //				processed.SetRed(xx, yy, red > matrixValue ? 1 : 0);
            //				processed.SetGreen(xx, yy, green > matrixValue ? 1 : 0);
            //				processed.SetBlue(xx, yy, blue > matrixValue ? 1 : 0);
            //			}
            //	}
            //}
            #endregion

            // new approach:
            var processed = new FastBitmapArray(array.Width, array.Height);

            int levelsCountLess = levelsCount - 1;

            var    matrix      = Matrices[matrixSize];
            var    matrixCoef  = matrixSize * matrixSize + 1;
            double matrixLevel = 1.0 / levelsCountLess;

            double[] levels = new double[levelsCount];
            // upper bounds for all levels (except for the last level, cos this one is always 1.0)
            double[] levelsBounds = new double[levelsCountLess];
            for (int i = 0; i < levelsCount; ++i)
            {
                levels[i] = ((double)i) / levelsCountLess;
                if (i > 0)
                {
                    levelsBounds[i - 1] = (levels[i - 1] + levels[i]) / 2;
                }
                if (i > 0 && i < levelsCount - 1)
                {
                    levels[i] += 0.5 / (levelsCountLess * (matrixCoef - 1) + 1);
                }
            }

            int matrixX = 0;
            int matrixY = 0;

            for (int x = 0; x < array.Width; ++x)
            {
                for (int y = 0; y < array.Height; ++y)
                {
                    double matrixValue = matrixLevel * ((double)matrix[matrixY][matrixX]) / matrixCoef;

                    double red   = array.GetRed(x, y);
                    double green = array.GetGreen(x, y);
                    double blue  = array.GetBlue(x, y);

                    // approximation
                    double redApprox   = processOnePixel(red, levels, levelsBounds, levelsCountLess, matrixValue);
                    double greenApprox = processOnePixel(green, levels, levelsBounds, levelsCountLess, matrixValue);
                    double blueApprox  = processOnePixel(blue, levels, levelsBounds, levelsCountLess, matrixValue);

                    processed.SetRedBatch(x, y, redApprox);
                    processed.SetGreenBatch(x, y, greenApprox);
                    processed.SetBlueBatch(x, y, blueApprox);

                    ++matrixY;
                    if (matrixY == matrixSize)
                    {
                        matrixY = 0;
                    }
                }
                ++matrixX;
                if (matrixX == matrixSize)
                {
                    matrixX = 0;
                }
            }

            processed.SetBatchArea();

            return(processed);
        }
Пример #12
0
        private void OptionGeneratePalette_Click(object sender, RoutedEventArgs e)
        {
            bitmapArray = new FastBitmapArray((int)DrawingScrollView.ViewportWidth, (int)DrawingScrollView.ViewportHeight);

            bitmapArrayWithoutLines = null;

            bitmapArray.SetBatchArea(0, 0, bitmapArray.Width - 1, bitmapArray.Height - 1);

            double xJump    = 1.0 / bitmapArray.Width;
            int    ySegment = bitmapArray.Height / (1 + 3 + 3 + 3 + 3);

            //double xJump = 1.0 / bitmapArray.Width;

            for (int x = 0; x < bitmapArray.Width; ++x)
            {
                int y    = 0;
                int yMax = ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    //bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    //bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    //bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, 1);
                    bitmapArray.SetBlueBatch(x, y, 1);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, 1);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, 1);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, 1);
                    bitmapArray.SetGreenBatch(x, y, 1);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, 1);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, 1);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, 1);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }
            }

            DrawingImage.Source = bitmapArray.GetBitmap(Mask.Disabled);
            DrawingImage.Width  = bitmapArray.Width;
            DrawingImage.Height = bitmapArray.Height;
            ReinitializeMask();

            if (latestFileName != null)
            {
                latestFileName = null;

                OptionReload.IsEnabled = false;
            }
        }
Пример #13
0
        private void DrawingArea_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (sender == null || !(sender is Canvas))
            {
                throw new ArgumentException("expected only Canvas", "sender");
            }

            //Status = "ready";

            var canvas = (Canvas)sender;

            if (!keyIsDown)
            {
                return;
            }

            switch (tool)
            {
            case Tools.Filtering:
            {
                ReinitializeMask();
                DrawingBrush.Visibility = Visibility.Hidden;
            } break;

            case Tools.Line:
            {
                double x = e.GetPosition(canvas).X;
                double y = e.GetPosition(canvas).Y;

                int startX = (int)currentLineStart.X;
                int startY = (int)currentLineStart.Y;
                int endX   = (int)x;
                int endY   = (int)y;

                bitmapArray.CopyArea(bitmapArrayTemp);
                if (bitmapArrayWithoutLines == null)
                {
                    bitmapArrayWithoutLines = new FastBitmapArray(bitmapArray);
                }

                if (multisamplingForNewLines)
                {
                    int scaling = 2;
                    bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleUp(scaling);

                    var l = new Line(scaling * startX, scaling * startY, scaling * endX, scaling * endY,
                                     lineColor.ScR, lineColor.ScG, lineColor.ScB, scaling * (int)lineThickness);

                    bitmapArrayWithoutLines.DrawLine(l);
                    bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleDown(scaling);

                    SetBitmapArray(bitmapArrayWithoutLines);
                }
                else
                {
                    var l = new Line(startX, startY, endX, endY,
                                     lineColor.ScR, lineColor.ScG, lineColor.ScB, (int)lineThickness);

                    bitmapArray.DrawLine(l);
                    bitmapArray.RefreshBitmap(Mask.Disabled);

                    Lines.Add(l);
                }

                bitmapArrayTemp = null;

                //LineAdd.IsEnabled = true;
                //LineUpdate.IsEnabled = true;
            } break;
            }

            if (canvas.IsMouseCaptured)
            {
                canvas.ReleaseMouseCapture();
            }

            if (keyIsDown)
            {
                keyIsDown = false;
            }
        }
Пример #14
0
 /// <summary>
 /// Applies this filter on the whole given FastBitmapArray.
 /// </summary>
 /// <param name="array"></param>
 /// <param name="mask"></param>
 protected void Fill(FastBitmapArray array, bool[][] mask)
 {
     PaintRect(array, new Point(0, 0), array.Width, array.Height, mask);
 }
Пример #15
0
 public void Apply(FastBitmapArray array, bool[][] mask)
 {
     ApplyAt(array, BrushShapes.Fill, new Point(array.Width / 2, array.Width / 2), 20, mask);
 }