Browse Source

Improved scaled exporting for vectors

flabbet 8 months ago
parent
commit
92672fcaad

+ 9 - 7
src/PixiEditor/Models/Files/ImageFileType.cs

@@ -32,17 +32,19 @@ internal abstract class ImageFileType : IoFileType
         }
         else
         {
-            job?.Report(0, new LocalizedString("RENDERING_IMAGE")); 
-            var maybeBitmap = document.TryRenderWholeImage(0);
+            job?.Report(0, new LocalizedString("RENDERING_IMAGE"));
+            
+            var exportSize = exportConfig.ExportSize;
+            if (exportSize.X <= 0 || exportSize.Y <= 0)
+            {
+                return SaveResult.UnknownError; // TODO: Add InvalidParameters error type
+            }
+            
+            var maybeBitmap = document.TryRenderWholeImage(0, exportSize);
             if (maybeBitmap.IsT0)
                 return SaveResult.ConcurrencyError;
 
             finalSurface = maybeBitmap.AsT1;
-            if (maybeBitmap.AsT1.Size != exportConfig.ExportSize && exportConfig.ExportSize.X > 0 && exportConfig.ExportSize.Y > 0)
-            {
-                finalSurface = finalSurface.ResizeNearestNeighbor(exportConfig.ExportSize);
-                maybeBitmap.AsT1.Dispose();
-            }
         }
 
         EncodedImageFormat mappedFormat = EncodedImageFormat;

+ 22 - 12
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -234,13 +234,13 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
 
         TransformViewModel = new(this);
         TransformViewModel.TransformMoved += (_, args) => Internals.ChangeController.TransformMovedInlet(args);
-        
+
         PathOverlayViewModel = new(this, Internals);
         PathOverlayViewModel.PathChanged += path =>
         {
             Internals.ChangeController.PathOverlayChangedInlet(path);
         };
-        
+
         LineToolOverlayViewModel = new();
         LineToolOverlayViewModel.LineMoved += (_, args) =>
             Internals.ChangeController.LineOverlayMovedInlet(args.Item1, args.Item2);
@@ -519,22 +519,22 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         OnPropertyChanged(nameof(AllChangesSaved));
     }
 
-
-    /// <summary>
-    /// Tries rendering the whole document
-    /// </summary>
-    /// <returns><see cref="Error"/> if the ChunkyImage was disposed, otherwise a <see cref="Surface"/> of the rendered document</returns>
-    public OneOf<Error, Surface> TryRenderWholeImage(KeyFrameTime frameTime)
+    public OneOf<Error, Surface> TryRenderWholeImage(KeyFrameTime frameTime, VecI renderSize)
     {
         try
         {
-            Surface finalSurface = null; 
+            Surface finalSurface = null;
             DrawingBackendApi.Current.RenderingDispatcher.Invoke(() =>
             {
-                using Texture texture = new Texture(SizeBindable);
-                Renderer.RenderDocument(texture.DrawingSurface, frameTime);
+                using Texture texture = new Texture(renderSize);
+                texture.DrawingSurface.Canvas.Save();
+                VecD scaling = new VecD(renderSize.X / (double)SizeBindable.X, renderSize.Y / (double)SizeBindable.Y);
                 
-                finalSurface = new Surface(SizeBindable);
+                texture.DrawingSurface.Canvas.Scale((float)scaling.X, (float)scaling.Y);
+                Renderer.RenderDocument(texture.DrawingSurface, frameTime);
+
+                texture.DrawingSurface.Canvas.Restore();
+                finalSurface = new Surface(renderSize);
                 finalSurface.DrawingSurface.Canvas.DrawImage(texture.DrawingSurface.Snapshot(), 0, 0);
             });
 
@@ -546,6 +546,16 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         }
     }
 
+    /// <summary>
+    /// Tries rendering the whole document
+    /// </summary>
+    /// <returns><see cref="Error"/> if the ChunkyImage was disposed, otherwise a <see cref="Surface"/> of the rendered document</returns>
+    public OneOf<Error, Surface> TryRenderWholeImage(KeyFrameTime frameTime)
+    {
+        return TryRenderWholeImage(frameTime, SizeBindable);
+    }
+
+
     /// <summary>
     /// Takes the selected area and converts it into a surface
     /// </summary>