示例#1
0
        private Rectangle[][] SliceUpRegion(PdnRegion region, int sliceCount, Rectangle layerBounds)
        {
            if (sliceCount <= 0)
            {
                throw new ArgumentOutOfRangeException("sliceCount");
            }
            Rectangle[][] rectangleArray  = new Rectangle[sliceCount][];
            Scanline[]    regionScanlines = GetRegionScanlines(region.GetRegionScansReadOnlyInt());
            for (int i = 0; i < sliceCount; i++)
            {
                int num2 = (regionScanlines.Length * i) / sliceCount;
                int num3 = Math.Min(regionScanlines.Length, (regionScanlines.Length * (i + 1)) / sliceCount);
                if (sliceCount > 1)
                {
                    switch (i)
                    {
                    case 0:
                        num3 = Math.Min(num3, num2 + 1);
                        break;

                    case 1:
                        num2 = Math.Min(num2, 1);
                        break;
                    }
                }
                Rectangle[] scans = ScanlinesToRectangles(regionScanlines, num2, num3 - num2);
                for (int j = 0; j < scans.Length; j++)
                {
                    scans[j].Intersect(layerBounds);
                }
                rectangleArray[i] = this.ConsolidateRects(scans);
            }
            return(rectangleArray);
        }
示例#2
0
        private Rectangle[][] SliceUpRegion(PdnRegion region, int sliceCount, Rectangle layerBounds)
        {
            Rectangle[][] slices      = new Rectangle[sliceCount][];
            Rectangle[]   regionRects = region.GetRegionScansReadOnlyInt();
            Scanline[]    regionScans = Utility.GetRegionScans(regionRects);

            for (int i = 0; i < sliceCount; ++i)
            {
                int beginScan = (regionScans.Length * i) / sliceCount;
                int endScan   = Math.Min(regionScans.Length, (regionScans.Length * (i + 1)) / sliceCount);

                // Try to arrange it such that the maximum size of the first region
                // is 1-pixel tall
                if (i == 0)
                {
                    endScan = Math.Min(endScan, beginScan + 1);
                }
                else if (i == 1)
                {
                    beginScan = Math.Min(beginScan, 1);
                }

                Rectangle[] newRects = Utility.ScanlinesToRectangles(regionScans, beginScan, endScan - beginScan);

                for (int j = 0; j < newRects.Length; ++j)
                {
                    newRects[j].Intersect(layerBounds);
                }

                slices[i] = newRects;
            }

            return(slices);
        }
示例#3
0
 /// <summary>
 /// This is a helper function. It allows you to render an effect "in place."
 /// That is, you don't need both a destination and a source Surface.
 /// </summary>
 public void RenderInPlace(RenderArgs srcAndDstArgs, PdnRegion roi)
 {
     using (Surface renderSurface = new Surface(srcAndDstArgs.Surface.Size))
     {
         using (RenderArgs renderArgs = new RenderArgs(renderSurface))
         {
             Rectangle[] scans = roi.GetRegionScansReadOnlyInt();
             Render(null, renderArgs, srcAndDstArgs, scans);
             srcAndDstArgs.Surface.CopySurface(renderSurface, roi);
         }
     }
 }
示例#4
0
        private void RenderGradient(Surface surface, PdnRegion clipRegion, CompositingMode compositingMode,
                                    PointF startPointF, ColorBgra startColor, PointF endPointF, ColorBgra endColor)
        {
            GradientRenderer gr = AppEnvironment.GradientInfo.CreateGradientRenderer();

            gr.StartColor    = startColor;
            gr.EndColor      = endColor;
            gr.StartPoint    = startPointF;
            gr.EndPoint      = endPointF;
            gr.AlphaBlending = (compositingMode == CompositingMode.SourceOver);
            gr.BeforeRender();

            Rectangle[] oldRois = clipRegion.GetRegionScansReadOnlyInt();
            Rectangle[] newRois;

            if (oldRois.Length == 1)
            {
                newRois = new Rectangle[Processor.LogicalCpuCount];
                Utility.SplitRectangle(oldRois[0], newRois);
            }
            else
            {
                newRois = oldRois;
            }

            RenderContext rc = new RenderContext();

            rc.surface  = surface;
            rc.rois     = newRois;
            rc.renderer = gr;

            WaitCallback wc = new WaitCallback(rc.Render);

            for (int i = 0; i < Processor.LogicalCpuCount; ++i)
            {
                if (i == Processor.LogicalCpuCount - 1)
                {
                    wc(BoxedConstants.GetInt32(i));
                }
                else
                {
                    PaintDotNet.Threading.ThreadPool.Global.QueueUserWorkItem(wc, BoxedConstants.GetInt32(i));
                }
            }

            PaintDotNet.Threading.ThreadPool.Global.Drain();
        }
