Browse Source

Brought back tight previews for small documents

Krzysztof Krysiński 2 months ago
parent
commit
d7d81b2e29

+ 6 - 1
src/ChunkyImageLib/ChunkyImage.cs

@@ -191,7 +191,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
     /// Finds the precise bounds in <paramref name="suggestedResolution"/>. If there are no chunks rendered for that resolution, full res chunks are used instead.
     /// Finds the precise bounds in <paramref name="suggestedResolution"/>. If there are no chunks rendered for that resolution, full res chunks are used instead.
     /// </summary>
     /// </summary>
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
-    public RectI? FindTightCommittedBounds(ChunkResolution suggestedResolution = ChunkResolution.Full)
+    public RectI? FindTightCommittedBounds(ChunkResolution suggestedResolution = ChunkResolution.Full, bool fallbackToChunkAligned = false)
     {
     {
         lock (lockObject)
         lock (lockObject)
         {
         {
@@ -225,6 +225,11 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
                 }
                 }
                 else
                 else
                 {
                 {
+                    if (fallbackToChunkAligned)
+                    {
+                        return FindChunkAlignedCommittedBounds();
+                    }
+
                     RectI visibleArea = new RectI(chunkPos * FullChunkSize, new VecI(FullChunkSize))
                     RectI visibleArea = new RectI(chunkPos * FullChunkSize, new VecI(FullChunkSize))
                         .Intersect(new RectI(VecI.Zero, CommittedSize)).Translate(-chunkPos * FullChunkSize);
                         .Intersect(new RectI(VecI.Zero, CommittedSize)).Translate(-chunkPos * FullChunkSize);
 
 

+ 1 - 1
src/ChunkyImageLib/IReadOnlyChunkyImage.cs

@@ -14,7 +14,7 @@ public interface IReadOnlyChunkyImage
     bool DrawCommittedChunkOn(VecI chunkPos, ChunkResolution resolution, DrawingSurface surface, VecD pos, Paint? paint = null);
     bool DrawCommittedChunkOn(VecI chunkPos, ChunkResolution resolution, DrawingSurface surface, VecD pos, Paint? paint = null);
     RectI? FindChunkAlignedMostUpToDateBounds();
     RectI? FindChunkAlignedMostUpToDateBounds();
     RectI? FindChunkAlignedCommittedBounds();
     RectI? FindChunkAlignedCommittedBounds();
-    RectI? FindTightCommittedBounds(ChunkResolution precision = ChunkResolution.Full);
+    RectI? FindTightCommittedBounds(ChunkResolution precision = ChunkResolution.Full, bool fallbackToChunkAligned = false);
     Color GetCommittedPixel(VecI posOnImage);
     Color GetCommittedPixel(VecI posOnImage);
     Color GetMostUpToDatePixel(VecI posOnImage);
     Color GetMostUpToDatePixel(VecI posOnImage);
     bool LatestOrCommittedChunkExists(VecI chunkPos);
     bool LatestOrCommittedChunkExists(VecI chunkPos);

+ 27 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs

@@ -18,6 +18,8 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
     public const string ImageFramesKey = "Frames";
     public const string ImageFramesKey = "Frames";
     public const string ImageLayerKey = "LayerImage";
     public const string ImageLayerKey = "LayerImage";
 
 
+    public const int AccuratePreviewMaxSize = 2048;
+
     public override VecD GetScenePosition(KeyFrameTime time) => layerImage.CommittedSize / 2f;
     public override VecD GetScenePosition(KeyFrameTime time) => layerImage.CommittedSize / 2f;
     public override VecD GetSceneSize(KeyFrameTime time) => layerImage.CommittedSize;
     public override VecD GetSceneSize(KeyFrameTime time) => layerImage.CommittedSize;
 
 
@@ -49,7 +51,29 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
 
     public override RectD? GetApproxBounds(KeyFrameTime frameTime)
     public override RectD? GetApproxBounds(KeyFrameTime frameTime)
     {
     {
-        var chunkAlignedBounds = GetLayerImageAtFrame(frameTime.Frame).FindChunkAlignedCommittedBounds();
+        var layerImage = GetLayerImageAtFrame(frameTime.Frame);
+        return GetApproxBounds(layerImage);
+    }
+
+    private static RectD? GetApproxBounds(ChunkyImage layerImage)
+    {
+        if (layerImage.CommittedSize.LongestAxis <= AccuratePreviewMaxSize)
+        {
+            ChunkResolution resolution = layerImage.CommittedSize.LongestAxis switch
+            {
+                <= 256 => ChunkResolution.Full,
+                <= 512 => ChunkResolution.Half,
+                <= 1024 => ChunkResolution.Quarter,
+                _ => ChunkResolution.Eighth
+            };
+
+            // Half is efficient enough to be used even for full res chunks
+            bool fallbackToChunkAligned = (int)resolution > 2;
+
+            return (RectD?)layerImage.FindTightCommittedBounds(resolution, fallbackToChunkAligned);
+        }
+
+        var chunkAlignedBounds = layerImage.FindChunkAlignedCommittedBounds();
         if (chunkAlignedBounds == null)
         if (chunkAlignedBounds == null)
         {
         {
             return null;
             return null;
@@ -145,7 +169,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
                     return null;
                     return null;
                 }
                 }
 
 
-                RectI? bounds = kf.FindChunkAlignedCommittedBounds(); // Don't use tight bounds, very expensive
+                RectI? bounds = (RectI?)GetApproxBounds(kf);
                 if (bounds.HasValue)
                 if (bounds.HasValue)
                 {
                 {
                     return new RectD(bounds.Value.X, bounds.Value.Y,
                     return new RectD(bounds.Value.X, bounds.Value.Y,
@@ -163,7 +187,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
                 return null;
                 return null;
             }
             }
 
 
-            var bounds = kf.FindChunkAlignedCommittedBounds(); // Don't use tight bounds, very expensive
+            var bounds = GetApproxBounds(kf);
             if (bounds.HasValue)
             if (bounds.HasValue)
             {
             {
                 return new RectD(bounds.Value.X, bounds.Value.Y,
                 return new RectD(bounds.Value.X, bounds.Value.Y,