Example #1
0
        public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace)
        {
            GeometryList cachedClippingMask = historyWorkspace.Selection.GetCachedClippingMask();

            if (historyWorkspace.Selection.IsEmpty || (cachedClippingMask.Bounds.Area < 1.0))
            {
                return(null);
            }
            Document document = historyWorkspace.Document;
            List <HistoryMemento> mementos   = new List <HistoryMemento>(document.Layers.Count);
            RectInt32             b          = cachedClippingMask.Bounds.GetInt32Bound(1E-05);
            RectInt32             sourceRect = RectInt32.Intersect(document.Bounds(), b);
            Document document2 = new Document(sourceRect.Width, sourceRect.Height);

            document2.ReplaceMetadataFrom(document);
            RectInt32 rect = new RectInt32(0, 0, sourceRect.Width, sourceRect.Height);
            IRenderer <ColorAlpha8> cachedClippingMaskRenderer = historyWorkspace.Selection.GetCachedClippingMaskRenderer(historyWorkspace.ToolSettings.Selection.RenderingQuality.Value);
            IRenderer <ColorAlpha8> newClipMaskRenderer        = new ClippedRenderer <ColorAlpha8>(cachedClippingMaskRenderer, sourceRect);
            SelectionHistoryMemento item = new SelectionHistoryMemento(null, null, historyWorkspace);

            mementos.Add(item);
            base.EnterCriticalRegion();
            int count = document.Layers.Count;

            while (document.Layers.Count > 0)
            {
                BitmapLayer layer          = (BitmapLayer)document.Layers[0];
                Surface     croppedSurface = layer.Surface.CreateWindow(sourceRect);
                BitmapLayer newLayer       = RetryManager.RunMemorySensitiveOperation <BitmapLayer>(() => new BitmapLayer(croppedSurface));
                newLayer.LoadProperties(layer.SaveProperties());
                HistoryMemento deleteLayerMemento = new DeleteLayerFunction(0).Execute(historyWorkspace);
                mementos.Add(deleteLayerMemento);
                Task task = Task.Factory.StartNew(delegate {
                    deleteLayerMemento.Flush();
                }, TaskCreationOptions.LongRunning);
                Parallel.ForEach <RectInt32>(rect.GetTiles(TilingStrategy.Tiles, 7), delegate(RectInt32 newTileRect) {
                    ISurface <ColorBgra> surface = newLayer.Surface.CreateWindow(newTileRect);
                    IRenderer <ColorAlpha8> mask = new ClippedRenderer <ColorAlpha8>(newClipMaskRenderer, newTileRect);
                    surface.MultiplyAlphaChannel(mask);
                });
                document2.Layers.Add(newLayer);
                task.Wait();
                if (document2.Layers.Count > count)
                {
                    ExceptionUtil.ThrowInternalErrorException("newDocument.Layers.Count > oldLayerCount");
                }
            }
            ReplaceDocumentHistoryMemento memento2 = new ReplaceDocumentHistoryMemento(null, null, historyWorkspace);

            mementos.Add(memento2);
            historyWorkspace.Document = document2;
            return(HistoryMemento.Combine(HistoryMementoName, HistoryMementoImage, mementos));
        }
        private BitmapLayer RotateLayer(BitmapLayer layer, RotateType rotationType, int width, int height, double startProgress, double endProgress)
        {
            Surface surface = new Surface(width, height);

            if (rotationType == RotateType.Clockwise180 ||
                rotationType == RotateType.CounterClockwise180)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        surface[x, y] = layer.Surface[width - x - 1, height - y - 1];
                    }

                    OnProgress(((double)y / (double)height) * (endProgress - startProgress) + startProgress);
                }
            }
            else if (rotationType == RotateType.Clockwise270 ||
                     rotationType == RotateType.CounterClockwise90)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        surface[x, y] = layer.Surface[height - y - 1, x];
                    }

                    OnProgress(((double)y / (double)height) * (endProgress - startProgress) + startProgress);
                }
            }
            else if (rotationType == RotateType.Clockwise90 ||
                     rotationType == RotateType.CounterClockwise270)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        surface[x, y] = layer.Surface[y, width - 1 - x];
                    }

                    OnProgress(((double)y / (double)height) * (endProgress - startProgress) + startProgress);
                }
            }

            BitmapLayer returnMe = new BitmapLayer(surface, true);

            returnMe.LoadProperties(layer.SaveProperties());
            return(returnMe);
        }