示例#5
0
        private Rectangle[][] SliceUpRegion(PdnRegion region, int sliceCount, Rectangle layerBounds)
        {
            if (sliceCount <= 0)
            {
                throw new ArgumentOutOfRangeException("sliceCount");
            }

            Rectangle[][] slices      = new Rectangle[sliceCount][];
            Rectangle[]   regionRects = region.GetRegionScansReadOnlyInt();
            Scanline[]    regionScans = GetRegionScanlines(regionRects);

            for (int i = 0; i < sliceCount; ++i)
            {
                int beginScan = (regionScans.Length * i) / sliceCount;
                int endScan   = Math.Min(regionScans.Length, (regionScans.Length * (i + 1)) / sliceCount);

                // Try to arrange it such that the maximum size of the first region is 1-pixel tall
                if (sliceCount > 1)
                {
                    if (i == 0)
                    {
                        endScan = Math.Min(endScan, beginScan + 1);
                    }
                    else if (i == 1)
                    {
                        beginScan = Math.Min(beginScan, 1);
                    }
                }

                Rectangle[] newRects = ScanlinesToRectangles(regionScans, beginScan, endScan - beginScan);

                for (int j = 0; j < newRects.Length; ++j)
                {
                    newRects[j].Intersect(layerBounds);
                }

                Rectangle[] consRects = ConsolidateRects(newRects);
                slices[i] = consRects;
            }

            return(slices);
        }
