Browse Source

Merge pull request #7 from flabbet/dev

Small performance improvements
Krzysztof Krysiński 5 years ago
parent
commit
7f78c7ec3c

+ 1 - 1
PixiEditorDotNetCore3/Models/Images/BitmapConverter.cs

@@ -17,6 +17,6 @@ namespace PixiEditorDotNetCore3.Models.Images
             WriteableBitmap bitmap = BitmapFactory.New(currentBitmapWidth, currentBitmapHeight);
             bitmap.FromByteArray(byteArray);
             return bitmap;
-        }
+        }      
     }
 }

+ 26 - 8
PixiEditorDotNetCore3/Models/Layers/Layer.cs

@@ -1,14 +1,9 @@
-using PixiEditor.Helpers;
-using PixiEditorDotNetCore3.Models.Tools;
+using PixiEditorDotNetCore3.Models.Tools;
 using System;
-using System.Collections.Generic;
 using System.ComponentModel;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
+using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 using System.Windows;
-using System.Windows.Controls;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 
@@ -46,10 +41,33 @@ namespace PixiEditorDotNetCore3.Models.Layers
 
         public void ApplyPixels(BitmapPixelChanges pixels, Color color)
         {
+            LayerBitmap.Lock();
+
             foreach (var coords in pixels.ChangedCoordinates)
             {
-                LayerBitmap.SetPixel(Math.Clamp(coords.X, 0, Width - 1), Math.Clamp(coords.Y, 0, Height - 1), color);
+                LayerBitmap.SetPixel(Math.Clamp(coords.X, 0, Width - 1), Math.Clamp(coords.Y, 0, Height - 1),
+                    color);
             }
+
+            LayerBitmap.Unlock();
+        }
+
+       
+        public byte[] ConvertBitmapToBytes()
+        {            
+            LayerBitmap.Lock();
+            byte[] byteArray = LayerBitmap.ToByteArray();
+            LayerBitmap.Unlock();
+            return byteArray;
         }
+
+        public byte[] ConvertBitmapToBytes(WriteableBitmap bitmap)
+        {
+            bitmap.Lock();
+            byte[] byteArray = bitmap.ToByteArray();
+            bitmap.Unlock();
+            return byteArray;
+        }
+
     }
 }

+ 4 - 1
PixiEditorDotNetCore3/Models/Layers/LayerGenerator.cs

@@ -28,7 +28,10 @@ namespace PixiEditorDotNetCore3.Models.Layers
         public static LightLayer GenerateWithByteArray(int width, int height)
         {
             WriteableBitmap bitmap = GenerateBitmap(width, height);
-            return new LightLayer(bitmap.ToByteArray(), height, width);
+            bitmap.Lock();
+            byte[] byteArray = bitmap.ToByteArray();
+            bitmap.Unlock();
+            return new LightLayer(byteArray, height, width);
         }
 
         /// <summary>

+ 0 - 29
PixiEditorDotNetCore3/Models/Tools/ToolManager.cs

@@ -1,29 +0,0 @@
-using PixiEditor.Helpers;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace PixiEditorDotNetCore3.Models.Tools
-{
-    class ToolManager : NotifyableObject
-    {
-
-        private ToolType _activeTool;
-
-        public ToolType ActiveTool
-        {
-            get { return _activeTool; }
-            set
-            {
-                if (_activeTool != value)
-                {
-                    _activeTool = value;
-                    RaisePropertyChanged("ActiveTool");
-                }
-            }
-        }
-    }
-}

+ 1 - 1
PixiEditorDotNetCore3/Models/Tools/Tools/LineTool.cs

@@ -16,7 +16,7 @@ namespace PixiEditorDotNetCore3.Models.Tools.Tools
         }
 
         public void CreateLine(Layer layer, Coordinates coordinates, Color color, int size)