Example #3
0
        private BitmapLayer RotateLayer(BitmapLayer layer, RotateType rotationType, int width, int height)
        {
            Surface surface = RetryManager.RunMemorySensitiveOperation <Surface>(() => new Surface(width, height));

            if (rotationType == RotateType.Rotate180)
            {
                Parallel.For(0, height, delegate(int y) {
                    for (int j = 0; j < width; j++)
                    {
                        surface[j, y] = layer.Surface[(width - j) - 1, (height - y) - 1];
                    }
                });
            }
            else if (rotationType == RotateType.CounterClockwise90)
            {
                Parallel.For(0, height, delegate(int y) {
                    for (int k = 0; k < width; k++)
                    {
                        surface[k, y] = layer.Surface[(height - y) - 1, k];
                    }
                });
            }
            else if (rotationType == RotateType.Clockwise90)
            {
                Parallel.For(0, height, delegate(int y) {
                    for (int m = 0; m < width; m++)
                    {
                        surface[m, y] = layer.Surface[y, (width - 1) - m];
                    }
                });
            }
            BitmapLayer layer2 = new BitmapLayer(surface, true);

            layer2.LoadProperties(layer.SaveProperties());
            return(layer2);
        }
Example #4
0
        public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace)
        {
            GeometryList cachedClippingMask = historyWorkspace.Selection.GetCachedClippingMask();

            if (historyWorkspace.Selection.IsEmpty || (cachedClippingMask.Bounds.Area < 1.0))
            {
                return(null);
            }
            Document  oldDocument   = historyWorkspace.Document;
            RectInt32 b             = cachedClippingMask.Bounds.GetInt32Bound(1E-05);
            RectInt32 oldClipBounds = RectInt32.Intersect(oldDocument.Bounds(), b);
            Document  document      = new Document(oldClipBounds.Width, oldClipBounds.Height);

            document.ReplaceMetadataFrom(oldDocument);
            RectInt32 newClipBounds = new RectInt32(0, 0, oldClipBounds.Width, oldClipBounds.Height);
            SelectionRenderingQuality                   quality = historyWorkspace.ToolSettings.Selection.RenderingQuality.Value;
            Result <IRenderer <ColorAlpha8> >           oldClipMaskRendererLazy = historyWorkspace.Selection.GetCachedLazyClippingMaskRenderer(quality);
            LazyResult <ClippedRenderer <ColorAlpha8> > newClipMaskRendererLazy = LazyResult.New <ClippedRenderer <ColorAlpha8> >(() => new ClippedRenderer <ColorAlpha8>(oldClipMaskRendererLazy.Value, oldClipBounds), LazyThreadSafetyMode.ExecutionAndPublication, new VistaCriticalSection(0));
            SelectionData selectionData = historyWorkspace.Selection.Save();

            System.Threading.Tasks.Task <SelectionHistoryMemento>       task  = System.Threading.Tasks.Task.Factory.StartNew <SelectionHistoryMemento>(() => new SelectionHistoryMemento(null, null, historyWorkspace, selectionData));
            System.Threading.Tasks.Task <ReplaceDocumentHistoryMemento> task2 = System.Threading.Tasks.Task.Factory.StartNew <ReplaceDocumentHistoryMemento>(() => new ReplaceDocumentHistoryMemento(null, null, historyWorkspace, oldDocument), TaskCreationOptions.LongRunning);
            int count = oldDocument.Layers.Count;

            System.Threading.Tasks.Task <BitmapLayer>[] items = new System.Threading.Tasks.Task <BitmapLayer> [count];
            for (int i = 0; i < count; i++)
            {
                int iP = i;
                items[iP] = System.Threading.Tasks.Task.Factory.StartNew <BitmapLayer>(delegate {
                    if (iP == 0)
                    {
                        newClipMaskRendererLazy.EnsureEvaluated();
                    }
                    BitmapLayer layer      = (BitmapLayer)oldDocument.Layers[iP];
                    Surface croppedSurface = layer.Surface.CreateWindow(oldClipBounds);
                    BitmapLayer newLayer   = RetryManager.RunMemorySensitiveOperation <BitmapLayer>(() => new BitmapLayer(croppedSurface));
                    newLayer.LoadProperties(layer.SaveProperties());
                    Parallel.ForEach <RectInt32>(newClipBounds.GetTiles(TilingStrategy.Tiles, 7), delegate(RectInt32 newTileRect) {
                        ISurface <ColorBgra> surface = newLayer.Surface.CreateWindow(newTileRect);
                        IRenderer <ColorAlpha8> mask = new ClippedRenderer <ColorAlpha8>(newClipMaskRendererLazy.Value, newTileRect);
                        surface.MultiplyAlphaChannel(mask);
                    });
                    return(newLayer);
                });
            }
            List <TupleStruct <System.Threading.Tasks.Task, double> > collection = new List <TupleStruct <System.Threading.Tasks.Task, double> >();

            collection.AddTuple <System.Threading.Tasks.Task, double>(task, 0.1);
            collection.AddTuple <System.Threading.Tasks.Task, double>(task2, 1.0);
            for (int j = 0; j < items.Length; j++)
            {
                collection.AddTuple <System.Threading.Tasks.Task, double>(items[j], 0.1);
            }
            PaintDotNet.Threading.Tasks.Task <Unit> task3 = historyWorkspace.TaskManager.CreateFrameworkTasksWrapper(collection);
            historyWorkspace.WaitWithProgress(task3, HistoryMementoImage, HistoryMementoName, PdnResources.GetString("Effects.ApplyingDialog.Description"));
            document.Layers.AddRange <Layer>(items.Select <System.Threading.Tasks.Task <BitmapLayer>, BitmapLayer>(t => t.Result));
            SelectionHistoryMemento       result   = task.Result;
            ReplaceDocumentHistoryMemento memento2 = task2.Result;

            base.EnterCriticalRegion();
            historyWorkspace.Document = document;
            HistoryMemento[] mementos = new HistoryMemento[] { result, memento2 };
            return(HistoryMemento.Combine(HistoryMementoName, HistoryMementoImage, mementos));
        }
        private BitmapLayer RotateLayer(BitmapLayer layer, RotateType rotationType, int width, int height, double startProgress, double endProgress)
        {
            Surface surface = new Surface(width, height);

            if (rotationType == RotateType.Clockwise180 ||
                rotationType == RotateType.CounterClockwise180)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        surface[x, y] = layer.Surface[width - x - 1, height - y - 1];
                    }

                    OnProgress(((double)y / (double)height) * (endProgress - startProgress) + startProgress);
                }
            }
            else if (rotationType == RotateType.Clockwise270 ||
                     rotationType == RotateType.CounterClockwise90)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        surface[x, y] = layer.Surface[height - y - 1, x];
                    }

                    OnProgress(((double)y / (double)height) * (endProgress - startProgress) + startProgress);
                }
            }
            else if (rotationType == RotateType.Clockwise90 ||
                     rotationType == RotateType.CounterClockwise270)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        surface[x, y] = layer.Surface[y, width - 1 - x];
                    }

                    OnProgress(((double)y / (double)height) * (endProgress - startProgress) + startProgress);
                }
            }

            BitmapLayer returnMe = new BitmapLayer(surface, true);
            returnMe.LoadProperties(layer.SaveProperties());
            return returnMe;
        }
        public static BitmapLayer ResizeLayer(BitmapLayer layer, Size newSize, AnchorEdge anchor, ColorBgra background)
        {
            BitmapLayer newLayer = new BitmapLayer(newSize.Width, newSize.Height);

            // Background
            new UnaryPixelOps.Constant(background).Apply(newLayer.Surface, newLayer.Surface.Bounds);

            // non-background = clear the alpha channel (see-through)
            if (!layer.IsBackground)
            {
                new UnaryPixelOps.SetAlphaChannel(0).Apply(newLayer.Surface, newLayer.Surface.Bounds);
            }

            int topY = 0;
            int leftX = 0;
            int rightX = newSize.Width - layer.Width;
            int bottomY = newSize.Height - layer.Height;
            int middleX = (newSize.Width - layer.Width) / 2;
            int middleY = (newSize.Height - layer.Height) / 2;

            int x = 0;
            int y = 0;

            #region choose x,y from AnchorEdge
            switch (anchor)
            {
                case AnchorEdge.TopLeft:
                    x = leftX;
                    y = topY;
                    break;

                case AnchorEdge.Top:
                    x = middleX;
                    y = topY;
                    break;

                case AnchorEdge.TopRight:
                    x = rightX;
                    y = topY;
                    break;

                case AnchorEdge.Left:
                    x = leftX;
                    y = middleY;
                    break;

                case AnchorEdge.Middle:
                    x = middleX;
                    y = middleY;
                    break;

                case AnchorEdge.Right:
                    x = rightX;
                    y = middleY;
                    break;

                case AnchorEdge.BottomLeft:
                    x = leftX;
                    y = bottomY;
                    break;

                case AnchorEdge.Bottom:
                    x = middleX;
                    y = bottomY;
                    break;

                case AnchorEdge.BottomRight:
                    x = rightX;
                    y = bottomY;
                    break;
            }
            #endregion

            newLayer.Surface.CopySurface(layer.Surface, new Point(x, y));
            newLayer.LoadProperties(layer.SaveProperties());
            return newLayer;
        }