示例#6
0
        private unsafe void DrawOverPoints(Point start, Point finish, ColorBgra colorToReplaceWith, ColorBgra colorBeingReplaced)
        {
            ColorBgra colorAdjusted = ColorBgra.FromColor(Color.Empty);
            byte      dstAlpha;
            ColorBgra colorLifted;

            Rectangle[] rectSelRegions;
            Rectangle   rectBrushArea;
            Rectangle   rectBrushRelativeOffset = new Rectangle(0, 0, 0, 0);

            // special condition for a canvas with no active selection
            // create an array of rectangles with a single rectangle
            // specifying the size of the canvas
            if (Selection.IsEmpty)
            {
                rectSelRegions = new Rectangle[] { DocumentWorkspace.Document.Bounds };
            }
            else
            {
                rectSelRegions = clipRegion.GetRegionScansReadOnlyInt();
            }

            // code ripped off from clone stamp tool
            Point direction = new Point(finish.X - start.X, finish.Y - start.Y);
            float length    = Utility.Magnitude(direction);
            float bw        = AppEnvironment.PenInfo.Width / 2;

            float fInc;

            if (length == 0.0f)
            {
                fInc = float.PositiveInfinity;
            }
            else
            {
                fInc = (float)Math.Sqrt(bw) / length;
            }

            // iterate through all points in the linear stroke
            for (float f = 0; f < 1; f += fInc)
            {
                PointF q = new PointF(finish.X * (1 - f) + f * start.X,
                                      finish.Y * (1 - f) + f * start.Y);

                Point p = Point.Round(q);

                // iterate through all rectangles
                foreach (Rectangle rectSel in rectSelRegions)
                {
                    // set the perimeter values for the rectBrushRegion rectangle
                    // so the area can be intersected with the active
                    // selection individual recSelRegion rectangle.
                    rectBrushArea = new Rectangle(p.X - halfPenWidth, p.Y - halfPenWidth, ceilingPenWidth, ceilingPenWidth);

                    // test the intersection...
                    // the perimeter values of rectBrushRegion (above)
                    // may calculate negative but
                    // *should* always be clipped to acceptable values by
                    // by the following intersection.
                    if (rectBrushArea.IntersectsWith(rectSel))
                    {
                        // a valid intersection was found.
                        // prune the brush rectangle to fit the intersection.
                        rectBrushArea.Intersect(rectSel);
                        for (int y = rectBrushArea.Top; y < rectBrushArea.Bottom; y++)
                        {
                            // create a new rectangle for an offset relative to the
                            // the brush mask
                            rectBrushRelativeOffset.X    = Math.Max(rectSel.X - (p.X - halfPenWidth), 0);
                            rectBrushRelativeOffset.Y    = Math.Max(rectSel.Y - (p.Y - halfPenWidth), 0);
                            rectBrushRelativeOffset.Size = rectBrushArea.Size;

                            ColorBgra *srcBgra;
                            ColorBgra *dstBgra;

                            try
                            {
                                // get the source address of the first pixel from the brush mask.
                                srcBgra = (ColorBgra *)brushRenderArgs.Surface.GetPointAddress(rectBrushRelativeOffset.Left,
                                                                                               rectBrushRelativeOffset.Y + (y - rectBrushArea.Y));

                                // get the address of the pixel we want to change on the canvas.
                                dstBgra = (ColorBgra *)renderArgs.Surface.GetPointAddress(rectBrushArea.Left, y);
                            }

                            catch
                            {
                                return;
                            }

                            for (int x = rectBrushArea.Left; x < rectBrushArea.Right; x++)
                            {
                                if (srcBgra->A != 0)
                                {
                                    colorLifted = *dstBgra;

                                    // hasDrawn is set if a pixel endures color replacement so that
                                    // the placed surface will be left alone, otherwise, the placed
                                    // surface will be discarded
                                    // adjust the channel color up and down based on the difference calculated
                                    // from the source.  These values are clamped to a byte.  It's possible
                                    // that the new color is too dark or too bright to take the whole range

                                    bool boolCIT  = this.IsColorInTolerance(colorLifted, colorBeingReplaced);
                                    bool boolPAAA = false;

                                    if (AppEnvironment.AntiAliasing)
                                    {
                                        boolPAAA = this.IsPointAlreadyAntiAliased(x, y);
                                    }

                                    if (boolCIT || boolPAAA)
                                    {
                                        if (boolPAAA)
                                        {
                                            colorAdjusted = (ColorBgra)AAPoints(x, y);

                                            if (penWidth < 2.0f)
                                            {
                                                colorAdjusted.B = Utility.ClampToByte(colorToReplaceWith.B + (colorAdjusted.B - colorBeingReplaced.B));
                                                colorAdjusted.G = Utility.ClampToByte(colorToReplaceWith.G + (colorAdjusted.G - colorBeingReplaced.G));
                                                colorAdjusted.R = Utility.ClampToByte(colorToReplaceWith.R + (colorAdjusted.R - colorBeingReplaced.R));
                                                colorAdjusted.A = Utility.ClampToByte(colorToReplaceWith.A + (colorAdjusted.A - colorBeingReplaced.A));
                                            }
                                        }
                                        else
                                        {
                                            colorAdjusted.B = Utility.ClampToByte(colorLifted.B + (colorToReplaceWith.B - colorBeingReplaced.B));
                                            colorAdjusted.G = Utility.ClampToByte(colorLifted.G + (colorToReplaceWith.G - colorBeingReplaced.G));
                                            colorAdjusted.R = Utility.ClampToByte(colorLifted.R + (colorToReplaceWith.R - colorBeingReplaced.R));
                                            colorAdjusted.A = Utility.ClampToByte(colorLifted.A + (colorToReplaceWith.A - colorBeingReplaced.A));
                                        }

                                        if ((srcBgra->A != 255) && AppEnvironment.AntiAliasing)
                                        {
                                            colorAdjusted.A = srcBgra->A;
                                            dstAlpha        = dstBgra->A;
                                            *dstBgra = blendOp.Apply(*dstBgra, colorAdjusted);
                                            dstBgra->A = dstAlpha;

                                            if (!this.IsPointAlreadyAntiAliased(x, y))
                                            {
                                                AAPointsAdd(x, y, colorAdjusted);
                                            }
                                        }
                                        else
                                        {
                                            colorAdjusted.A = (*dstBgra).A;
                                            *dstBgra = colorAdjusted;

                                            if (boolPAAA)
                                            {
                                                AAPointsRemove(x, y);
                                            }
                                        }

                                        hasDrawn = true;
                                    }
                                }

                                ++srcBgra;
                                ++dstBgra;
                            }
                        }
                    }
                }
            }
        }
        public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace)
        {
            if (historyWorkspace.Selection.IsEmpty)
            {
                return null;
            }
            else
            {
                PdnRegion selectionRegion = historyWorkspace.Selection.CreateRegion();

                if (selectionRegion.GetArea() == 0)
                {
                    selectionRegion.Dispose();
                    return null;
                }

                SelectionHistoryMemento sha = new SelectionHistoryMemento(StaticName, null, historyWorkspace);
                ReplaceDocumentHistoryMemento rdha = new ReplaceDocumentHistoryMemento(StaticName, null, historyWorkspace);
                Rectangle boundingBox;
                Rectangle[] inverseRegionRects = null;

                boundingBox = Utility.GetRegionBounds(selectionRegion);

                using (PdnRegion inverseRegion = new PdnRegion(boundingBox))
                {
                    inverseRegion.Exclude(selectionRegion);

                    inverseRegionRects = Utility.TranslateRectangles(
                        inverseRegion.GetRegionScansReadOnlyInt(),
                        -boundingBox.X,
                        -boundingBox.Y);
                }

                selectionRegion.Dispose();
                selectionRegion = null;

                Document oldDocument = historyWorkspace.Document; // TODO: serialize this to disk so we don't *have* to store the full thing
                Document newDocument = new Document(boundingBox.Width, boundingBox.Height);

                // copy the document's meta data over
                newDocument.ReplaceMetaDataFrom(oldDocument);

                foreach (Layer layer in oldDocument.Layers)
                {
                    if (layer is BitmapLayer)
                    {
                        BitmapLayer oldLayer = (BitmapLayer)layer;
                        Surface croppedSurface = oldLayer.Surface.CreateWindow(boundingBox);
                        BitmapLayer newLayer = new BitmapLayer(croppedSurface);

                        ColorBgra clearWhite = ColorBgra.White.NewAlpha(0);

                        foreach (Rectangle rect in inverseRegionRects)
                        {
                            newLayer.Surface.Clear(rect, clearWhite);
                        }

                        newLayer.LoadProperties(oldLayer.SaveProperties());
                        newDocument.Layers.Add(newLayer);
                    }
                    else
                    {
                        throw new InvalidOperationException("Crop does not support Layers that are not BitmapLayers");
                    }
                }

                CompoundHistoryMemento cha = new CompoundHistoryMemento(
                    StaticName,
                    PdnResources.GetImageResource("Icons.MenuImageCropIcon.png"),
                    new HistoryMemento[] { sha, rdha });

                EnterCriticalRegion();
                historyWorkspace.Document = newDocument;

                return cha;
            }
        }
