From 1829ed7180f00fd1755e79bf6c1bafb3d6d062cd Mon Sep 17 00:00:00 2001 From: MarcinZiabek Date: Tue, 9 May 2023 01:11:49 +0200 Subject: [PATCH] Simplified image handling --- Source/QuestPDF/Drawing/DocumentGenerator.cs | 1 - Source/QuestPDF/Elements/DynamicImage.cs | 9 ++-- Source/QuestPDF/Elements/Image.cs | 48 +++++-------------- .../QuestPDF/Fluent/ImageModelExtensions.cs | 6 --- Source/QuestPDF/Helpers/Helpers.cs | 33 +++++++++++++ .../Infrastructure/DocumentSettings.cs | 9 ++-- Source/QuestPDF/Infrastructure/Image.cs | 29 +---------- .../Infrastructure/ImageResizeStrategy.cs | 11 ----- 8 files changed, 56 insertions(+), 90 deletions(-) delete mode 100644 Source/QuestPDF/Infrastructure/ImageResizeStrategy.cs diff --git a/Source/QuestPDF/Drawing/DocumentGenerator.cs b/Source/QuestPDF/Drawing/DocumentGenerator.cs index 336c90d..3133ea2 100644 --- a/Source/QuestPDF/Drawing/DocumentGenerator.cs +++ b/Source/QuestPDF/Drawing/DocumentGenerator.cs @@ -235,7 +235,6 @@ namespace QuestPDF.Drawing if (x is QuestPDF.Elements.Image image) { image.TargetDpi ??= settings.RasterDpi; - image.ResizeStrategy ??= settings.ImageResizeStrategy; image.CompressionQuality ??= settings.ImageCompressionQuality; } diff --git a/Source/QuestPDF/Elements/DynamicImage.cs b/Source/QuestPDF/Elements/DynamicImage.cs index 6a7d29b..4441c63 100644 --- a/Source/QuestPDF/Elements/DynamicImage.cs +++ b/Source/QuestPDF/Elements/DynamicImage.cs @@ -30,8 +30,11 @@ namespace QuestPDF.Elements if (imageData == null) return; - using var image = SKImage.FromEncodedData(imageData); - Canvas.DrawImage(image, Position.Zero, availableSpace); + using var originalImage = SKImage.FromEncodedData(imageData); + using var compressedImage = originalImage.CompressImage(CompressionQuality.Value); + + var targetImage = Helpers.Helpers.GetImageWithSmallerSize(originalImage, compressedImage); + Canvas.DrawImage(targetImage, Position.Zero, availableSpace); } private static ImageSize GetTargetResolution(Size availableSize, int targetDpi) @@ -44,4 +47,4 @@ namespace QuestPDF.Elements ); } } -} \ No newline at end of file +} diff --git a/Source/QuestPDF/Elements/Image.cs b/Source/QuestPDF/Elements/Image.cs index 2f05b2e..ca91841 100644 --- a/Source/QuestPDF/Elements/Image.cs +++ b/Source/QuestPDF/Elements/Image.cs @@ -12,7 +12,6 @@ namespace QuestPDF.Elements internal bool UseOriginalImage { get; set; } internal int? TargetDpi { get; set; } internal ImageCompressionQuality? CompressionQuality { get; set; } - internal ImageResizeStrategy? ResizeStrategy { get; set; } private const float ImageSizeSimilarityToleranceMax = 0.75f; @@ -40,56 +39,35 @@ namespace QuestPDF.Elements private SKImage GetImageToDraw(Size availableSpace) { + var originalImage = DocumentImage.SkImage; + if (UseOriginalImage) - return DocumentImage.SkImage; + return originalImage; var request = new GetImageVersionRequest { - Resolution = GetTargetResolution(ResizeStrategy.Value, DocumentImage.Size, availableSpace, TargetDpi.Value), - CompressionQuality = CompressionQuality.Value, - ResizeStrategy = ResizeStrategy.Value + Resolution = GetTargetResolution(DocumentImage.Size, availableSpace, TargetDpi.Value), + CompressionQuality = CompressionQuality.Value }; - return DocumentImage.GetVersionOfSize(request); + var targetImage = DocumentImage.GetVersionOfSize(request); + return Helpers.Helpers.GetImageWithSmallerSize(originalImage, targetImage); } - private static ImageSize GetTargetResolution(ImageResizeStrategy resizeStrategy, ImageSize imageResolution, Size availableAreaSize, int targetDpi) + private static ImageSize GetTargetResolution(ImageSize imageResolution, Size availableAreaSize, int targetDpi) { - if (resizeStrategy == ImageResizeStrategy.Never) - return imageResolution; - var scalingFactor = targetDpi / (float)DocumentSettings.DefaultRasterDpi; + var targetResolution = new ImageSize( (int)(availableAreaSize.Width * scalingFactor), (int)(availableAreaSize.Height * scalingFactor)); - - if (resizeStrategy == ImageResizeStrategy.Always) - return targetResolution; - var isSignificantlySmaller = IsImageSignificantlySmallerThanDrawingArea(imageResolution, targetResolution); - - if (resizeStrategy == ImageResizeStrategy.ScaleOnlyToSignificantlySmallerResolution && isSignificantlySmaller) - return targetResolution; + var isImageResolutionSmallerThanTarget = imageResolution.Width < targetResolution.Width || imageResolution.Height < targetResolution.Height; - var isSmaller = IsImageSmallerThanDrawingArea(imageResolution, targetResolution); + if (isImageResolutionSmallerThanTarget) + return imageResolution; - if (resizeStrategy == ImageResizeStrategy.ScaleOnlyToSmallerResolution && isSmaller) - return targetResolution; - - return imageResolution; - } - - private static bool IsImageSmallerThanDrawingArea(ImageSize imageResolution, ImageSize targetResolution) - { - return imageResolution.Width < targetResolution.Width || imageResolution.Height < targetResolution.Height; - } - - private static bool IsImageSignificantlySmallerThanDrawingArea(ImageSize imageResolution, ImageSize targetResolution, float sizeSimilarityThreshold = ImageSizeSimilarityToleranceMax) - { - var widthRatio = targetResolution.Width / imageResolution.Width; - var heightRatio = targetResolution.Height / imageResolution.Height; - - return widthRatio < sizeSimilarityThreshold && heightRatio < sizeSimilarityThreshold; + return targetResolution; } } } \ No newline at end of file diff --git a/Source/QuestPDF/Fluent/ImageModelExtensions.cs b/Source/QuestPDF/Fluent/ImageModelExtensions.cs index 5f91fb1..459dc42 100644 --- a/Source/QuestPDF/Fluent/ImageModelExtensions.cs +++ b/Source/QuestPDF/Fluent/ImageModelExtensions.cs @@ -52,12 +52,6 @@ namespace QuestPDF.Fluent return this; } - public ImageDescriptor WithResizeStrategy(ImageResizeStrategy strategy) - { - ImageElement.ResizeStrategy = strategy; - return this; - } - #region Aspect Ratio public ImageDescriptor FitWidth() diff --git a/Source/QuestPDF/Helpers/Helpers.cs b/Source/QuestPDF/Helpers/Helpers.cs index 89506c1..ea637ee 100644 --- a/Source/QuestPDF/Helpers/Helpers.cs +++ b/Source/QuestPDF/Helpers/Helpers.cs @@ -75,5 +75,38 @@ namespace QuestPDF.Helpers _ => throw new ArgumentOutOfRangeException(nameof(quality), quality, null) }; } + + internal static SKImage CompressImage(this SKImage image, ImageCompressionQuality compressionQuality) + { + var targetFormat = image.Info.IsOpaque + ? SKEncodedImageFormat.Jpeg + : SKEncodedImageFormat.Png; + + if (targetFormat == SKEncodedImageFormat.Png) + compressionQuality = ImageCompressionQuality.Best; + + var data = image.Encode(targetFormat, compressionQuality.ToQualityValue()); + return SKImage.FromEncodedData(data); + } + + internal static SKImage ResizeAndCompressImage(this SKImage image, ImageSize targetResolution, ImageCompressionQuality compressionQuality) + { + if (image.Width == targetResolution.Width && image.Height == targetResolution.Height) + return CompressImage(image, compressionQuality); + + var imageInfo = new SKImageInfo(targetResolution.Width, targetResolution.Height); + + using var resultImage = SKImage.Create(imageInfo); + image.ScalePixels(resultImage.PeekPixels(), SKFilterQuality.Medium); + + return CompressImage(resultImage, compressionQuality); + } + + internal static SKImage GetImageWithSmallerSize(SKImage one, SKImage second) + { + return one.EncodedData.Size < second.EncodedData.Size + ? one + : second; + } } } \ No newline at end of file diff --git a/Source/QuestPDF/Infrastructure/DocumentSettings.cs b/Source/QuestPDF/Infrastructure/DocumentSettings.cs index 5e0d294..0cc4e54 100644 --- a/Source/QuestPDF/Infrastructure/DocumentSettings.cs +++ b/Source/QuestPDF/Infrastructure/DocumentSettings.cs @@ -18,17 +18,14 @@ /// The default value is 90 (very high quality). /// public ImageCompressionQuality ImageCompressionQuality { get; set; } = ImageCompressionQuality.VeryHigh; - - // TODO: add comments - public ImageResizeStrategy ImageResizeStrategy { get; set; } = ImageResizeStrategy.ScaleOnlyToSignificantlySmallerResolution; - + /// /// The DPI (pixels-per-inch) at which images and features without native PDF support will be rasterized. /// A larger DPI would create a PDF that reflects the original intent with better fidelity, but it can make for larger PDF files too, which would use more memory while rendering, and it would be slower to be processed or sent online or to printer. /// When generating images, this parameter also controls the resolution of the generated content. - /// Default value is 72. + /// Default value is 144. /// - public int RasterDpi { get; set; } = DefaultRasterDpi; + public int RasterDpi { get; set; } = DefaultRasterDpi * 2; public ContentDirection ContentDirection { get; set; } = ContentDirection.LeftToRight; diff --git a/Source/QuestPDF/Infrastructure/Image.cs b/Source/QuestPDF/Infrastructure/Image.cs index 89f2611..5ed6579 100644 --- a/Source/QuestPDF/Infrastructure/Image.cs +++ b/Source/QuestPDF/Infrastructure/Image.cs @@ -11,7 +11,6 @@ namespace QuestPDF.Infrastructure { internal ImageSize Resolution { get; set; } internal ImageCompressionQuality CompressionQuality { get; set; } - internal ImageResizeStrategy ResizeStrategy { get; set; } } public class Image : IDisposable @@ -46,37 +45,11 @@ namespace QuestPDF.Infrastructure return cacheKey.image; } - var result = ResizeAndCompressImage(SkImage, request.Resolution, request.CompressionQuality); + var result = SkImage.ResizeAndCompressImage(request.Resolution, request.CompressionQuality); ScaledImageCache.AddLast((request, result)); return result; } - private static SKImage CompressImage(SKImage image, ImageCompressionQuality compressionQuality) - { - var targetFormat = image.Info.IsOpaque - ? SKEncodedImageFormat.Jpeg - : SKEncodedImageFormat.Png; - - if (targetFormat == SKEncodedImageFormat.Png) - compressionQuality = ImageCompressionQuality.Best; - - var data = image.Encode(targetFormat, compressionQuality.ToQualityValue()); - return SKImage.FromEncodedData(data); - } - - private static SKImage ResizeAndCompressImage(SKImage image, ImageSize targetResolution, ImageCompressionQuality compressionQuality) - { - if (image.Width == targetResolution.Width && image.Height == targetResolution.Height) - return CompressImage(image, compressionQuality); - - var imageInfo = new SKImageInfo(targetResolution.Width, targetResolution.Height); - - using var resultImage = SKImage.Create(imageInfo); - image.ScalePixels(resultImage.PeekPixels(), SKFilterQuality.Medium); - - return CompressImage(resultImage, compressionQuality); - } - #endregion #region public constructors diff --git a/Source/QuestPDF/Infrastructure/ImageResizeStrategy.cs b/Source/QuestPDF/Infrastructure/ImageResizeStrategy.cs deleted file mode 100644 index 290a24c..0000000 --- a/Source/QuestPDF/Infrastructure/ImageResizeStrategy.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace QuestPDF.Infrastructure -{ - public enum ImageResizeStrategy - { - // TODO: add comments - Always, - ScaleOnlyToSmallerResolution, - ScaleOnlyToSignificantlySmallerResolution, - Never - } -} \ No newline at end of file