Example #7
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);
            }
        }
        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;
            }
        }
Example #9
0
        public static BitmapLayer ResizeLayer(BitmapLayer layer, Size newSize, AnchorEdge anchor, ColorBgra background)
        {
            BitmapLayer layer2 = new BitmapLayer(newSize.Width, newSize.Height);

            new UnaryPixelOps.Constant(background).Apply(layer2.Surface, layer2.Surface.Bounds);
            if (!layer.IsBackground)
            {
                new UnaryPixelOps.SetAlphaChannel(0).Apply(layer2.Surface, layer2.Surface.Bounds);
            }
            int num  = 0;
            int num2 = 0;
            int num3 = newSize.Width - layer.Width;
            int num4 = newSize.Height - layer.Height;
            int num5 = (newSize.Width - layer.Width) / 2;
            int num6 = (newSize.Height - layer.Height) / 2;
            int x    = 0;
            int y    = 0;

            switch (anchor)
            {
            case AnchorEdge.TopLeft:
                x = num2;
                y = num;
                break;

            case AnchorEdge.Top:
                x = num5;
                y = num;
                break;

            case AnchorEdge.TopRight:
                x = num3;
                y = num;
                break;

            case AnchorEdge.Left:
                x = num2;
                y = num6;
                break;

            case AnchorEdge.Middle:
                x = num5;
                y = num6;
                break;

            case AnchorEdge.Right:
                x = num3;
                y = num6;
                break;

            case AnchorEdge.BottomLeft:
                x = num2;
                y = num4;
                break;

            case AnchorEdge.Bottom:
                x = num5;
                y = num4;
                break;

            case AnchorEdge.BottomRight:
                x = num3;
                y = num4;
                break;
            }
            layer2.Surface.CopySurface(layer.Surface, new Point(x, y));
            layer2.LoadProperties(layer.SaveProperties());
            return(layer2);
        }