示例#8
0
        private static unsafe void LoadOrSaveSurfaceRegion(FileStream fileHandle, Surface surface, PdnRegion region, bool trueForSave)
        {
            Rectangle[] scans         = region.GetRegionScansReadOnlyInt();
            Rectangle   regionBounds  = region.GetBoundsInt();
            Rectangle   surfaceBounds = surface.Bounds;
            int         scanCount     = 0;

            void *[] ppvBuffers;
            uint[]   lengths;

            regionBounds.Intersect(surfaceBounds);
            long length = (long)regionBounds.Width * (long)regionBounds.Height * (long)ColorBgra.SizeOf;

            if (scans.Length == 1 &&
                length <= uint.MaxValue &&
                surface.IsContiguousMemoryRegion(regionBounds))
            {
                ppvBuffers = new void *[1];
                lengths    = new uint[1];

                ppvBuffers[0] = surface.GetPointAddressUnchecked(regionBounds.Location);
                lengths[0]    = (uint)length;
            }
            else
            {
                for (int i = 0; i < scans.Length; ++i)
                {
                    Rectangle rect = scans[i];
                    rect.Intersect(surfaceBounds);

                    if (rect.Width != 0 && rect.Height != 0)
                    {
                        scanCount += rect.Height;
                    }
                }

                int scanIndex = 0;
                ppvBuffers = new void *[scanCount];
                lengths    = new uint[scanCount];

                for (int i = 0; i < scans.Length; ++i)
                {
                    Rectangle rect = scans[i];
                    rect.Intersect(surfaceBounds);

                    if (rect.Width != 0 && rect.Height != 0)
                    {
                        for (int y = rect.Top; y < rect.Bottom; ++y)
                        {
                            ppvBuffers[scanIndex] = surface.GetPointAddressUnchecked(rect.Left, y);
                            lengths[scanIndex]    = (uint)(rect.Width * ColorBgra.SizeOf);
                            ++scanIndex;
                        }
                    }
                }
            }

            if (trueForSave)
            {
                FileSystem.WriteToStreamingFileGather(fileHandle, ppvBuffers, lengths);
            }
            else
            {
                FileSystem.ReadFromStreamScatter(fileHandle, ppvBuffers, lengths);
            }
        }
        private static unsafe void LoadOrSaveSurfaceRegion(FileStream fileHandle, Surface surface, PdnRegion region, bool trueForSave)
        {
            Rectangle[] scans = region.GetRegionScansReadOnlyInt();
            Rectangle regionBounds = region.GetBoundsInt();
            Rectangle surfaceBounds = surface.Bounds;
            int scanCount = 0;

            void*[] ppvBuffers;
            uint[] lengths;

            regionBounds.Intersect(surfaceBounds);
            long length = (long)regionBounds.Width * (long)regionBounds.Height * (long)ColorBgra.SizeOf;

            if (scans.Length == 1 &&
                length <= uint.MaxValue &&
                surface.IsContiguousMemoryRegion(regionBounds))
            {
                ppvBuffers = new void*[1];
                lengths = new uint[1];

                ppvBuffers[0] = surface.GetPointAddressUnchecked(regionBounds.Location);
                lengths[0] = (uint)length;
            }
            else
            {
                for (int i = 0; i < scans.Length; ++i)
                {
                    Rectangle rect = scans[i];
                    rect.Intersect(surfaceBounds);

                    if (rect.Width != 0 && rect.Height != 0)
                    {
                        scanCount += rect.Height;
                    }
                }

                int scanIndex = 0;
                ppvBuffers = new void*[scanCount];
                lengths = new uint[scanCount];

                for (int i = 0; i < scans.Length; ++i)
                {
                    Rectangle rect = scans[i];
                    rect.Intersect(surfaceBounds);

                    if (rect.Width != 0 && rect.Height != 0)
                    {
                        for (int y = rect.Top; y < rect.Bottom; ++y)
                        {
                            ppvBuffers[scanIndex] = surface.GetPointAddressUnchecked(rect.Left, y);
                            lengths[scanIndex] = (uint)(rect.Width * ColorBgra.SizeOf);
                            ++scanIndex;
                        }
                    }
                }
            }

            if (trueForSave)
            {
                FileSystem.WriteToStreamingFileGather(fileHandle, ppvBuffers, lengths);
            }
            else
            {
                FileSystem.ReadFromStreamScatter(fileHandle, ppvBuffers, lengths);
            }
        }