-        {           
+        {
             layer.LayerBitmap.DrawLineBresenham(coordinates.X, coordinates.Y, MousePositionConverter.CurrentCoordinates.X,
                 MousePositionConverter.CurrentCoordinates.Y, color);
         }

+ 17 - 7
PixiEditorDotNetCore3/Models/Tools/ToolsManager.cs

@@ -42,24 +42,34 @@ namespace PixiEditorDotNetCore3.Models.Tools
         private void LoopTimer_Elapsed(object sender, ElapsedEventArgs e)
         {
             Application.Current.Dispatcher.Invoke(() =>
-            {              
-                if(_clonedBitmap != null)
+            {
+                _layer.LayerBitmap.Lock();
+
+                if (_clonedBitmap != null)
                 {
-                    _layer.LayerBitmap.Clear();
-                    _layer.LayerBitmap.Blit(new Rect(new Size(_layer.Width, _layer.Height)), _clonedBitmap, new Rect(new Size(_layer.Width, _layer.Height)), WriteableBitmapExtensions.BlendMode.Additive);
+                    RestoreLastBitmap();
                 }
+
                 BitmapPixelChanges changes = SelectedTool.Use(_layer, _startCoordinates, _color, _toolSzie);
 
                 if (!SelectedTool.ExecutesItself)
                 {
                     _layer.ApplyPixels(changes, changes.PixelsColor);
                 }
+                _layer.LayerBitmap.Unlock();
+
             });
         }
 
+        private void RestoreLastBitmap()
+        {
+            _layer.LayerBitmap.Clear();
+            _layer.LayerBitmap.Blit(new Rect(new Size(_layer.Width, _layer.Height)), _clonedBitmap, new Rect(new Size(_layer.Width, _layer.Height)), WriteableBitmapExtensions.BlendMode.Additive);
+        }
+
         public void SetTool(ToolType tool)
         {
-              SelectedTool = Tools.Find(x => x.ToolType == tool);
+            SelectedTool = Tools.Find(x => x.ToolType == tool);
         }
 
         public void StopExectuingTool()
@@ -79,7 +89,7 @@ namespace PixiEditorDotNetCore3.Models.Tools
         {
             if (SelectedTool.GetType().BaseType == typeof(ShapeTool))
             {
-                _clonedBitmap = _layer.LayerBitmap.Clone();                
+                _clonedBitmap = _layer.LayerBitmap.Clone();
             }
         }
 
@@ -97,7 +107,7 @@ namespace PixiEditorDotNetCore3.Models.Tools
             if (toolSize < 1)
                 return;
 
-            if(_toolRecievedData == false || (_toolRecievedData == true && SelectedTool.GetType().BaseType != typeof(ShapeTool)))
+            if (_toolRecievedData == false || (_toolRecievedData == true && SelectedTool.GetType().BaseType != typeof(ShapeTool)))
             {
                 _startCoordinates = startingCoords;
                 _layer = layer;

+ 3 - 0
PixiEditorDotNetCore3/PixiEditorDotNetCore3.csproj

@@ -5,6 +5,8 @@
     <TargetFramework>netcoreapp3.0</TargetFramework>
     <UseWPF>true</UseWPF>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
   </PropertyGroup>
   <ItemGroup>
     <PackageReference Include="Expression.Blend.Sdk">
@@ -14,6 +16,7 @@
       <Version>3.5.0</Version>
     </PackageReference>
     <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
+    <PackageReference Include="System.Drawing.Common" Version="4.6.0" />
     <PackageReference Include="WriteableBitmapEx">
       <Version>1.6.2</Version>
     </PackageReference>

+ 4 - 2
PixiEditorDotNetCore3/ViewModels/ViewModelMain.cs

@@ -69,7 +69,9 @@ namespace PixiEditor.ViewModels
             get 
             {
                 if (_activeLayer != null)
-                    return new LightLayer(_activeLayer.LayerBitmap.ToByteArray(), ActiveLayer.Height, ActiveLayer.Width);
+                    return new LightLayer(
+                        _activeLayer.ConvertBitmapToBytes(), 
+                        ActiveLayer.Height, ActiveLayer.Width);
                 else
                     return null;
             }
@@ -249,7 +251,7 @@ namespace PixiEditor.ViewModels
 
             if (SelectedTool != ToolType.ColorPicker)
             {
-                UndoManager.RecordChanges("ActiveLightLayer", new LightLayer(ActiveLayer.LayerBitmap.ToByteArray(), (int)ActiveLayer.LayerBitmap.Height, 
+                UndoManager.RecordChanges("ActiveLightLayer", new LightLayer(ActiveLayer.ConvertBitmapToBytes(), (int)ActiveLayer.LayerBitmap.Height, 
                     (int)ActiveLayer.LayerBitmap.Width), $"Used {SelectedTool.ToString()}");
                 primaryToolSet.ExecuteTool(ActiveLayer, cords, SelectedColor, ToolSize);
                 RefreshImage();

+ 1 - 1
PixiEditorDotNetCore3/Views/MainWindow.xaml

@@ -11,7 +11,7 @@
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
         xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
         mc:Ignorable="d"
-        Title="Pixi" Height="1000" Width="1600" Background="#FF252424" WindowStartupLocation="CenterScreen"  WindowState="Maximized" DataContext="{DynamicResource ViewModelMain}">
+        Title="PixiEditor" Height="1000" Width="1600" Background="#FF252424" WindowStartupLocation="CenterScreen"  WindowState="Maximized" DataContext="{DynamicResource ViewModelMain}">
     <Window.Resources>
         <vm:ViewModelMain x:Key="ViewModelMain"/>
         <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>

+ 33 - 0
PixiEditorTests/PerformanceTests/BitmapOperationsTests.cs

@@ -0,0 +1,33 @@
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Media.Imaging;
+
+namespace PixiEditorTests.PerformanceTests
+{
+    [TestFixture]
+    public class BitmapOperationsTests
+    {
+        [TestCase(16,16)]
+        [TestCase(128, 128)]
+        [TestCase(512, 512)]
+        [TestCase(1024, 1024)]
+        [TestCase(2046, 2046)]
+        [TestCase(4096, 4096)]
+        public void FillBitmapWithPixelsTest(int width, int height)
+        {
+            WriteableBitmap bitmap = BitmapFactory.New(width, height);
+            bitmap.Lock();
+
+            for (int i = 0; i < width * height; i++)
+            {
+                bitmap.SetPixeli(i, 0xFFFFF);
+
+            }
+            bitmap.Unlock();
+
+            Assert.Pass();
+        }
+    }
+}