Example #10
0
        public static BitmapLayer ResizeLayer(BitmapLayer layer, Size newSize, AnchorEdge anchor, ColorBgra background)
        {
            BitmapLayer newLayer = new BitmapLayer(newSize.Width, newSize.Height);

            // Background
            new UnaryPixelOps.Constant(background).Apply(newLayer.Surface, newLayer.Surface.Bounds);

            // non-background = clear the alpha channel (see-through)
            if (!layer.IsBackground)
            {
                new UnaryPixelOps.SetAlphaChannel(0).Apply(newLayer.Surface, newLayer.Surface.Bounds);
            }

            int topY    = 0;
            int leftX   = 0;
            int rightX  = newSize.Width - layer.Width;
            int bottomY = newSize.Height - layer.Height;
            int middleX = (newSize.Width - layer.Width) / 2;
            int middleY = (newSize.Height - layer.Height) / 2;

            int x = 0;
            int y = 0;

            #region choose x,y from AnchorEdge
            switch (anchor)
            {
            case AnchorEdge.TopLeft:
                x = leftX;
                y = topY;
                break;

            case AnchorEdge.Top:
                x = middleX;
                y = topY;
                break;

            case AnchorEdge.TopRight:
                x = rightX;
                y = topY;
                break;

            case AnchorEdge.Left:
                x = leftX;
                y = middleY;
                break;

            case AnchorEdge.Middle:
                x = middleX;
                y = middleY;
                break;

            case AnchorEdge.Right:
                x = rightX;
                y = middleY;
                break;

            case AnchorEdge.BottomLeft:
                x = leftX;
                y = bottomY;
                break;

            case AnchorEdge.Bottom:
                x = middleX;
                y = bottomY;
                break;

            case AnchorEdge.BottomRight:
                x = rightX;
                y = bottomY;
                break;
            }
            #endregion

            newLayer.Surface.CopySurface(layer.Surface, new Point(x, y));
            newLayer.LoadProperties(layer.SaveProperties());
            return(newLayer);
        }