示例#10
0
        public unsafe static void FillStencilFromPoint(Surface surface, IBitVector2D stencil, Point start,
                                                       int tolerance, out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection)
        {
            ColorBgra cmp    = surface[start];
            int       top    = int.MaxValue;
            int       bottom = int.MinValue;
            int       left   = int.MaxValue;
            int       right  = int.MinValue;

            Rectangle[] scans;

            stencil.Clear(false);

            if (limitToSelection)
            {
                using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height)))
                {
                    excluded.Xor(limitRegion);
                    scans = excluded.GetRegionScansReadOnlyInt();
                }
            }
            else
            {
                scans = new Rectangle[0];
            }

            foreach (Rectangle rect in scans)
            {
                stencil.Set(rect, true);
            }

            Queue <Point> queue = new Queue <Point>(16);

            queue.Enqueue(start);

            while (queue.Count > 0)
            {
                Point pt = queue.Dequeue();

                ColorBgra *rowPtr     = surface.GetRowAddressUnchecked(pt.Y);
                int        localLeft  = pt.X - 1;
                int        localRight = pt.X;

                while (localLeft >= 0 &&
                       !stencil.GetUnchecked(localLeft, pt.Y) &&
                       CheckColor(cmp, rowPtr[localLeft], tolerance))
                {
                    stencil.SetUnchecked(localLeft, pt.Y, true);
                    --localLeft;
                }

                while (localRight < surface.Width &&
                       !stencil.GetUnchecked(localRight, pt.Y) &&
                       CheckColor(cmp, rowPtr[localRight], tolerance))
                {
                    stencil.SetUnchecked(localRight, pt.Y, true);
                    ++localRight;
                }

                ++localLeft;
                --localRight;

                if (pt.Y > 0)
                {
                    int        sleft    = localLeft;
                    int        sright   = localLeft;
                    ColorBgra *rowPtrUp = surface.GetRowAddressUnchecked(pt.Y - 1);

                    for (int sx = localLeft; sx <= localRight; ++sx)
                    {
                        if (!stencil.GetUnchecked(sx, pt.Y - 1) &&
                            CheckColor(cmp, rowPtrUp[sx], tolerance))
                        {
                            ++sright;
                        }
                        else
                        {
                            if (sright - sleft > 0)
                            {
                                queue.Enqueue(new Point(sleft, pt.Y - 1));
                            }

                            ++sright;
                            sleft = sright;
                        }
                    }

                    if (sright - sleft > 0)
                    {
                        queue.Enqueue(new Point(sleft, pt.Y - 1));
                    }
                }

                if (pt.Y < surface.Height - 1)
                {
                    int        sleft      = localLeft;
                    int        sright     = localLeft;
                    ColorBgra *rowPtrDown = surface.GetRowAddressUnchecked(pt.Y + 1);

                    for (int sx = localLeft; sx <= localRight; ++sx)
                    {
                        if (!stencil.GetUnchecked(sx, pt.Y + 1) &&
                            CheckColor(cmp, rowPtrDown[sx], tolerance))
                        {
                            ++sright;
                        }
                        else
                        {
                            if (sright - sleft > 0)
                            {
                                queue.Enqueue(new Point(sleft, pt.Y + 1));
                            }

                            ++sright;
                            sleft = sright;
                        }
                    }

                    if (sright - sleft > 0)
                    {
                        queue.Enqueue(new Point(sleft, pt.Y + 1));
                    }
                }

                if (localLeft < left)
                {
                    left = localLeft;
                }

                if (localRight > right)
                {
                    right = localRight;
                }

                if (pt.Y < top)
                {
                    top = pt.Y;
                }

                if (pt.Y > bottom)
                {
                    bottom = pt.Y;
                }
            }

            foreach (Rectangle rect in scans)
            {
                stencil.Set(rect, false);
            }

            boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1);
        }
