/// <summary> /// Constructs an outline of the given region with the given bounds /// and scaling factor. /// </summary> /// <param name="region"> /// The selection to approximate. /// </param> /// <param name="bounds"> /// The boundaries of the image. /// </param> /// <param name="scalingMultiplier"> /// The amount to scale the size of the outline by. /// </param> public static PdnRegion ConstructOutline( this PdnRegion region, RectangleF bounds, float scalingMultiplier) { GraphicsPath path = new GraphicsPath(); PdnRegion newRegion = region.Clone(); //The size to scale the region by. Matrix scalematrix = new Matrix( bounds, new PointF[] { new PointF(bounds.Left, bounds.Top), new PointF(bounds.Right * scalingMultiplier, bounds.Top), new PointF(bounds.Left, bounds.Bottom * scalingMultiplier) }); newRegion.Transform(scalematrix); //Makes the new region slightly larger by inflating rectangles. foreach (RectangleF rect in newRegion.GetRegionScans()) { path.AddRectangle(RectangleF.Inflate(rect, 1, 1)); } //Subtracts the old region, leaving an outline from the expansion. PdnRegion result = new PdnRegion(path); result.Exclude(newRegion); return(result); }
public static PdnRegion GetOutline(this PdnRegion region, RectangleF bounds, float scalefactor) { GraphicsPath path = new GraphicsPath(); PdnRegion region2 = region.Clone(); Matrix scalematrix = new Matrix( bounds, new PointF[] { new PointF(bounds.Left, bounds.Top), new PointF(bounds.Right * scalefactor, bounds.Top), new PointF(bounds.Left, bounds.Bottom * scalefactor) }); region2.Transform(scalematrix); foreach (RectangleF rect in region2.GetRegionScans()) { path.AddRectangle(RectangleF.Inflate(rect, 1, 1)); } PdnRegion retval = new PdnRegion(path); retval.Exclude(region2); return(retval); }
private void InvalidateSelection() { if (selection != null) { unSelection = new PdnRegion(new Rectangle(0, 0, surface.Width, surface.Height)); unSelection.Exclude(selection); selectionOutline = selection.GetOutline(surface.Bounds, scale); } canvas.Invalidate(); }
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); } }
static void Main(string[] args) { for (int i = 0; i < args.Length; i++) { switch (args[i]) { case "/proc": if (i + 1 == args.Length) { Console.WriteLine("Use /proc <N> to specify number of processors"); return; } int numProcs; if (Int32.TryParse(args[i + 1], out numProcs)) { // only increment i if successful b/c we're going to continue the run // with the default # of processors and don't want to automatically // eat the next parameter. ++i; Processor.LogicalCpuCount = numProcs; } else { Console.WriteLine("You must specify a integer for /proc <N>, continuing with default"); } break; case "/image": if (i + 1 == args.Length) { Console.WriteLine("Use /image <filename> to specify a file to perform benchmark with"); return; } ++i; benchmarkImageName = args[i]; if (!System.IO.File.Exists(benchmarkImageName)) { Console.WriteLine("Specified image doesn't exist"); return; } break; case "/tsv": useTsvOutput = true; break; case "/?": PrintHelp(); return; default: break; } } //Processor.LogicalCpuCount = 1; Console.WriteLine("PdnBench v" + PdnInfo.GetVersion()); Console.WriteLine("Running in " + (8 * Marshal.SizeOf(typeof(IntPtr))) + "-bit mode on " + Processor.NativeArchitecture.ToString().ToLower() + " OS"); Console.WriteLine("Processor: " + Processor.LogicalCpuCount + "x " + Processor.CpuName); Console.WriteLine("Memory: " + ((Memory.TotalPhysicalBytes / 1024) / 1024) + " MB"); Console.WriteLine(); Console.WriteLine("Using " + Processor.LogicalCpuCount + " threads."); ArrayList benchmarks = new ArrayList(); Document document; Console.Write("Loading image ... "); Stream imageStream = null; try { imageStream = (defaultImageName == benchmarkImageName) ? Assembly.GetExecutingAssembly().GetManifestResourceStream(benchmarkImageName) : new FileStream(benchmarkImageName, FileMode.Open); JpegFileType jft = new JpegFileType(); document = jft.Load(imageStream); } finally { if (imageStream != null) { imageStream.Dispose(); } } Console.WriteLine("(" + document.Width + " x " + document.Height + ") done"); Surface surface = ((BitmapLayer)document.Layers[0]).Surface; #if EFFECTS for (double i = 0; i < (2 * Math.PI); i += 70.0 * ((2 * Math.PI) / 360.0)) { benchmarks.Add( new EffectBenchmark("Rotate/Zoom at " + ((i * 180.0) / Math.PI).ToString("F2") + " degrees", 3, new PaintDotNet.Effects.RotateZoomEffect(), new PaintDotNet.Effects.RotateZoomEffectConfigToken( true, (float)(Math.PI * 0.3f), (float)((Math.PI * -0.4) + i), 50, 0.5f, new PointF(-0.2f, 0.3f), false, true), surface)); } for (int i = 1; i <= 4; i += 3) { for (int j = 10; j < 100; j += 75) { benchmarks.Add( new EffectBenchmark( "Oil Painting, brush size = " + i + ", coarseness = " + j, 1, new OilPaintingEffect(), new TwoAmountsConfigToken(i, j), surface)); } } for (int i = 2; i <= 50; i += i) { benchmarks.Add( new EffectBenchmark( "Blur with radius of " + i, 1, new BlurEffect(), new AmountEffectConfigToken(i), surface)); } for (int i = 1; i <= 4; i += 3) { benchmarks.Add( new EffectBenchmark( "Sharpen with value of " + i, 1, new SharpenEffect(), new AmountEffectConfigToken(i), surface)); } benchmarks.Add( new EffectBenchmark( "Auto-Levels", 50, new AutoLevelEffect(), null, surface)); for (int i = 81; i >= 5; i /= 3) { benchmarks.Add( new EffectBenchmark( "Clouds, roughness = " + i, 2, new CloudsEffect(), new CloudsEffectConfigToken(50, i, 12345, new UserBlendOps.NormalBlendOp()), surface)); } for (int i = 4; i <= 64; i *= 4) { benchmarks.Add( new EffectBenchmark( "Median, radius " + i, 1, new MedianEffect(), new TwoAmountsConfigToken(/*radius*/ i, /*roughness*/ 50), surface)); } for (int i = 4; i <= 64; i *= 4) { benchmarks.Add( new EffectBenchmark( "Unfocus, radius " + i, 1, new UnfocusEffect(), new AmountEffectConfigToken(i), surface)); } benchmarks.Add( new EffectBenchmark( "Motion Blur, Horizontal", 1, new MotionBlurEffect(), new MotionBlurEffectConfigToken(0, 100, true), surface)); benchmarks.Add( new EffectBenchmark( "Motion Blur, Vertical", 1, new MotionBlurEffect(), new MotionBlurEffectConfigToken(90, 100, true), surface)); #endif Surface dst = new Surface(surface.Width * 4, surface.Height * 4); #if RESIZE // Resize benchmarks for (int i = 1; i < 8; i += 2) { int newWidth = i * (dst.Width / 8); int newHeight = i * (dst.Height / 8); Surface dstWindow = dst.CreateWindow(new Rectangle(0, 0, newWidth, newHeight)); benchmarks.Add(new ResizeBenchmark("Resize from " + surface.Width + "x" + surface.Height + " to " + newWidth + "x" + newHeight, surface, dstWindow)); benchmarks.Add(new ResizeBenchmark("Resize from " + newWidth + "x" + newHeight + " to " + surface.Width + "x" + surface.Height, dstWindow, surface)); } #endif #if GRADIENT // Gradient benchmarks benchmarks.Add(new GradientBenchmark( "Linear reflected gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.LinearReflected(false, new UserBlendOps.NormalBlendOp()), 2)); benchmarks.Add(new GradientBenchmark( "Conical gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.Conical(false, new UserBlendOps.NormalBlendOp()), 2)); benchmarks.Add(new GradientBenchmark( "Radial gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.Radial(false, new UserBlendOps.NormalBlendOp()), 2)); #endif #if COMPOSITION // Composition benchmarks Document doc1 = new Document(surface.Size); BitmapLayer layer1 = Layer.CreateBackgroundLayer(doc1.Width, doc1.Height); layer1.Surface.CopySurface(surface); doc1.Layers.Add(layer1); doc1.Layers.Add(layer1.Clone()); doc1.Layers.Add(layer1.Clone()); doc1.Layers.Add(layer1.Clone()); benchmarks.Add(new CompositionBenchmark("Compositing one layer, Normal blend mode, 255 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else { layer.Visible = false; } })); benchmarks.Add(new CompositionBenchmark("Compositing one layer, Normal blend mode, 128 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else { layer.Visible = false; } })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 255 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 255 (layer 0) and 128 (layer 1-3) opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 128 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing three layers, Normal+Multiply+Overlay blending, 150+255+170 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 150; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else if (layerIndex == 1) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.MultiplyBlendOp()); } else if (layerIndex == 2) { layer.Visible = true; layer.Opacity = 170; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.OverlayBlendOp()); } else { layer.Visible = false; } })); #endif #if TRANSFORM // Transform benchmarks Matrix m = new Matrix(); m.Reset(); MaskedSurface msSimple = new MaskedSurface(surface, new PdnRegion(surface.Bounds)); // simple masked surface PdnRegion complexRegion = new PdnRegion(surface.Bounds); // cut 4 holes in region 1 to form a complex clipping surface for (int x = -1; x < 3; ++x) { for (int y = -1; y < 3; ++y) { int left = (1 + (x * 3)) * (surface.Width / 6); int top = (1 + (x * 3)) * (surface.Height / 6); int right = (2 + (x * 3)) * (surface.Width / 6); int bottom = (2 + (x * 3)) * (surface.Height / 6); Rectangle rect = Rectangle.FromLTRB(left, top, right, bottom); PdnGraphicsPath path = new PdnGraphicsPath(); path.AddEllipse(rect); complexRegion.Exclude(path); } } MaskedSurface msComplex = new MaskedSurface(surface, complexRegion); benchmarks.Add(new TransformBenchmark("Transform simple surface, no transform, nearest neighbor resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, false)); benchmarks.Add(new TransformBenchmark("Transform complex surface, no transform, nearest neighbor resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, false)); benchmarks.Add(new TransformBenchmark("Transform simple surface, no transform, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, no transform, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, true)); Matrix m2 = m.Clone(); m2.RotateAt(45.0f, new PointF(surface.Width / 2, surface.Height / 2)); benchmarks.Add(new TransformBenchmark("Transform simple surface, 45 deg. rotation about center, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m2, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, 45 deg. rotation about center, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m2, true)); Matrix m3 = m.Clone(); m3.Scale(0.5f, 0.75f); benchmarks.Add(new TransformBenchmark("Transform simple surface, 50% x-scaling 75% y-scaling, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m3, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, 50% x-scaling 75% y-scaling, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m3, true)); #endif #if BLIT // Blit benchmarks benchmarks.Add(new ZoomOutBlitBenchmark("Zoom out, rotated grid multisampling, 66% (" + ZoomOutBlitBenchmark.IterationCount + "x)", surface, dst, new Size((surface.Width * 2) / 3, (surface.Height * 2) / 3))); benchmarks.Add(new ZoomOutBlitBenchmark("Zoom out, rotated grid multisampling, 28% (" + ZoomOutBlitBenchmark.IterationCount + "x)", surface, dst, new Size((surface.Width * 28) / 100, (surface.Height * 28) / 100))); benchmarks.Add(new ZoomOneToOneBlitBenchmark("Zoom 1:1, straight blit (" + ZoomOneToOneBlitBenchmark.IterationCount + "x)", surface, dst.CreateWindow(new Rectangle(0, 0, surface.Width, surface.Height)))); #endif // Run benchmarks! Timing timing = new Timing(); ulong start = timing.GetTickCount(); foreach (Benchmark benchmark in benchmarks) { Console.Write(benchmark.Name + (useTsvOutput ? "\t" : " ... ")); TimeSpan timeSpan = benchmark.Execute(); Console.WriteLine(" " + timeSpan.TotalMilliseconds.ToString() + (useTsvOutput ? "\t" : "") + " milliseconds"); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); } ulong end = timing.GetTickCount(); Console.WriteLine(); Console.WriteLine("Total time: " + (useTsvOutput ? "\t" : "") + (end - start).ToString() + (useTsvOutput ? "\t" : "") + " milliseconds"); Console.WriteLine(); }
public void RunEffect(Type effectType) { bool oldDirtyValue = AppWorkspace.ActiveDocumentWorkspace.Document.Dirty; bool resetDirtyValue = false; AppWorkspace.Update(); // make sure the window is done 'closing' AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); DocumentWorkspace activeDW = AppWorkspace.ActiveDocumentWorkspace; PdnRegion selectedRegion; if (activeDW.Selection.IsEmpty) { selectedRegion = new PdnRegion(activeDW.Document.Bounds); } else { selectedRegion = activeDW.Selection.CreateRegion(); } BitmapLayer layer = (BitmapLayer)activeDW.ActiveLayer; using (new PushNullToolMode(activeDW)) { try { Effect effect = (Effect)Activator.CreateInstance(effectType); EffectEnvironmentParameters eep = new EffectEnvironmentParameters( AppWorkspace.AppEnvironment.PrimaryColor, AppWorkspace.AppEnvironment.SecondaryColor, AppWorkspace.AppEnvironment.PenInfo.Width, selectedRegion); string name = effect.Name; EffectConfigToken newLastToken = null; effect.EnvironmentParameters = eep; if (!(effect.IsConfigurable)) { Surface copy = activeDW.BorrowScratchSurface(this.GetType() + ".RunEffect() using scratch surface for non-configurable rendering"); try { using (new WaitCursorChanger(AppWorkspace)) { copy.CopySurface(layer.Surface); } DoEffect(effect, null, selectedRegion, selectedRegion, copy); } finally { activeDW.ReturnScratchSurface(copy); } } else { PdnRegion previewRegion = (PdnRegion)selectedRegion.Clone(); previewRegion.Intersect(RectangleF.Inflate(activeDW.VisibleDocumentRectangleF, 1, 1)); Surface originalSurface = activeDW.BorrowScratchSurface(this.GetType() + ".RunEffect() using scratch surface for rendering during configuration"); try { using (new WaitCursorChanger(AppWorkspace)) { originalSurface.CopySurface(layer.Surface); } // AppWorkspace.SuspendThumbnailUpdates(); // using (EffectConfigDialog configDialog = effect.CreateConfigDialog()) { configDialog.Opacity = 0.9; configDialog.Effect = effect; configDialog.EffectSourceSurface = originalSurface; configDialog.Selection = selectedRegion; EventHandler eh = new EventHandler(EffectConfigTokenChangedHandler); configDialog.EffectTokenChanged += eh; if (this.effectTokens.ContainsKey(effectType)) { EffectConfigToken oldToken = (EffectConfigToken)effectTokens[effectType].Clone(); configDialog.EffectToken = oldToken; } BackgroundEffectRenderer ber = new BackgroundEffectRenderer( effect, configDialog.EffectToken, new RenderArgs(layer.Surface), new RenderArgs(originalSurface), previewRegion, tilesPerCpu * renderingThreadCount, renderingThreadCount); ber.RenderedTile += new RenderedTileEventHandler(RenderedTileHandler); ber.StartingRendering += new EventHandler(StartingRenderingHandler); ber.FinishedRendering += new EventHandler(FinishedRenderingHandler); configDialog.Tag = ber; invalidateTimer.Enabled = true; DialogResult dr = Utility.ShowDialog(configDialog, AppWorkspace); invalidateTimer.Enabled = false; this.InvalidateTimer_Tick(invalidateTimer, EventArgs.Empty); if (dr == DialogResult.OK) { this.effectTokens[effectType] = (EffectConfigToken)configDialog.EffectToken.Clone(); } using (new WaitCursorChanger(AppWorkspace)) { ber.Abort(); ber.Join(); ber.Dispose(); ber = null; if (dr != DialogResult.OK) { ((BitmapLayer)activeDW.ActiveLayer).Surface.CopySurface(originalSurface); activeDW.ActiveLayer.Invalidate(); } configDialog.EffectTokenChanged -= eh; configDialog.Hide(); AppWorkspace.Update(); previewRegion.Dispose(); } // AppWorkspace.ResumeThumbnailUpdates(); // if (dr == DialogResult.OK) { PdnRegion remainingToRender = selectedRegion.Clone(); PdnRegion alreadyRendered = PdnRegion.CreateEmpty(); for (int i = 0; i < this.progressRegions.Length; ++i) { if (this.progressRegions[i] == null) { break; } else { remainingToRender.Exclude(this.progressRegions[i]); alreadyRendered.Union(this.progressRegions[i]); } } activeDW.ActiveLayer.Invalidate(alreadyRendered); newLastToken = (EffectConfigToken)configDialog.EffectToken.Clone(); AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); DoEffect(effect, newLastToken, selectedRegion, remainingToRender, originalSurface); } else // if (dr == DialogResult.Cancel) { using (new WaitCursorChanger(AppWorkspace)) { activeDW.ActiveLayer.Invalidate(); Utility.GCFullCollect(); } resetDirtyValue = true; return; } } } finally { activeDW.ReturnScratchSurface(originalSurface); } } // if it was from the Effects menu, save it as the "Repeat ...." item if (effect.Category == EffectCategory.Effect) { this.lastEffect = effect; if (newLastToken == null) { this.lastEffectToken = null; } else { this.lastEffectToken = (EffectConfigToken)newLastToken.Clone(); } PopulateMenu(true); } } finally { selectedRegion.Dispose(); AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); AppWorkspace.Widgets.StatusBarProgress.EraseProgressStatusBar(); AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = true; for (int i = 0; i < this.progressRegions.Length; ++i) { if (this.progressRegions[i] != null) { this.progressRegions[i].Dispose(); this.progressRegions[i] = null; } } if (resetDirtyValue) { AppWorkspace.ActiveDocumentWorkspace.Document.Dirty = oldDirtyValue; } } } }
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; } }
private void DrawGradient(Graphics g) { Rectangle rectangle; double num; g.PixelOffsetMode = PixelOffsetMode.Half; System.Windows.Forms.Orientation orientation = this.orientation; if (orientation != System.Windows.Forms.Orientation.Horizontal) { if (orientation != System.Windows.Forms.Orientation.Vertical) { throw ExceptionUtil.InvalidEnumArgumentException <System.Windows.Forms.Orientation>(this.orientation, "this.Orientation"); } } else { num = 180.0; goto Label_0040; } num = 90.0; Label_0040: rectangle = base.ClientRectangle; orientation = this.orientation; if (orientation != System.Windows.Forms.Orientation.Horizontal) { if (orientation != System.Windows.Forms.Orientation.Vertical) { throw ExceptionUtil.InvalidEnumArgumentException <System.Windows.Forms.Orientation>(this.orientation, "this.Orientation"); } } else { rectangle.Inflate(-3, -4); goto Label_0082; } rectangle.Inflate(-4, -3); Label_0082: if (((this.customGradient != null) && (rectangle.Width > 1)) && (rectangle.Height > 1)) { Surface surface = new Surface(rectangle.Size.ToSizeInt32()); using (RenderArgs args = new RenderArgs(surface)) { ColorRectangle.Draw(args.Graphics, args.Bounds, Color.Transparent, true, false); if (this.Orientation == System.Windows.Forms.Orientation.Horizontal) { for (int j = 0; j < surface.Width; j++) { double num16; double num17; double num18; double d = ((double)(j * (this.customGradient.Length - 1))) / ((double)(surface.Width - 1)); int index = (int)Math.Floor(d); double num5 = 1.0 - (d - index); int num6 = (int)Math.Min((double)(this.customGradient.Length - 1), Math.Ceiling(d)); Color c = this.customGradient[index]; Color disabledColor = this.customGradient[num6]; if (!base.Enabled) { c = DisabledRendering.GetDisabledColor(c); disabledColor = DisabledRendering.GetDisabledColor(disabledColor); } double num7 = ((double)c.A) / 255.0; double num8 = ((double)c.R) / 255.0; double num9 = ((double)c.G) / 255.0; double num10 = ((double)c.B) / 255.0; double num11 = ((double)disabledColor.A) / 255.0; double num12 = ((double)disabledColor.R) / 255.0; double num13 = ((double)disabledColor.G) / 255.0; double num14 = ((double)disabledColor.B) / 255.0; double num15 = (num5 * num7) + ((1.0 - num5) * num11); if (num15 == 0.0) { num16 = 0.0; num17 = 0.0; num18 = 0.0; } else { num16 = (((num5 * num7) * num8) + (((1.0 - num5) * num11) * num12)) / num15; num17 = (((num5 * num7) * num9) + (((1.0 - num5) * num11) * num13)) / num15; num18 = (((num5 * num7) * num10) + (((1.0 - num5) * num11) * num14)) / num15; } int num19 = ((int)Math.Round((double)(num15 * 255.0), MidpointRounding.AwayFromZero)).Clamp(0, 0xff); int num20 = ((int)Math.Round((double)(num16 * 255.0), MidpointRounding.AwayFromZero)).Clamp(0, 0xff); int num21 = ((int)Math.Round((double)(num17 * 255.0), MidpointRounding.AwayFromZero)).Clamp(0, 0xff); int num22 = ((int)Math.Round((double)(num18 * 255.0), MidpointRounding.AwayFromZero)).Clamp(0, 0xff); for (int k = 0; k < surface.Height; k++) { ColorBgra bgra = surface[j, k]; int num24 = ((num20 * num19) + (bgra.R * (0xff - num19))) / 0xff; int num25 = ((num21 * num19) + (bgra.G * (0xff - num19))) / 0xff; int num26 = ((num22 * num19) + (bgra.B * (0xff - num19))) / 0xff; surface[j, k] = ColorBgra.FromBgra((byte)num26, (byte)num25, (byte)num24, 0xff); } } g.DrawImage(args.Bitmap, rectangle, args.Bounds, GraphicsUnit.Pixel); } else if (this.Orientation != System.Windows.Forms.Orientation.Vertical) { throw ExceptionUtil.InvalidEnumArgumentException <System.Windows.Forms.Orientation>(this.orientation, "this.Orientation"); } } surface.Dispose(); } else { Color color3 = base.Enabled ? this.maxColor : DisabledRendering.GetDisabledColor(this.maxColor); Color color4 = base.Enabled ? this.minColor : DisabledRendering.GetDisabledColor(this.minColor); using (LinearGradientBrush brush = new LinearGradientBrush(base.ClientRectangle, color3, color4, (float)num, false)) { g.FillRectangle(brush, rectangle); } } using (PdnRegion region = new PdnRegion()) { region.MakeInfinite(); region.Exclude(rectangle); using (SolidBrush brush2 = new SolidBrush(this.BackColor)) { g.FillRegion(brush2, region.GetRegionReadOnly()); } } for (int i = 0; i < this.vals.Length; i++) { Brush blue; Pen pen; Point point; Point point2; Point point3; Point point4; Point point5; Point point6; int x = this.ValueToPosition(this.vals[i]); if (i == this.highlight) { blue = Brushes.Blue; pen = (Pen)Pens.White.Clone(); } else { blue = base.Enabled ? Brushes.Black : Brushes.Gray; pen = (Pen)Pens.Gray.Clone(); } g.SmoothingMode = SmoothingMode.AntiAlias; orientation = this.orientation; if (orientation != System.Windows.Forms.Orientation.Horizontal) { if (orientation != System.Windows.Forms.Orientation.Vertical) { throw ExceptionUtil.InvalidEnumArgumentException <System.Windows.Forms.Orientation>(this.orientation, "this.Orientation"); } } else { point = new Point(x - 3, 0); point2 = new Point(x, 6); point3 = new Point(x + 3, 0); point4 = new Point(point.X, (base.Height - 1) - point.Y); point5 = new Point(point2.X, (base.Height - 1) - point2.Y); point6 = new Point(point3.X, (base.Height - 1) - point3.Y); goto Label_0678; } point = new Point(0, x - 3); point2 = new Point(6, x); point3 = new Point(0, x + 3); point4 = new Point((base.Width - 1) - point.X, point.Y); point5 = new Point((base.Width - 1) - point2.X, point2.Y); point6 = new Point((base.Width - 1) - point3.X, point3.Y); Label_0678: if (this.drawNearNub) { Point[] points = new Point[] { point, point2, point3, point }; g.FillPolygon(blue, points); } if (this.drawFarNub) { Point[] pointArray2 = new Point[] { point4, point5, point6, point4 }; g.FillPolygon(blue, pointArray2); } if (pen != null) { if (this.drawNearNub) { Point[] pointArray3 = new Point[] { point, point2, point3, point }; g.DrawPolygon(pen, pointArray3); } if (this.drawFarNub) { Point[] pointArray4 = new Point[] { point4, point5, point6, point4 }; g.DrawPolygon(pen, pointArray4); } pen.Dispose(); } } }
public void RunEffect(Type effectType) { bool oldDirtyValue = AppWorkspace.ActiveDocumentWorkspace.Document.Dirty; bool resetDirtyValue = false; AppWorkspace.Update(); // make sure the window is done 'closing' AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); DocumentWorkspace activeDW = AppWorkspace.ActiveDocumentWorkspace; PdnRegion selectedRegion; if (activeDW.Selection.IsEmpty) { selectedRegion = new PdnRegion(activeDW.Document.Bounds); } else { selectedRegion = activeDW.Selection.CreateRegion(); } Exception exception = null; Effect effect = null; BitmapLayer layer = (BitmapLayer)activeDW.ActiveLayer; using (new PushNullToolMode(activeDW)) { try { effect = (Effect)Activator.CreateInstance(effectType); string name = effect.Name; EffectConfigToken newLastToken = null; if (!(effect.CheckForEffectFlags(EffectFlags.Configurable))) { Surface copy = activeDW.BorrowScratchSurface(GetType() + ".RunEffect() using scratch surface for non-configurable rendering"); try { using (new WaitCursorChanger(AppWorkspace)) { copy.CopySurface(layer.Surface); } EffectEnvironmentParameters eep = new EffectEnvironmentParameters( AppWorkspace.AppEnvironment.PrimaryColor, AppWorkspace.AppEnvironment.SecondaryColor, AppWorkspace.AppEnvironment.PenInfo.Width, selectedRegion, copy); effect.EnvironmentParameters = eep; DoEffect(effect, null, selectedRegion, selectedRegion, copy, out exception); } finally { activeDW.ReturnScratchSurface(copy); } } else { PdnRegion previewRegion = (PdnRegion)selectedRegion.Clone(); previewRegion.Intersect(RectangleF.Inflate(activeDW.VisibleDocumentRectangleF, 1, 1)); Surface originalSurface = activeDW.BorrowScratchSurface(GetType() + ".RunEffect() using scratch surface for rendering during configuration"); try { using (new WaitCursorChanger(AppWorkspace)) { originalSurface.CopySurface(layer.Surface); } EffectEnvironmentParameters eep = new EffectEnvironmentParameters( AppWorkspace.AppEnvironment.PrimaryColor, AppWorkspace.AppEnvironment.SecondaryColor, AppWorkspace.AppEnvironment.PenInfo.Width, selectedRegion, originalSurface); effect.EnvironmentParameters = eep; // IDisposable resumeTUFn = AppWorkspace.SuspendThumbnailUpdates(); // using (EffectConfigDialog configDialog = effect.CreateConfigDialog()) { configDialog.Opacity = 0.9; configDialog.Effect = effect; configDialog.EffectSourceSurface = originalSurface; configDialog.Selection = selectedRegion; BackgroundEffectRenderer ber = null; void OnEffectTokenChanged(object sender, EventArgs e) { EffectConfigDialog ecf = (EffectConfigDialog)sender; if (ber != null) { AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBarAsync(); try { ber.Start(); } catch (Exception ex) { exception = ex; ecf.Close(); } } } configDialog.EffectTokenChanged += OnEffectTokenChanged; if (EffectTokens.ContainsKey(effectType)) { EffectConfigToken oldToken = (EffectConfigToken)EffectTokens[effectType].Clone(); configDialog.EffectToken = oldToken; } int pixelCount = layer.Surface.Height; int threadCount = effect.CheckForEffectFlags(EffectFlags.SingleThreaded) ? 1 : RenderingThreadCount; int maxTiles = TilesPerCpu * threadCount; int tileCount = Math.Min(maxTiles, pixelCount); ber = new BackgroundEffectRenderer( effect, configDialog.EffectToken, new RenderArgs(layer.Surface), new RenderArgs(originalSurface), previewRegion, tileCount, threadCount); ber.RenderedTile += new RenderedTileEventHandler(RenderedTileHandler); ber.StartingRendering += new EventHandler(StartingRenderingHandler); ber.FinishedRendering += new EventHandler(FinishedRenderingHandler); InvalidateTimer.Enabled = true; DialogResult dr; try { dr = Utility.ShowDialog(configDialog, AppWorkspace); } catch (Exception ex) { dr = DialogResult.None; exception = ex; } InvalidateTimer.Enabled = false; InvalidateTimer_Tick(InvalidateTimer, EventArgs.Empty); if (dr == DialogResult.OK) { EffectTokens[effectType] = (EffectConfigToken)configDialog.EffectToken.Clone(); } using (new WaitCursorChanger(AppWorkspace)) { try { ber.Abort(); ber.Join(); } catch (Exception ex) { exception = ex; } ber.Dispose(); ber = null; if (dr != DialogResult.OK) { ((BitmapLayer)activeDW.ActiveLayer).Surface.CopySurface(originalSurface); activeDW.ActiveLayer.Invalidate(); } configDialog.EffectTokenChanged -= OnEffectTokenChanged; configDialog.Hide(); AppWorkspace.Update(); previewRegion.Dispose(); } // resumeTUFn.Dispose(); resumeTUFn = null; // if (dr == DialogResult.OK) { PdnRegion remainingToRender = selectedRegion.Clone(); PdnRegion alreadyRendered = PdnRegion.CreateEmpty(); for (int i = 0; i < ProgressRegions.Length; ++i) { if (ProgressRegions[i] == null) { break; } else { remainingToRender.Exclude(ProgressRegions[i]); alreadyRendered.Union(ProgressRegions[i]); } } activeDW.ActiveLayer.Invalidate(alreadyRendered); newLastToken = (EffectConfigToken)configDialog.EffectToken.Clone(); AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); DoEffect(effect, newLastToken, selectedRegion, remainingToRender, originalSurface, out exception); } else // if (dr == DialogResult.Cancel) { using (new WaitCursorChanger(AppWorkspace)) { activeDW.ActiveLayer.Invalidate(); Utility.GCFullCollect(); } resetDirtyValue = true; return; } } } catch (Exception ex) { exception = ex; } finally { activeDW.ReturnScratchSurface(originalSurface); } } // if it was from the Effects menu, save it as the "Repeat ...." item if (effect.Category == EffectCategory.Effect) { LastEffect = effect; LastEffectToken = newLastToken == null ? null : (EffectConfigToken)newLastToken.Clone(); PopulateMenu(true); } } catch (Exception ex) { exception = ex; } finally { selectedRegion.Dispose(); AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); AppWorkspace.Widgets.StatusBarProgress.EraseProgressStatusBar(); AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = true; if (ProgressRegions != null) { for (int i = 0; i < ProgressRegions.Length; ++i) { ProgressRegions[i]?.Dispose(); ProgressRegions[i] = null; } } if (resetDirtyValue) { AppWorkspace.ActiveDocumentWorkspace.Document.Dirty = oldDirtyValue; } if (exception != null) { HandleEffectException(AppWorkspace, effect, exception); } } } }