Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 41ba1ac1ce | |||
| dc0a21b8e7 | |||
| 8a358a8fa2 | |||
| 1c9bccbeb2 |
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using QuestPDF.Drawing.Exceptions;
|
using QuestPDF.Drawing.Exceptions;
|
||||||
using QuestPDF.Examples.Engine;
|
using QuestPDF.Examples.Engine;
|
||||||
using QuestPDF.Fluent;
|
using QuestPDF.Fluent;
|
||||||
using QuestPDF.Helpers;
|
using QuestPDF.Helpers;
|
||||||
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
namespace QuestPDF.Examples
|
namespace QuestPDF.Examples
|
||||||
{
|
{
|
||||||
@@ -64,42 +66,24 @@ namespace QuestPDF.Examples
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ReusingTheSameImageFileShouldBePossible()
|
public void ImageResolutionScaling()
|
||||||
{
|
{
|
||||||
var fileName = Path.GetTempFileName() + ".jpg";
|
var image = Image.FromFile("large-image.jpg");
|
||||||
|
|
||||||
try
|
Document
|
||||||
{
|
.Create(document =>
|
||||||
var image = Placeholders.Image(300, 100);
|
{
|
||||||
|
document.Page(page =>
|
||||||
using var file = File.Create(fileName);
|
|
||||||
file.Write(image);
|
|
||||||
file.Dispose();
|
|
||||||
|
|
||||||
RenderingTest
|
|
||||||
.Create()
|
|
||||||
.ProducePdf()
|
|
||||||
.PageSize(PageSizes.A4)
|
|
||||||
.ShowResults()
|
|
||||||
.Render(container =>
|
|
||||||
{
|
{
|
||||||
container
|
page.Size(210, 210);
|
||||||
.Padding(20)
|
page.Margin(50);
|
||||||
.Column(column =>
|
page.Content().Image(image);
|
||||||
{
|
|
||||||
column.Spacing(20);
|
|
||||||
|
|
||||||
column.Item().Image(fileName);
|
|
||||||
column.Item().Image(fileName);
|
|
||||||
column.Item().Image(fileName);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
})
|
||||||
finally
|
.GeneratePdf($"test.pdf");
|
||||||
{
|
|
||||||
File.Delete(fileName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@@ -32,6 +32,12 @@
|
|||||||
<None Update="pdf-icon.svg">
|
<None Update="pdf-icon.svg">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="large-image.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="large-image.jpg">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
@@ -1,10 +1,16 @@
|
|||||||
using NUnit.Framework;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Mime;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
using QuestPDF.Drawing;
|
using QuestPDF.Drawing;
|
||||||
using QuestPDF.Elements;
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Fluent;
|
using QuestPDF.Fluent;
|
||||||
|
using QuestPDF.Helpers;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
using QuestPDF.UnitTests.TestEngine;
|
using QuestPDF.UnitTests.TestEngine;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
using Image = QuestPDF.Infrastructure.Image;
|
||||||
|
|
||||||
namespace QuestPDF.UnitTests
|
namespace QuestPDF.UnitTests
|
||||||
{
|
{
|
||||||
@@ -15,9 +21,9 @@ namespace QuestPDF.UnitTests
|
|||||||
public void Measure_TakesAvailableSpaceRegardlessOfSize()
|
public void Measure_TakesAvailableSpaceRegardlessOfSize()
|
||||||
{
|
{
|
||||||
TestPlan
|
TestPlan
|
||||||
.For(x => new Image
|
.For(x => new QuestPDF.Elements.Image
|
||||||
{
|
{
|
||||||
InternalImage = GenerateImage(400, 300)
|
DocumentImage = Image.FromSkImage(GenerateImage(400, 300))
|
||||||
})
|
})
|
||||||
.MeasureElement(new Size(300, 200))
|
.MeasureElement(new Size(300, 200))
|
||||||
.CheckMeasureResult(SpacePlan.FullRender(300, 200));
|
.CheckMeasureResult(SpacePlan.FullRender(300, 200));
|
||||||
@@ -27,9 +33,9 @@ namespace QuestPDF.UnitTests
|
|||||||
public void Draw_TakesAvailableSpaceRegardlessOfSize()
|
public void Draw_TakesAvailableSpaceRegardlessOfSize()
|
||||||
{
|
{
|
||||||
TestPlan
|
TestPlan
|
||||||
.For(x => new Image
|
.For(x => new QuestPDF.Elements.Image
|
||||||
{
|
{
|
||||||
InternalImage = GenerateImage(400, 300)
|
DocumentImage = Image.FromSkImage(GenerateImage(400, 300))
|
||||||
})
|
})
|
||||||
.DrawElement(new Size(300, 200))
|
.DrawElement(new Size(300, 200))
|
||||||
.ExpectCanvasDrawImage(new Position(0, 0), new Size(300, 200))
|
.ExpectCanvasDrawImage(new Position(0, 0), new Size(300, 200))
|
||||||
@@ -58,5 +64,53 @@ namespace QuestPDF.UnitTests
|
|||||||
using var surface = SKSurface.Create(imageInfo);
|
using var surface = SKSurface.Create(imageInfo);
|
||||||
return surface.Snapshot();
|
return surface.Snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void UsingSharedImageShouldNotDrasticallyIncreaseDocumentSize()
|
||||||
|
{
|
||||||
|
var placeholderImage = Placeholders.Image(1000, 200);
|
||||||
|
|
||||||
|
var documentWithSingleImageSize = GetDocumentSize(container =>
|
||||||
|
{
|
||||||
|
container.Image(placeholderImage);
|
||||||
|
});
|
||||||
|
|
||||||
|
var documentWithMultipleImagesSize = GetDocumentSize(container =>
|
||||||
|
{
|
||||||
|
container.Column(column =>
|
||||||
|
{
|
||||||
|
foreach (var i in Enumerable.Range(0, 100))
|
||||||
|
column.Item().Image(placeholderImage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var documentWithSingleImageUsedMultipleTimesSize = GetDocumentSize(container =>
|
||||||
|
{
|
||||||
|
container.Column(column =>
|
||||||
|
{
|
||||||
|
var sharedImage = Image.FromBinaryData(placeholderImage).DisposeAfterDocumentGeneration();
|
||||||
|
|
||||||
|
foreach (var i in Enumerable.Range(0, 100))
|
||||||
|
column.Item().Image(sharedImage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
(documentWithMultipleImagesSize / (float)documentWithSingleImageSize).Should().BeInRange(90, 100);
|
||||||
|
(documentWithSingleImageUsedMultipleTimesSize / (float)documentWithSingleImageSize).Should().BeInRange(1f, 1.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetDocumentSize(Action<IContainer> container)
|
||||||
|
{
|
||||||
|
return Document
|
||||||
|
.Create(document =>
|
||||||
|
{
|
||||||
|
document.Page(page =>
|
||||||
|
{
|
||||||
|
page.Content().Element(container);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.GeneratePdf()
|
||||||
|
.Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using QuestPDF.Elements.Text.Items;
|
|||||||
using QuestPDF.Fluent;
|
using QuestPDF.Fluent;
|
||||||
using QuestPDF.Helpers;
|
using QuestPDF.Helpers;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
|
using Image = QuestPDF.Elements.Image;
|
||||||
|
|
||||||
namespace QuestPDF.Drawing
|
namespace QuestPDF.Drawing
|
||||||
{
|
{
|
||||||
@@ -21,7 +22,7 @@ namespace QuestPDF.Drawing
|
|||||||
|
|
||||||
var metadata = document.GetMetadata();
|
var metadata = document.GetMetadata();
|
||||||
var canvas = new PdfCanvas(stream, metadata);
|
var canvas = new PdfCanvas(stream, metadata);
|
||||||
RenderDocument(canvas, document);
|
RenderDocument(canvas, document, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void GenerateXps(Stream stream, IDocument document)
|
internal static void GenerateXps(Stream stream, IDocument document)
|
||||||
@@ -30,7 +31,7 @@ namespace QuestPDF.Drawing
|
|||||||
|
|
||||||
var metadata = document.GetMetadata();
|
var metadata = document.GetMetadata();
|
||||||
var canvas = new XpsCanvas(stream, metadata);
|
var canvas = new XpsCanvas(stream, metadata);
|
||||||
RenderDocument(canvas, document);
|
RenderDocument(canvas, document, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckIfStreamIsCompatible(Stream stream)
|
private static void CheckIfStreamIsCompatible(Stream stream)
|
||||||
@@ -46,24 +47,26 @@ namespace QuestPDF.Drawing
|
|||||||
{
|
{
|
||||||
var metadata = document.GetMetadata();
|
var metadata = document.GetMetadata();
|
||||||
var canvas = new ImageCanvas(metadata);
|
var canvas = new ImageCanvas(metadata);
|
||||||
RenderDocument(canvas, document);
|
RenderDocument(canvas, document, metadata);
|
||||||
|
|
||||||
return canvas.Images;
|
return canvas.Images;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ICollection<PreviewerPicture> GeneratePreviewerPictures(IDocument document)
|
internal static ICollection<PreviewerPicture> GeneratePreviewerPictures(IDocument document)
|
||||||
{
|
{
|
||||||
|
var metadata = document.GetMetadata();
|
||||||
var canvas = new SkiaPictureCanvas();
|
var canvas = new SkiaPictureCanvas();
|
||||||
RenderDocument(canvas, document);
|
RenderDocument(canvas, document, metadata);
|
||||||
return canvas.Pictures;
|
return canvas.Pictures;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void RenderDocument<TCanvas>(TCanvas canvas, IDocument document)
|
internal static void RenderDocument<TCanvas>(TCanvas canvas, IDocument document, DocumentMetadata metadata)
|
||||||
where TCanvas : ICanvas, IRenderingCanvas
|
where TCanvas : ICanvas, IRenderingCanvas
|
||||||
{
|
{
|
||||||
var container = new DocumentContainer();
|
var container = new DocumentContainer();
|
||||||
document.Compose(container);
|
document.Compose(container);
|
||||||
var content = container.Compose();
|
var content = container.Compose();
|
||||||
|
ApplyDefaultImageDpi(content, metadata.RasterDpi);
|
||||||
ApplyDefaultTextStyle(content, TextStyle.LibraryDefault);
|
ApplyDefaultTextStyle(content, TextStyle.LibraryDefault);
|
||||||
ApplyContentDirection(content, ContentDirection.LeftToRight);
|
ApplyContentDirection(content, ContentDirection.LeftToRight);
|
||||||
|
|
||||||
@@ -173,6 +176,15 @@ namespace QuestPDF.Drawing
|
|||||||
|
|
||||||
return debuggingState;
|
return debuggingState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void ApplyDefaultImageDpi(this Element? content, int targetDpi)
|
||||||
|
{
|
||||||
|
content.VisitChildren(x =>
|
||||||
|
{
|
||||||
|
if (x is Image { DocumentImage: { } image })
|
||||||
|
image.TargetDpi ??= targetDpi;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
internal static void ApplyContentDirection(this Element? content, ContentDirection direction)
|
internal static void ApplyContentDirection(this Element? content, ContentDirection direction)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ namespace QuestPDF.Drawing
|
|||||||
{
|
{
|
||||||
public class DocumentMetadata
|
public class DocumentMetadata
|
||||||
{
|
{
|
||||||
|
public const int DefaultPdfDpi = 72;
|
||||||
|
|
||||||
public int ImageQuality { get; set; } = 101;
|
public int ImageQuality { get; set; } = 101;
|
||||||
public int RasterDpi { get; set; } = 72;
|
public int RasterDpi { get; set; } = DefaultPdfDpi;
|
||||||
public bool PdfA { get; set; }
|
public bool PdfA { get; set; }
|
||||||
|
|
||||||
public string? Title { get; set; }
|
public string? Title { get; set; }
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ namespace QuestPDF.Elements
|
|||||||
{
|
{
|
||||||
internal class Image : Element, ICacheable
|
internal class Image : Element, ICacheable
|
||||||
{
|
{
|
||||||
public SKImage? InternalImage { get; set; }
|
public Infrastructure.Image? DocumentImage { get; set; }
|
||||||
|
|
||||||
~Image()
|
~Image()
|
||||||
{
|
{
|
||||||
InternalImage?.Dispose();
|
if (DocumentImage is { IsDocumentScoped: true })
|
||||||
|
DocumentImage?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override SpacePlan Measure(Size availableSpace)
|
internal override SpacePlan Measure(Size availableSpace)
|
||||||
@@ -23,10 +24,10 @@ namespace QuestPDF.Elements
|
|||||||
|
|
||||||
internal override void Draw(Size availableSpace)
|
internal override void Draw(Size availableSpace)
|
||||||
{
|
{
|
||||||
if (InternalImage == null)
|
if (DocumentImage == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Canvas.DrawImage(InternalImage, Position.Zero, availableSpace);
|
Canvas.DrawImage(DocumentImage.GetVersionOfSize(availableSpace), Position.Zero, availableSpace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,6 @@ using System.IO;
|
|||||||
using QuestPDF.Drawing.Exceptions;
|
using QuestPDF.Drawing.Exceptions;
|
||||||
using QuestPDF.Elements;
|
using QuestPDF.Elements;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
using SkiaSharp;
|
|
||||||
|
|
||||||
namespace QuestPDF.Fluent
|
namespace QuestPDF.Fluent
|
||||||
{
|
{
|
||||||
@@ -11,30 +10,30 @@ namespace QuestPDF.Fluent
|
|||||||
{
|
{
|
||||||
public static void Image(this IContainer parent, byte[] imageData, ImageScaling scaling = ImageScaling.FitWidth)
|
public static void Image(this IContainer parent, byte[] imageData, ImageScaling scaling = ImageScaling.FitWidth)
|
||||||
{
|
{
|
||||||
var image = SKImage.FromEncodedData(imageData);
|
var image = Infrastructure.Image.FromBinaryData(imageData).DisposeAfterDocumentGeneration();
|
||||||
parent.Image(image, scaling);
|
parent.Image(image, scaling);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Image(this IContainer parent, string filePath, ImageScaling scaling = ImageScaling.FitWidth)
|
public static void Image(this IContainer parent, string filePath, ImageScaling scaling = ImageScaling.FitWidth)
|
||||||
{
|
{
|
||||||
var image = SKImage.FromEncodedData(filePath);
|
var image = Infrastructure.Image.FromFile(filePath).DisposeAfterDocumentGeneration();
|
||||||
parent.Image(image, scaling);
|
parent.Image(image, scaling);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Image(this IContainer parent, Stream fileStream, ImageScaling scaling = ImageScaling.FitWidth)
|
public static void Image(this IContainer parent, Stream fileStream, ImageScaling scaling = ImageScaling.FitWidth)
|
||||||
{
|
{
|
||||||
var image = SKImage.FromEncodedData(fileStream);
|
var image = Infrastructure.Image.FromStream(fileStream).DisposeAfterDocumentGeneration();
|
||||||
parent.Image(image, scaling);
|
parent.Image(image, scaling);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Image(this IContainer parent, SKImage image, ImageScaling scaling = ImageScaling.FitWidth)
|
public static void Image(this IContainer parent, Infrastructure.Image image, ImageScaling scaling = ImageScaling.FitWidth)
|
||||||
{
|
{
|
||||||
if (image == null)
|
if (image == null)
|
||||||
throw new DocumentComposeException("Cannot load or decode provided image.");
|
throw new DocumentComposeException("Cannot load or decode provided image.");
|
||||||
|
|
||||||
var imageElement = new Image
|
var imageElement = new QuestPDF.Elements.Image
|
||||||
{
|
{
|
||||||
InternalImage = image
|
DocumentImage = image
|
||||||
};
|
};
|
||||||
|
|
||||||
if (scaling != ImageScaling.Resize)
|
if (scaling != ImageScaling.Resize)
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using QuestPDF.Drawing;
|
||||||
|
using QuestPDF.Drawing.Exceptions;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace QuestPDF.Infrastructure
|
||||||
|
{
|
||||||
|
public class Image : IDisposable
|
||||||
|
{
|
||||||
|
private SKImage SkImage { get; }
|
||||||
|
internal List<(Size size, SKImage image)>? ScaledImageCache { get; set; }
|
||||||
|
|
||||||
|
internal int? TargetDpi { get; set; }
|
||||||
|
internal bool PerformScalingToTargetDpi { get; set; } = true;
|
||||||
|
internal bool IsDocumentScoped { get; set; }
|
||||||
|
|
||||||
|
public int Width => SkImage.Width;
|
||||||
|
public int Height => SkImage.Height;
|
||||||
|
|
||||||
|
private const float ImageSizeSimilarityToleranceMax = 1.1f;
|
||||||
|
private const float ImageSizeSimilarityToleranceMin = 1 / ImageSizeSimilarityToleranceMax;
|
||||||
|
|
||||||
|
private Image(SKImage image)
|
||||||
|
{
|
||||||
|
SkImage = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
SkImage.Dispose();
|
||||||
|
ScaledImageCache?.ForEach(x => x.image.Dispose());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal SKImage GetVersionOfSize(Size size)
|
||||||
|
{
|
||||||
|
if (!PerformScalingToTargetDpi)
|
||||||
|
return SkImage;
|
||||||
|
|
||||||
|
var scalingFactor = TargetDpi.Value / (float)DocumentMetadata.DefaultPdfDpi;
|
||||||
|
var targetResolution = new Size(size.Width * scalingFactor, size.Height * scalingFactor);
|
||||||
|
|
||||||
|
if (targetResolution.Width > Width || targetResolution.Height > Height)
|
||||||
|
return SkImage;
|
||||||
|
|
||||||
|
ScaledImageCache ??= new List<(Size size, SKImage image)>();
|
||||||
|
|
||||||
|
foreach (var imageCache in ScaledImageCache)
|
||||||
|
{
|
||||||
|
if (HasSimilarSize(imageCache.size, targetResolution))
|
||||||
|
return imageCache.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scaledImage = ScaleImage(SkImage, targetResolution);
|
||||||
|
ScaledImageCache.Add((targetResolution, scaledImage));
|
||||||
|
|
||||||
|
return scaledImage;
|
||||||
|
|
||||||
|
static SKImage ScaleImage(SKImage originalImage, Size targetSize)
|
||||||
|
{
|
||||||
|
var imageInfo = new SKImageInfo((int)targetSize.Width, (int)targetSize.Height);
|
||||||
|
var target = SKImage.Create(imageInfo);
|
||||||
|
originalImage.ScalePixels(target.PeekPixels(), SKFilterQuality.High);
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HasSimilarSize(Size a, Size b)
|
||||||
|
{
|
||||||
|
var widthRatio = a.Width / b.Width;
|
||||||
|
var heightRatio = a.Height / b.Height;
|
||||||
|
|
||||||
|
return widthRatio is > ImageSizeSimilarityToleranceMin and < ImageSizeSimilarityToleranceMax &&
|
||||||
|
heightRatio is > ImageSizeSimilarityToleranceMin and < ImageSizeSimilarityToleranceMax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region public constructors
|
||||||
|
|
||||||
|
internal static Image FromSkImage(SKImage image)
|
||||||
|
{
|
||||||
|
return CreateImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Image FromBinaryData(byte[] imageData)
|
||||||
|
{
|
||||||
|
return CreateImage(SKImage.FromEncodedData(imageData));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Image FromFile(string filePath)
|
||||||
|
{
|
||||||
|
return CreateImage(SKImage.FromEncodedData(filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Image FromStream(Stream fileStream)
|
||||||
|
{
|
||||||
|
return CreateImage(SKImage.FromEncodedData(fileStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Image CreateImage(SKImage? image)
|
||||||
|
{
|
||||||
|
if (image == null)
|
||||||
|
throw new DocumentComposeException("Cannot load or decode provided image.");
|
||||||
|
|
||||||
|
return new Image(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region configuration API
|
||||||
|
|
||||||
|
public Image DisposeAfterDocumentGeneration()
|
||||||
|
{
|
||||||
|
IsDocumentScoped = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image WithTargetDpi(int dpi = DocumentMetadata.DefaultPdfDpi)
|
||||||
|
{
|
||||||
|
TargetDpi = dpi;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image ScaleToTargetDpi(bool value = true)
|
||||||
|
{
|
||||||
|
PerformScalingToTargetDpi = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user