示例#11
0
        public static unsafe void FillStencilFromPoint(Surface surface, IBitVector2D stencil, Point start, 
            int tolerance, out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection)
        {
            ColorBgra cmp = surface[start];
            int top = int.MaxValue;
            int bottom = int.MinValue;
            int left = int.MaxValue;
            int right = int.MinValue;
            Rectangle[] scans;

            stencil.Clear(false);

            if (limitToSelection)
            {
                using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height)))
                {
                    excluded.Xor(limitRegion);
                    scans = excluded.GetRegionScansReadOnlyInt();
                }
            }
            else
            {
                scans = new Rectangle[0];
            }

            foreach (Rectangle rect in scans)
            {
                stencil.Set(rect, true);
            }

            Queue<Point> queue = new Queue<Point>(16);
            queue.Enqueue(start);

            while (queue.Count > 0)
            {
                Point pt = queue.Dequeue();

                ColorBgra* rowPtr = surface.GetRowAddressUnchecked(pt.Y);
                int localLeft = pt.X - 1;
                int localRight = pt.X;

                while (localLeft >= 0 &&
                       !stencil.GetUnchecked(localLeft, pt.Y) &&
                       CheckColor(cmp, rowPtr[localLeft], tolerance))
                {
                    stencil.SetUnchecked(localLeft, pt.Y, true);
                    --localLeft;
                }

                while (localRight < surface.Width &&
                       !stencil.GetUnchecked(localRight, pt.Y) &&
                       CheckColor(cmp, rowPtr[localRight], tolerance))
                {
                    stencil.SetUnchecked(localRight, pt.Y, true);
                    ++localRight;
                }

                ++localLeft;
                --localRight;

                if (pt.Y > 0)
                {
                    int sleft = localLeft;
                    int sright = localLeft;
                    ColorBgra* rowPtrUp = surface.GetRowAddressUnchecked(pt.Y - 1);

                    for (int sx = localLeft; sx <= localRight; ++sx)
                    {
                        if (!stencil.GetUnchecked(sx, pt.Y - 1) &&
                            CheckColor(cmp, rowPtrUp[sx], tolerance))
                        {
                            ++sright;
                        }
                        else
                        {
                            if (sright - sleft > 0)
                            {
                                queue.Enqueue(new Point(sleft, pt.Y - 1));
                            }

                            ++sright;
                            sleft = sright;
                        }
                    }

                    if (sright - sleft > 0)
                    {
                        queue.Enqueue(new Point(sleft, pt.Y - 1));
                    }
                }

                if (pt.Y < surface.Height - 1)
                {
                    int sleft = localLeft;
                    int sright = localLeft;
                    ColorBgra* rowPtrDown = surface.GetRowAddressUnchecked(pt.Y + 1);

                    for (int sx = localLeft; sx <= localRight; ++sx)
                    {
                        if (!stencil.GetUnchecked(sx, pt.Y + 1) &&
                            CheckColor(cmp, rowPtrDown[sx], tolerance))
                        {
                            ++sright;
                        }
                        else
                        {
                            if (sright - sleft > 0)
                            {
                                queue.Enqueue(new Point(sleft, pt.Y + 1));
                            }

                            ++sright;
                            sleft = sright;
                        }
                    }

                    if (sright - sleft > 0)
                    {
                        queue.Enqueue(new Point(sleft, pt.Y + 1));
                    }
                }

                if (localLeft < left)
                {
                    left = localLeft;
                }

                if (localRight > right)
                {
                    right = localRight;
                }

                if (pt.Y < top)
                {
                    top = pt.Y;
                }

                if (pt.Y > bottom)
                {
                    bottom = pt.Y;
                }
            }

            foreach (Rectangle rect in scans)
            {
                stencil.Set(rect, false);
            }

            boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1);
        }
        private Rectangle[][] SliceUpRegion(PdnRegion region, int sliceCount, Rectangle layerBounds)
        {
            Rectangle[][] slices = new Rectangle[sliceCount][];
            Rectangle[] regionRects = region.GetRegionScansReadOnlyInt();
            Scanline[] regionScans = Utility.GetRegionScans(regionRects);

            for (int i = 0; i < sliceCount; ++i)
            {
                int beginScan = (regionScans.Length * i) / sliceCount;
                int endScan = Math.Min(regionScans.Length, (regionScans.Length * (i + 1)) / sliceCount);

                // Try to arrange it such that the maximum size of the first region
                // is 1-pixel tall
                if (i == 0)
                {
                    endScan = Math.Min(endScan, beginScan + 1);
                }
                else if (i == 1)
                {
                    beginScan = Math.Min(beginScan, 1);
                }

                Rectangle[] newRects = Utility.ScanlinesToRectangles(regionScans, beginScan, endScan - beginScan);

                for (int j = 0; j < newRects.Length; ++j)
                {
                    newRects[j].Intersect(layerBounds);
                }

                slices[i] = newRects;
            }

            return slices;
        }