Example #11
0
        private static BitmapLayer ResizeLayer(BitmapLayer layer, int width, int height, ResamplingAlgorithm algorithm,
            int tileCount, Procedure progressCallback, ref bool pleaseStopMonitor)
        {
            Surface surface = new Surface(width, height);
            surface.Clear(ColorBgra.FromBgra(255, 255, 255, 0));

            PaintDotNet.Threading.ThreadPool threadPool = new PaintDotNet.Threading.ThreadPool();
            int rectCount;

            if (tileCount == 0)
            {
                rectCount = Processor.LogicalCpuCount;
            }
            else
            {
                rectCount = tileCount;
            }

            Rectangle[] rects = new Rectangle[rectCount];
            Utility.SplitRectangle(surface.Bounds, rects);

            FitSurfaceContext fsc = new FitSurfaceContext(surface, layer.Surface, rects, algorithm);

            if (progressCallback != null)
            {
                fsc.RenderedRect += progressCallback;
            }

            WaitCallback callback = new WaitCallback(fsc.FitSurface);

            for (int i = 0; i < rects.Length; ++i)
            {
                if (pleaseStopMonitor)
                {
                    break;
                }
                else
                {
                    threadPool.QueueUserWorkItem(callback, BoxedConstants.GetInt32(i));
                }
            }

            threadPool.Drain();
            threadPool.DrainExceptions();

            if (pleaseStopMonitor)
            {
                surface.Dispose();
                surface = null;
            }

            BitmapLayer newLayer;

            if (surface == null)
            {
                newLayer = null;
            }
            else
            {
                newLayer = new BitmapLayer(surface, true);
                newLayer.LoadProperties(layer.SaveProperties());
            }

            if (progressCallback != null)
            {
                fsc.RenderedRect -= progressCallback;
            }

            return newLayer;
        }
Example #12
0
        private static BitmapLayer ResizeLayer(BitmapLayer layer, int width, int height, ResamplingAlgorithm algorithm,
                                               int tileCount, Procedure progressCallback, ref bool pleaseStopMonitor)
        {
            Surface surface = new Surface(width, height);

            surface.Clear(ColorBgra.FromBgra(255, 255, 255, 0));

            PaintDotNet.Threading.ThreadPool threadPool = new PaintDotNet.Threading.ThreadPool();
            int rectCount;

            if (tileCount == 0)
            {
                rectCount = Processor.LogicalCpuCount;
            }
            else
            {
                rectCount = tileCount;
            }

            Rectangle[] rects = new Rectangle[rectCount];
            Utility.SplitRectangle(surface.Bounds, rects);

            FitSurfaceContext fsc = new FitSurfaceContext(surface, layer.Surface, rects, algorithm);

            if (progressCallback != null)
            {
                fsc.RenderedRect += progressCallback;
            }

            WaitCallback callback = new WaitCallback(fsc.FitSurface);

            for (int i = 0; i < rects.Length; ++i)
            {
                if (pleaseStopMonitor)
                {
                    break;
                }
                else
                {
                    threadPool.QueueUserWorkItem(callback, BoxedConstants.GetInt32(i));
                }
            }

            threadPool.Drain();
            threadPool.DrainExceptions();

            if (pleaseStopMonitor)
            {
                surface.Dispose();
                surface = null;
            }

            BitmapLayer newLayer;

            if (surface == null)
            {
                newLayer = null;
            }
            else
            {
                newLayer = new BitmapLayer(surface, true);
                newLayer.LoadProperties(layer.SaveProperties());
            }

            if (progressCallback != null)
            {
                fsc.RenderedRect -= progressCallback;
            }

            return(newLayer);
        }