Przeglądaj źródła

DPI-based image scaling prototype (not ready for production)

MarcinZiabek 2 lat temu
rodzic
commit
8a358a8fa2

+ 22 - 0
Source/QuestPDF.Examples/Engine/Helpers.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using QuestPDF.Fluent;
+using QuestPDF.Infrastructure;
+
+namespace QuestPDF.Examples.Engine
+{
+    public static class Helpers
+    {
+        public static void GeneratePdfAndOpen(this Document document, string? fileName = null)
+        {
+            fileName ??= $"{Guid.NewGuid():D}.pdf";
+
+            var filePath = Path.GetTempPath() + fileName;
+            var documentData = document.GeneratePdf();
+            File.WriteAllBytes(filePath, documentData);
+            
+            Process.Start("explorer", filePath);
+        }
+    }
+}

+ 24 - 0
Source/QuestPDF.Examples/ImageExamples.cs

@@ -89,5 +89,29 @@ namespace QuestPDF.Examples
                         });
                 });
         }
+        
+        [Test]
+        public void ImageResolutionScaling()
+        {
+            var image = Image.FromFile("large-image.jpg");
+            
+            Document
+                .Create(document =>
+                {
+                    document.Page(page =>
+                    {
+                        page.Size(11000, 11000);
+                        page.Margin(50);
+                        page.Content().Image(image);
+                    });
+                })
+                .GeneratePdfAndOpen();
+
+           //Console.WriteLine(documentData.Length);
+            
+            // var filePath = Path.GetTempPath() + $"test.pdf";
+            // File.WriteAllBytes(filePath, documentData);
+            // Console.WriteLine(filePath);
+        }
     }
 }

+ 6 - 0
Source/QuestPDF.Examples/QuestPDF.Examples.csproj

@@ -32,6 +32,12 @@
       <None Update="pdf-icon.svg">
         <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       </None>
+      <None Update="large-image.png">
+        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      </None>
+      <None Update="large-image.jpg">
+        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      </None>
     </ItemGroup>
 
 </Project>

BIN
Source/QuestPDF.Examples/large-image.jpg


+ 1 - 1
Source/QuestPDF/Elements/Image.cs

@@ -27,7 +27,7 @@ namespace QuestPDF.Elements
             if (DocumentImage == null)
                 return;
 
-            Canvas.DrawImage(DocumentImage.SkImage, Position.Zero, availableSpace);
+            Canvas.DrawImage(DocumentImage.GetVersionOfSize(availableSpace), Position.Zero, availableSpace);
         }
     }
 }

+ 31 - 1
Source/QuestPDF/Infrastructure/Image.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.IO;
 using QuestPDF.Drawing.Exceptions;
 using SkiaSharp;
@@ -7,7 +8,8 @@ namespace QuestPDF.Infrastructure
 {
     public class Image : IDisposable
     {
-        internal SKImage SkImage { get; }
+        private SKImage SkImage { get; }
+        internal List<(Size size, SKImage image)>? ScaledImageCache { get; }
         internal bool IsDocumentScoped { get; set; }
         
         public int Width => SkImage.Width;
@@ -27,6 +29,34 @@ namespace QuestPDF.Infrastructure
         public void Dispose()
         {
             SkImage.Dispose();
+            ScaledImageCache?.ForEach(x => x.image.Dispose());
+        }
+
+        internal SKImage GetVersionOfSize(Size size)
+        {
+            if (size.Width > Width || size.Height > Height)
+                return SkImage;
+            
+            var target = SKImage.Create(new SKImageInfo((int)size.Width, (int)size.Height));
+            SkImage.ScalePixels(target.PeekPixels(), SKFilterQuality.High);
+
+            return target;
+
+            // bool ShouldApplyScaling()
+            // {
+            //     const float tolerance = 1.1f;
+            //     
+            //     if (width > Width / tolerance || height > Height / tolerance)
+            //         return false;
+            //     
+            //     SkImage.sca
+            // }
+            
+            static bool HasSimilarSize(Size a, Size b, float tolerance)
+            {
+                return (a.Width / b.Width > 1 / tolerance && a.Width / b.Width < tolerance) ||
+                       (a.Height / b.Height > 1 / tolerance && a.Height / b.Height < tolerance);
+            }
         }
 
         #region public constructors