示例#13
0
        private void RenderGradient(Surface surface, PdnRegion clipRegion, CompositingMode compositingMode,
            PointF startPointF, ColorBgra startColor, PointF endPointF, ColorBgra endColor)
        {
            GradientRenderer gr = AppEnvironment.GradientInfo.CreateGradientRenderer();

            gr.StartColor = startColor;
            gr.EndColor = endColor;
            gr.StartPoint = startPointF;
            gr.EndPoint = endPointF;
            gr.AlphaBlending = (compositingMode == CompositingMode.SourceOver);
            gr.BeforeRender();

            Rectangle[] oldRois = clipRegion.GetRegionScansReadOnlyInt();
            Rectangle[] newRois;

            if (oldRois.Length == 1)
            {
                newRois = new Rectangle[Processor.LogicalCpuCount];
                Utility.SplitRectangle(oldRois[0], newRois);
            }
            else
            {
                newRois = oldRois;
            }

            RenderContext rc = new RenderContext();
            rc.surface = surface;
            rc.rois = newRois;
            rc.renderer = gr;

            WaitCallback wc = new WaitCallback(rc.Render);

            for (int i = 0; i < Processor.LogicalCpuCount; ++i)
            {
                if (i == Processor.LogicalCpuCount - 1)
                {
                    wc(BoxedConstants.GetInt32(i));
                }
                else
                {
                    PaintDotNet.Threading.ThreadPool.Global.QueueUserWorkItem(wc, BoxedConstants.GetInt32(i));
                }
            }

            PaintDotNet.Threading.ThreadPool.Global.Drain();
        }
示例#14
0
 public void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, PdnRegion roi)
 {
     Rectangle[] scans = roi.GetRegionScansReadOnlyInt();
     Render(parameters, dstArgs, srcArgs, scans, 0, scans.Length);
 }
示例#15
0
        public unsafe static void FillStencilByColor(Surface surface, IBitVector2D stencil, ColorBgra cmp, int tolerance,
                                                     out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection)
        {
            int top    = int.MaxValue;
            int bottom = int.MinValue;
            int left   = int.MaxValue;
            int right  = int.MinValue;

            Rectangle[] scans;

            stencil.Clear(false);

            if (limitToSelection)
            {
                using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height)))
                {
                    excluded.Xor(limitRegion);
                    scans = excluded.GetRegionScansReadOnlyInt();
                }
            }
            else
            {
                scans = new Rectangle[0];
            }

            foreach (Rectangle rect in scans)
            {
                stencil.Set(rect, true);
            }

            for (int y = 0; y < surface.Height; ++y)
            {
                bool       foundPixelInRow = false;
                ColorBgra *ptr             = surface.GetRowAddressUnchecked(y);

                for (int x = 0; x < surface.Width; ++x)
                {
                    if (CheckColor(cmp, *ptr, tolerance))
                    {
                        stencil.SetUnchecked(x, y, true);

                        if (x < left)
                        {
                            left = x;
                        }

                        if (x > right)
                        {
                            right = x;
                        }

                        foundPixelInRow = true;
                    }

                    ++ptr;
                }

                if (foundPixelInRow)
                {
                    if (y < top)
                    {
                        top = y;
                    }

                    if (y >= bottom)
                    {
                        bottom = y;
                    }
                }
            }

            foreach (Rectangle rect in scans)
            {
                stencil.Set(rect, false);
            }

            boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1);
        }
