Ejemplo n.º 1
0
        public void Render(Image image, Drawable drawable)
        {
            if (image.Selection.Empty)
            {
                return;
            }
            image.UndoGroupStart();
            Tile.CacheDefault(drawable);

            var temp = image.Duplicate();
            var imageRect = image.Bounds;

            var layerPixels = LayerToArray(imageRect, drawable);

            //temp.Selection.Border(1);
            bool selectionNonEmpty;
            var selectionBounds = temp.Selection.Bounds(out selectionNonEmpty);
            var selectionMask = new SelectionMask(temp.Selection);

            //var progress = new Progress(_("Filling the region..."));
            var initArea = selectionMask.Area;

            //init confidance term
            //TODO throw out rgniterator from here
            var pxConfidenceTerm = RegionHelper.FilledMatrix(image.Width, image.Height, 1.0);
            var iter = new RgnIterator(image.Selection, RunMode.Noninteractive);
            iter.IterateSrc(pixel => pxConfidenceTerm[pixel.X, pixel.Y] = selectionMask[pixel.X, pixel.Y] ? 0 : 1);

            int iteration = 0;
            while (!selectionMask.Empty && iteration < _iterations)
            {
                //  initial selection border / target region
                var selectionBorder =
                    RegionHelper.TraceBorder(selectionBounds,
                                             coord => selectionMask[coord.X, coord.Y])
                                .ToList();

                var borderConfidanceValues = NewConfidanceValue(selectionBorder, pxConfidenceTerm, _windowSize);
                var borderGradientValues = GradientValues(selectionBorder, layerPixels, selectionMask, _windowSize).ToList();
                var borderNormals = NormalVectors.CalculateNormals(selectionBorder);
                var borderDataTerms = borderGradientValues.Zip(borderNormals, ComputeDataTerm);
                var borderPriorities = borderConfidanceValues.Zip(borderDataTerms, (c, d) => c * d)
                                                             .ToArray();

                var currentIndex = borderPriorities.MaxIndex();
                var currentPoint = selectionBorder[currentIndex];
                var currentRect = currentPoint.PointCenteredRectangle(_windowSize);
                var currentRegion = new PixelRgn(drawable, currentRect, true, true);

                var minRgnRect = _pixelDistanceCalc.MinDistanceRegion(currentRect, borderGradientValues[currentIndex], layerPixels,
                                                                      selectionMask);
                var minRgn = new PixelRgn(drawable, minRgnRect, false, false);

                var iterator = new RegionIterator(currentRegion, minRgn);
                iterator.ForEach((targetPixel, srcPixel) =>
                    {
                        if (!selectionMask[targetPixel.X, targetPixel.Y])
                        {
                            return;
                        }
                        layerPixels[targetPixel.X, targetPixel.Y] = srcPixel;
                        targetPixel.Set(srcPixel);
                    });
                drawable.Flush();
                drawable.MergeShadow(true);
                drawable.Update(temp.Selection.MaskBounds);

                //update confidance values
                var currentCoords =
                    RegionHelper.Grid(currentRect).Where(coord => selectionMask[coord.X, coord.Y]).ToArray();
                var newConfidanceValues = NewConfidanceValue(currentCoords, pxConfidenceTerm, _windowSize).ToArray();
                foreach (var point in
                    currentCoords.Zip(newConfidanceValues,
                                      (coordinate, confidance) =>
                                      new {Coordinate = coordinate, Confidance = confidance}))
                {
                    pxConfidenceTerm[point.Coordinate.X, point.Coordinate.Y] = point.Confidance;
                }
                // exclude current region pixels from selection
                selectionMask.SetAreaToZero(currentRect);
                //progress.Update((initArea - selectionMask.Area)/(double) initArea);

                iteration++;
                if (iteration == _iterations)
                {
                    selectionBorder =
                    RegionHelper.TraceBorder(selectionBounds,
                                             coord => selectionMask[coord.X, coord.Y])
                                .ToList();
                    var rgn = new PixelRgn(drawable, selectionBounds, true, true);
                    for (int i = 0; i < selectionBorder.Count; i++)
                    {
                        var coord = selectionBorder[i];
                        rgn.SetPixel(new byte[] { (byte)(255), 0, 0, 255 }, coord.X, coord.Y);
                    }

                    drawable.Flush();
                    drawable.MergeShadow(false);
                    drawable.Update(temp.Selection.MaskBounds);
                }
            }
            temp.Delete();
            image.UndoGroupEnd();
        }