示例#16
0
        public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace)
        {
            if (historyWorkspace.Selection.IsEmpty)
            {
                return(null);
            }
            else
            {
                PdnRegion selectionRegion = historyWorkspace.Selection.CreateRegion();

                if (selectionRegion.GetArea() == 0)
                {
                    selectionRegion.Dispose();
                    return(null);
                }

                SelectionHistoryMemento       sha  = new SelectionHistoryMemento(StaticName, null, historyWorkspace);
                ReplaceDocumentHistoryMemento rdha = new ReplaceDocumentHistoryMemento(StaticName, null, historyWorkspace);
                Rectangle   boundingBox;
                Rectangle[] inverseRegionRects = null;

                boundingBox = Utility.GetRegionBounds(selectionRegion);

                using (PdnRegion inverseRegion = new PdnRegion(boundingBox))
                {
                    inverseRegion.Exclude(selectionRegion);

                    inverseRegionRects = Utility.TranslateRectangles(
                        inverseRegion.GetRegionScansReadOnlyInt(),
                        -boundingBox.X,
                        -boundingBox.Y);
                }

                selectionRegion.Dispose();
                selectionRegion = null;

                Document oldDocument = historyWorkspace.Document; // TODO: serialize this to disk so we don't *have* to store the full thing
                Document newDocument = new Document(boundingBox.Width, boundingBox.Height);

                // copy the document's meta data over
                newDocument.ReplaceMetaDataFrom(oldDocument);

                foreach (Layer layer in oldDocument.Layers)
                {
                    if (layer is BitmapLayer)
                    {
                        BitmapLayer oldLayer       = (BitmapLayer)layer;
                        Surface     croppedSurface = oldLayer.Surface.CreateWindow(boundingBox);
                        BitmapLayer newLayer       = new BitmapLayer(croppedSurface);

                        ColorBgra clearWhite = ColorBgra.White.NewAlpha(0);

                        foreach (Rectangle rect in inverseRegionRects)
                        {
                            newLayer.Surface.Clear(rect, clearWhite);
                        }

                        newLayer.LoadProperties(oldLayer.SaveProperties());
                        newDocument.Layers.Add(newLayer);
                    }
                    else
                    {
                        throw new InvalidOperationException("Crop does not support Layers that are not BitmapLayers");
                    }
                }

                CompoundHistoryMemento cha = new CompoundHistoryMemento(
                    StaticName,
                    PdnResources.GetImageResource("Icons.MenuImageCropIcon.png"),
                    new HistoryMemento[] { sha, rdha });

                EnterCriticalRegion();
                historyWorkspace.Document = newDocument;

                return(cha);
            }
        }
示例#17
0
 public void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, PdnRegion roi)
 {
     Rectangle[] scans = roi.GetRegionScansReadOnlyInt();
     Render(parameters, dstArgs, srcArgs, scans, 0, scans.Length);
 }
示例#18
0
        public static unsafe void FillStencilByColor(Surface surface, IBitVector2D stencil, ColorBgra cmp, int tolerance, 
            out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection)
        {
            int top = int.MaxValue;
            int bottom = int.MinValue;
            int left = int.MaxValue;
            int right = int.MinValue;
            Rectangle[] scans;

            stencil.Clear(false);

            if (limitToSelection)
            {
                using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height)))
                {
                    excluded.Xor(limitRegion);
                    scans = excluded.GetRegionScansReadOnlyInt();
                }
            }
            else
            {
                scans = new Rectangle[0];
            }

            foreach (Rectangle rect in scans)
            {
                stencil.Set(rect, true);
            }

            for (int y = 0; y < surface.Height; ++y)
            {
                bool foundPixelInRow = false;
                ColorBgra *ptr = surface.GetRowAddressUnchecked(y);

                for (int x = 0; x < surface.Width; ++x)
                {
                    if (CheckColor(cmp, *ptr, tolerance))
                    {
                        stencil.SetUnchecked(x, y, true);

                        if (x < left)
                        {
                            left = x;
                        }

                        if (x > right)
                        {
                            right = x;
                        }

                        foundPixelInRow = true;
                    }

                    ++ptr;
                }

                if (foundPixelInRow)
                {
                    if (y < top)
                    {
                        top = y;
                    }

                    if (y >= bottom)
                    {
                        bottom = y;
                    }
                }
            }

            foreach (Rectangle rect in scans)
            {
                stencil.Set(rect, false);
            }

            boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1);
        }
示例#19
0
 /// <summary>
 /// This is a helper function. It allows you to render an effect "in place."
 /// That is, you don't need both a destination and a source Surface.
 /// </summary>
 public void RenderInPlace(RenderArgs srcAndDstArgs, PdnRegion roi)
 {
     using (Surface renderSurface = new Surface(srcAndDstArgs.Surface.Size))
     {
         using (RenderArgs renderArgs = new RenderArgs(renderSurface))
         {
             Rectangle[] scans = roi.GetRegionScansReadOnlyInt();
             Render(null, renderArgs, srcAndDstArgs, scans);
             srcAndDstArgs.Surface.CopySurface(renderSurface, roi);
         }
     }
 }